Print this page
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by:  Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by:  Evan Layton <evan.layton@nexenta.com>
NEX-5428 Backout the 5.0 changes
NEX-2937 Continuous write_same starves all other commands
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-5602 cpqary3: add support for more hp gen9 smart array controllers
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-1533 fcinfo hba-port doesn't get correct supported speeds and connection speed for 16Gb target ports
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-4532 STC comstar FC test causes panic on 5.0
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-3856 panic is occurred in module "fct" due to a NULL pointer dereference
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-2787 Multiple comstar / fibre channel / qlt threads stuck waiting on locks with a spinning interrupt thread
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Approved by: Jean McCormack <jean.mccormack@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/comstar/port/fct/fct.c
          +++ new/usr/src/uts/common/io/comstar/port/fct/fct.c
↓ open down ↓ 105 lines elided ↑ open up ↑
 106  106          MODREV_1,
 107  107          &modldrv,
 108  108          NULL
 109  109  };
 110  110  
 111  111  static uint32_t rportid_table_size = FCT_HASH_TABLE_SIZE;
 112  112  static int max_cached_ncmds = FCT_MAX_CACHED_CMDS;
 113  113  static fct_i_local_port_t *fct_iport_list = NULL;
 114  114  static kmutex_t fct_global_mutex;
 115  115  uint32_t fct_rscn_options = RSCN_OPTION_VERIFY;
      116 +/*
      117 + * This is to keep fibre channel from hanging if syseventd is
      118 + * not working correctly and the queue fills. It is a tunable
      119 + * to allow the user to force event logging to always happen
      120 + * which is the default.
      121 + */
      122 +static uint8_t fct_force_log = 0;  /* use DDI_SLEEP on ddi_log_sysevent */
 116  123  
      124 +/*
      125 + * For use during core examination. These counts are normally really low
      126 + * since they're bumped during port operations. If a customer core shows
      127 + * really high values without having an uptime of a year something is most
      128 + * likely wrong with their environment.
      129 + */
      130 +int fct_els_cnt = 0;
      131 +int fct_abort_cnt = 0;
      132 +
 117  133  int
 118  134  _init(void)
 119  135  {
 120  136          int ret;
 121  137  
 122  138          ret = mod_install(&modlinkage);
 123  139          if (ret)
 124  140                  return (ret);
 125  141          /* XXX */
 126  142          mutex_init(&fct_global_mutex, NULL, MUTEX_DRIVER, NULL);
↓ open down ↓ 1054 lines elided ↑ open up ↑
1181 1197          iport->iport_rp_slots = (fct_i_remote_port_t **)kmem_zalloc(
1182 1198              port->port_max_logins * sizeof (fct_i_remote_port_t *), KM_SLEEP);
1183 1199          iport->iport_rp_tb = kmem_zalloc(rportid_table_size *
1184 1200              sizeof (fct_i_remote_port_t *), KM_SLEEP);
1185 1201  
1186 1202          /* fct_cmds for SCSI traffic */
1187 1203          iport->iport_total_alloced_ncmds = 0;
1188 1204          iport->iport_cached_ncmds = 0;
1189 1205          port->port_fca_fcp_cmd_size =
1190 1206              (port->port_fca_fcp_cmd_size + 7) & ~7;
1191      -        iport->iport_cached_cmdlist = NULL;
     1207 +        list_create(&iport->iport_cached_cmdlist, sizeof (fct_i_cmd_t),
     1208 +            offsetof(fct_i_cmd_t, icmd_node));
     1209 +        list_create(&iport->iport_abort_queue, sizeof (fct_i_cmd_t),
     1210 +            offsetof(fct_i_cmd_t, icmd_node));
     1211 +
1192 1212          mutex_init(&iport->iport_cached_cmd_lock, NULL, MUTEX_DRIVER, NULL);
1193 1213  
1194 1214          /* Initialize cmd slots */
1195 1215          iport->iport_cmd_slots = (fct_cmd_slot_t *)kmem_zalloc(
1196 1216              port->port_max_xchges * sizeof (fct_cmd_slot_t), KM_SLEEP);
1197 1217          iport->iport_next_free_slot = 0;
1198 1218          for (i = 0; i < port->port_max_xchges; ) {
1199 1219                  slot = &iport->iport_cmd_slots[i];
1200 1220                  slot->slot_no = (uint16_t)i;
1201 1221                  slot->slot_next = (uint16_t)(++i);
↓ open down ↓ 68 lines elided ↑ open up ↑
1270 1290                  kmem_free(iport->iport_rp_tb, rportid_table_size *
1271 1291                      sizeof (fct_i_remote_port_t *));
1272 1292          }
1273 1293          return (FCT_FAILURE);
1274 1294  }
1275 1295  
1276 1296  fct_status_t
1277 1297  fct_deregister_local_port(fct_local_port_t *port)
1278 1298  {
1279 1299          fct_i_local_port_t      *iport;
1280      -        fct_i_cmd_t             *icmd, *next_icmd;
     1300 +        fct_i_cmd_t             *icmd;
1281 1301          int                     ndx;
1282 1302  
1283 1303          iport = (fct_i_local_port_t *)port->port_fct_private;
1284 1304  
1285 1305          if ((iport->iport_state != FCT_STATE_OFFLINE) ||
1286 1306              iport->iport_state_not_acked) {
1287 1307                  return (FCT_FAILURE);
1288 1308          }
1289 1309  
1290 1310          /* Stop the taskq 1st */
↓ open down ↓ 24 lines elided ↑ open up ↑
1315 1335          if (iport->iport_prev)
1316 1336                  iport->iport_prev->iport_next = iport->iport_next;
1317 1337          else
1318 1338                  fct_iport_list = iport->iport_next;
1319 1339          mutex_exit(&fct_global_mutex);
1320 1340          /*
1321 1341           * At this time, there should be no outstanding and pending
1322 1342           * I/Os, so we can just release resources.
1323 1343           */
1324 1344          ASSERT(iport->iport_total_alloced_ncmds == iport->iport_cached_ncmds);
1325      -        for (icmd = iport->iport_cached_cmdlist; icmd; icmd = next_icmd) {
1326      -                next_icmd = icmd->icmd_next;
1327      -                fct_free(icmd->icmd_cmd);
     1345 +        while (!list_is_empty(&iport->iport_cached_cmdlist)) {
     1346 +                icmd = list_remove_head(&iport->iport_cached_cmdlist);
     1347 +                fct_free(icmd);
1328 1348          }
1329 1349          mutex_destroy(&iport->iport_cached_cmd_lock);
1330 1350          kmem_free(iport->iport_cmd_slots, port->port_max_xchges *
1331 1351              sizeof (fct_cmd_slot_t));
1332 1352          kmem_free(iport->iport_rp_slots, port->port_max_logins *
1333 1353              sizeof (fct_i_remote_port_t *));
1334 1354          rw_destroy(&iport->iport_lock);
1335 1355          cv_destroy(&iport->iport_worker_cv);
1336 1356          sema_destroy(&iport->iport_rls_sema);
1337 1357          mutex_destroy(&iport->iport_worker_lock);
↓ open down ↓ 132 lines elided ↑ open up ↑
1470 1490  int
1471 1491  fct_is_irp_logging_out(fct_i_remote_port_t *irp, int force_implicit)
1472 1492  {
1473 1493          int logging_out = 0;
1474 1494  
1475 1495          rw_enter(&irp->irp_lock, RW_WRITER);
1476 1496          if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
1477 1497                  logging_out = 0;
1478 1498                  goto ilo_done;
1479 1499          }
1480      -        if ((irp->irp_els_list == NULL) && (irp->irp_deregister_timer)) {
     1500 +        if (list_is_empty(&irp->irp_els_list) && (irp->irp_deregister_timer)) {
1481 1501                  if (force_implicit && irp->irp_nonfcp_xchg_count) {
1482 1502                          logging_out = 0;
1483 1503                  } else {
1484 1504                          logging_out = 1;
1485 1505                  }
1486 1506                  goto ilo_done;
1487 1507          }
1488      -        if (irp->irp_els_list) {
     1508 +        if (!list_is_empty(&irp->irp_els_list)) {
1489 1509                  fct_i_cmd_t *icmd;
1490 1510                  /* Last session affecting ELS should be a LOGO */
1491      -                for (icmd = irp->irp_els_list; icmd; icmd = icmd->icmd_next) {
     1511 +                for (icmd = list_head(&irp->irp_els_list); icmd;
     1512 +                    icmd = list_next(&irp->irp_els_list, icmd)) {
1492 1513                          uint8_t op = (ICMD_TO_ELS(icmd))->els_req_payload[0];
1493 1514                          if (op == ELS_OP_LOGO) {
1494 1515                                  if (force_implicit) {
1495 1516                                          if (icmd->icmd_flags & ICMD_IMPLICIT)
1496 1517                                                  logging_out = 1;
1497 1518                                          else
1498 1519                                                  logging_out = 0;
1499 1520                                  } else {
1500 1521                                          logging_out = 1;
1501 1522                                  }
↓ open down ↓ 103 lines elided ↑ open up ↑
1605 1626                              irp->irp_nonfcp_xchg_count)
1606 1627                                  return (0);
1607 1628                          irp = irp->irp_next;
1608 1629                  }
1609 1630          }
1610 1631          return (1);
1611 1632  }
1612 1633  
1613 1634  fct_cmd_t *
1614 1635  fct_scsi_task_alloc(fct_local_port_t *port, uint16_t rp_handle,
1615      -    uint32_t rportid, uint8_t *lun, uint16_t cdb_length, uint16_t task_ext)
     1636 +    uint32_t rportid, uint8_t *lun, uint16_t cdb_length,
     1637 +    uint16_t task_ext)
1616 1638  {
1617 1639          fct_cmd_t *cmd;
1618 1640          fct_i_cmd_t *icmd;
1619 1641          fct_i_local_port_t *iport =
1620 1642              (fct_i_local_port_t *)port->port_fct_private;
1621 1643          fct_i_remote_port_t *irp;
1622 1644          scsi_task_t *task;
1623 1645          fct_remote_port_t *rp;
1624 1646          uint16_t cmd_slot;
1625 1647  
↓ open down ↓ 27 lines elided ↑ open up ↑
1653 1675          rw_enter(&irp->irp_lock, RW_READER);
1654 1676          if ((irp->irp_flags & IRP_PRLI_DONE) == 0) {
1655 1677                  rw_exit(&irp->irp_lock);
1656 1678                  rw_exit(&iport->iport_lock);
1657 1679                  stmf_trace(iport->iport_alias, "cmd alloc called while fcp "
1658 1680                      "login was not done. portid=%x, rp=%p", rp->rp_id, rp);
1659 1681                  return (NULL);
1660 1682          }
1661 1683  
1662 1684          mutex_enter(&iport->iport_cached_cmd_lock);
1663      -        if ((icmd = iport->iport_cached_cmdlist) != NULL) {
1664      -                iport->iport_cached_cmdlist = icmd->icmd_next;
     1685 +        if (!list_is_empty(&iport->iport_cached_cmdlist)) {
     1686 +                icmd = list_remove_head(&iport->iport_cached_cmdlist);
1665 1687                  iport->iport_cached_ncmds--;
1666 1688                  cmd = icmd->icmd_cmd;
1667 1689          } else {
1668 1690                  icmd = NULL;
1669 1691          }
1670 1692          mutex_exit(&iport->iport_cached_cmd_lock);
1671 1693          if (icmd == NULL) {
1672 1694                  cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_FCP_XCHG,
1673 1695                      port->port_fca_fcp_cmd_size, 0);
1674 1696                  if (cmd == NULL) {
1675 1697                          rw_exit(&irp->irp_lock);
1676 1698                          rw_exit(&iport->iport_lock);
1677 1699                          stmf_trace(iport->iport_alias, "Ran out of "
1678 1700                              "memory, port=%p", port);
1679 1701                          return (NULL);
1680 1702                  }
1681 1703  
1682 1704                  icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1683      -                icmd->icmd_next = NULL;
     1705 +                list_link_init(&icmd->icmd_node);
1684 1706                  cmd->cmd_port = port;
1685 1707                  atomic_inc_32(&iport->iport_total_alloced_ncmds);
1686 1708          }
1687 1709  
1688 1710          /*
1689 1711           * The accuracy of iport_max_active_ncmds is not important
1690 1712           */
1691 1713          if ((iport->iport_total_alloced_ncmds - iport->iport_cached_ncmds) >
1692 1714              iport->iport_max_active_ncmds) {
1693 1715                  iport->iport_max_active_ncmds =
↓ open down ↓ 183 lines elided ↑ open up ↑
1877 1899          return (cmd_slot);
1878 1900  }
1879 1901  
1880 1902  /*
1881 1903   * If icmd is not NULL, irp_lock must be held
1882 1904   */
1883 1905  void
1884 1906  fct_post_to_discovery_queue(fct_i_local_port_t *iport,
1885 1907      fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
1886 1908  {
1887      -        fct_i_cmd_t     **p;
1888      -
1889 1909          ASSERT(!MUTEX_HELD(&iport->iport_worker_lock));
1890 1910          if (icmd) {
1891      -                icmd->icmd_next = NULL;
1892      -                for (p = &irp->irp_els_list; *p != NULL;
1893      -                    p = &((*p)->icmd_next))
1894      -                        ;
1895      -
1896      -                *p = icmd;
     1911 +                list_insert_tail(&irp->irp_els_list, icmd);
     1912 +                fct_els_cnt++;
1897 1913                  atomic_or_32(&icmd->icmd_flags, ICMD_IN_IRP_QUEUE);
1898 1914          }
1899 1915  
1900 1916          mutex_enter(&iport->iport_worker_lock);
1901 1917          if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
1902 1918  
1903 1919                  /*
1904 1920                   * CAUTION: do not grab local_port/remote_port locks after
1905 1921                   * grabbing the worker lock.
1906 1922                   */
↓ open down ↓ 211 lines elided ↑ open up ↑
2118 2134                          fct_cmd_free(lcmd);
2119 2135                          cmd->cmd_link = NULL;
2120 2136                  }
2121 2137          }
2122 2138  
2123 2139          /* Free the cmd */
2124 2140          if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
2125 2141                  if (iport->iport_cached_ncmds < max_cached_ncmds) {
2126 2142                          icmd->icmd_flags = 0;
2127 2143                          mutex_enter(&iport->iport_cached_cmd_lock);
2128      -                        icmd->icmd_next = iport->iport_cached_cmdlist;
2129      -                        iport->iport_cached_cmdlist = icmd;
     2144 +                        list_insert_head(&iport->iport_cached_cmdlist, icmd);
2130 2145                          iport->iport_cached_ncmds++;
2131 2146                          mutex_exit(&iport->iport_cached_cmd_lock);
2132 2147                  } else {
2133 2148                          atomic_dec_32(&iport->iport_total_alloced_ncmds);
2134 2149                          fct_free(cmd);
2135 2150                  }
2136 2151          } else {
2137 2152                  fct_free(cmd);
2138 2153          }
2139 2154  }
↓ open down ↓ 682 lines elided ↑ open up ↑
2822 2837                      "s-%llx, iofalgs-%x", (void *)cmd, st, ioflags);
2823 2838                  (void) fct_port_shutdown(cmd->cmd_port,
2824 2839                      STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
2825 2840                  return;
2826 2841          }
2827 2842  
2828 2843          atomic_and_32(&icmd->icmd_flags, ~ICMD_KNOWN_TO_FCA);
2829 2844          /* For non FCP Rest of the work is done by the terminator */
2830 2845          /* For FCP stuff just call stmf */
2831 2846          if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
2832      -                stmf_task_lport_aborted((scsi_task_t *)cmd->cmd_specific,
2833      -                    s, STMF_IOF_LPORT_DONE);
     2847 +                stmf_task_lport_aborted_unlocked(
     2848 +                    (scsi_task_t *)cmd->cmd_specific, s, STMF_IOF_LPORT_DONE);
2834 2849          }
2835 2850  }
2836 2851  
2837 2852  /*
2838 2853   * FCA drivers will use it, when they want to abort some FC transactions
2839 2854   * due to lack of resource.
2840 2855   */
2841 2856  uint16_t
2842 2857  fct_get_rp_handle(fct_local_port_t *port, uint32_t rportid)
2843 2858  {
↓ open down ↓ 52 lines elided ↑ open up ↑
2896 2911          uint8_t *p;
2897 2912  
2898 2913          abts->abts_resp_rctl = BLS_OP_BA_ACC;
2899 2914          p = abts->abts_resp_payload;
2900 2915          bzero(p, 12);
2901 2916          *((uint16_t *)(p+4)) = BE_16(cmd->cmd_oxid);
2902 2917          *((uint16_t *)(p+6)) = BE_16(cmd->cmd_rxid);
2903 2918          p[10] = p[11] = 0xff;
2904 2919  }
2905 2920  
     2921 +/*
     2922 + * fct_cmd_unlink_els -- remove icmd from ELS queue
     2923 + *
     2924 + * The commands are found via the slot array of active commands and will be
     2925 + * terminated shortly after being removed.
     2926 + */
2906 2927  void
     2928 +fct_cmd_unlink_els(fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
     2929 +{
     2930 +        ASSERT(rw_write_held(&irp->irp_lock));
     2931 +        if (icmd->icmd_node.list_next) {
     2932 +                /*
     2933 +                 * Command is on two queues. Determine which queue and
     2934 +                 * handle appropriately.
     2935 +                 */
     2936 +                if (icmd->icmd_flags & ICMD_IN_IRP_QUEUE) {
     2937 +                        /*
     2938 +                         * If the command is active on the IRP queue it
     2939 +                         * will be freed during command termination
     2940 +                         * processing. Unfortuntely the ELS processing will
     2941 +                         * peek at the command and possibly panic if it's
     2942 +                         * been freed already. Remove it from the ELS
     2943 +                         * queue to avoid that.
     2944 +                         */
     2945 +                        if (icmd->icmd_flags & ICMD_SESSION_AFFECTING)
     2946 +                                atomic_dec_16(&irp->irp_sa_elses_count);
     2947 +                        else
     2948 +                                atomic_dec_16(&irp->irp_nsa_elses_count);
     2949 +                        atomic_and_32(&icmd->icmd_flags, ~ICMD_IN_IRP_QUEUE);
     2950 +                        list_remove(&irp->irp_els_list, icmd);
     2951 +                }
     2952 +                /*
     2953 +                 * There's an else case here, but the processing is handled
     2954 +                 * in fct_check_solcmd_queue(). In this case the command
     2955 +                 * is on the solicited queue and will be marked as aborted.
     2956 +                 * During command termination processing the command will be
     2957 +                 * marked as complete, but not freed. The freeing of the memory
     2958 +                 * is done in fct_check_solcmd_queue(). If that routine, which
     2959 +                 * holds the appropriate lock, is run first it will remove the
     2960 +                 * command from the abort queue so that no memory access
     2961 +                 * is done after the command has been freed.
     2962 +                 */
     2963 +        }
     2964 +}
     2965 +
     2966 +void
2907 2967  fct_handle_rcvd_abts(fct_cmd_t *cmd)
2908 2968  {
2909 2969          char                    info[FCT_INFO_LEN];
2910 2970          fct_local_port_t        *port = cmd->cmd_port;
2911 2971          fct_i_local_port_t      *iport =
2912 2972              (fct_i_local_port_t *)port->port_fct_private;
2913 2973          fct_i_cmd_t             *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
2914 2974          fct_i_remote_port_t     *irp;
2915      -        fct_cmd_t               *c = NULL;
     2975 +        fct_cmd_t               *c = NULL, *term_cmd;
2916 2976          fct_i_cmd_t             *ic = NULL;
2917 2977          int                     found = 0;
2918 2978          int                     i;
     2979 +        fct_status_t            term_val;
2919 2980  
2920 2981          icmd->icmd_start_time = ddi_get_lbolt();
2921 2982          icmd->icmd_flags |= ICMD_KNOWN_TO_FCA;
2922 2983  
2923 2984          rw_enter(&iport->iport_lock, RW_WRITER);
2924 2985          /* Make sure local port is sane */
2925 2986          if ((iport->iport_link_state & S_LINK_ONLINE) == 0) {
2926 2987                  rw_exit(&iport->iport_lock);
2927 2988                  stmf_trace(iport->iport_alias, "ABTS not posted becasue"
2928 2989                      "port state was %x", iport->iport_link_state);
↓ open down ↓ 62 lines elided ↑ open up ↑
2991 3052                              "ABTS_ACC port_send_cmd_response failed",
2992 3053                              (void *)iport);
2993 3054                          (void) fct_port_shutdown(iport->iport_port,
2994 3055                              STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
2995 3056                  } else {
2996 3057                          fct_cmd_free(cmd);
2997 3058                  }
2998 3059                  return;
2999 3060          }
3000 3061  
     3062 +        fct_cmd_unlink_els(irp, ic);
     3063 +
3001 3064          /* Check if this an abts retry */
3002 3065          if (c->cmd_link && (ic->icmd_flags & ICMD_ABTS_RECEIVED)) {
3003 3066                  /* Kill this abts. */
3004      -                fct_q_for_termination_lock_held(iport, icmd, FCT_ABORTED);
3005      -                if (IS_WORKER_SLEEPING(iport))
3006      -                        cv_signal(&iport->iport_worker_cv);
3007      -                mutex_exit(&iport->iport_worker_lock);
3008      -                rw_exit(&irp->irp_lock);
3009      -                rw_exit(&iport->iport_lock);
3010      -                return;
     3067 +                term_cmd = icmd->icmd_cmd;
     3068 +                term_val = FCT_ABORTED;
     3069 +        } else {
     3070 +                c->cmd_link = cmd;
     3071 +                atomic_or_32(&ic->icmd_flags, ICMD_ABTS_RECEIVED);
     3072 +                cmd->cmd_link = c;
     3073 +                term_cmd = c;
     3074 +                term_val = FCT_ABTS_RECEIVED;
3011 3075          }
3012      -        c->cmd_link = cmd;
3013      -        atomic_or_32(&ic->icmd_flags, ICMD_ABTS_RECEIVED);
3014      -        cmd->cmd_link = c;
3015 3076          mutex_exit(&iport->iport_worker_lock);
3016 3077          rw_exit(&irp->irp_lock);
3017      -        fct_queue_cmd_for_termination(c, FCT_ABTS_RECEIVED);
     3078 +        fct_queue_cmd_for_termination(term_cmd, term_val);
3018 3079          rw_exit(&iport->iport_lock);
3019 3080  }
3020 3081  
3021 3082  void
3022 3083  fct_queue_cmd_for_termination(fct_cmd_t *cmd, fct_status_t s)
3023 3084  {
3024 3085          fct_local_port_t *port = cmd->cmd_port;
3025 3086          fct_i_local_port_t *iport = (fct_i_local_port_t *)
3026 3087              port->port_fct_private;
3027 3088          fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
↓ open down ↓ 10 lines elided ↑ open up ↑
3038 3099  }
3039 3100  
3040 3101  /*
3041 3102   * This function will not be called for SCSI CMDS
3042 3103   */
3043 3104  void
3044 3105  fct_q_for_termination_lock_held(fct_i_local_port_t *iport, fct_i_cmd_t *icmd,
3045 3106      fct_status_t s)
3046 3107  {
3047 3108          uint32_t old, new;
3048      -        fct_i_cmd_t **ppicmd;
3049 3109  
3050 3110          do {
3051 3111                  old = icmd->icmd_flags;
3052 3112                  if (old & ICMD_BEING_ABORTED)
3053 3113                          return;
3054 3114                  new = old | ICMD_BEING_ABORTED;
3055 3115          } while (atomic_cas_32(&icmd->icmd_flags, old, new) != old);
3056 3116  
3057 3117          icmd->icmd_start_time = ddi_get_lbolt();
3058 3118          icmd->icmd_cmd->cmd_comp_status = s;
3059 3119  
3060      -        icmd->icmd_next = NULL;
3061      -        for (ppicmd = &(iport->iport_abort_queue); *ppicmd != NULL;
3062      -            ppicmd = &((*ppicmd)->icmd_next))
3063      -                ;
3064      -
3065      -        *ppicmd = icmd;
     3120 +        list_insert_tail(&iport->iport_abort_queue, icmd);
     3121 +        fct_abort_cnt++;
3066 3122  }
3067 3123  
3068 3124  /*
3069 3125   * For those cmds, for which we called fca_abort but it has not yet completed,
3070 3126   * reset the FCA_ABORT_CALLED flag, so that abort can be called again.
3071 3127   * This is done after a FCA offline. The reason is that after offline, the
3072 3128   * firmware is not running so abort will never complete. But if we call it
3073 3129   * again, the FCA will detect that it is not offline and it will
3074 3130   * not call the firmware at all. Most likely it will abort in a synchronous
3075 3131   * manner i.e. return FCT_ABORT_SUCCESS or FCT_NOT_FOUND.
↓ open down ↓ 158 lines elided ↑ open up ↑
3234 3290  /*
3235 3291   * Called by worker thread. The aim is to terminate the command
3236 3292   * using whatever means it takes.
3237 3293   * Called with worker lock held.
3238 3294   */
3239 3295  disc_action_t
3240 3296  fct_cmd_terminator(fct_i_local_port_t *iport)
3241 3297  {
3242 3298          char                    info[FCT_INFO_LEN];
3243 3299          clock_t                 endtime;
3244      -        fct_i_cmd_t             **ppicmd;
     3300 +        fct_i_cmd_t             *next;
3245 3301          fct_i_cmd_t             *icmd;
3246 3302          fct_cmd_t               *cmd;
3247 3303          fct_local_port_t        *port = iport->iport_port;
3248 3304          disc_action_t           ret = DISC_ACTION_NO_WORK;
3249 3305          fct_status_t            abort_ret;
3250 3306          int                     fca_done, fct_done, cmd_implicit = 0;
3251 3307          int                     flags;
3252 3308          unsigned long long      st;
3253 3309  
3254 3310          /* Lets Limit each run to 20ms max. */
3255 3311          endtime = ddi_get_lbolt() + drv_usectohz(20000);
3256 3312  
3257 3313          /* Start from where we left off last time */
3258 3314          if (iport->iport_ppicmd_term) {
3259      -                ppicmd = iport->iport_ppicmd_term;
     3315 +                icmd = iport->iport_ppicmd_term;
3260 3316                  iport->iport_ppicmd_term = NULL;
3261 3317          } else {
3262      -                ppicmd = &iport->iport_abort_queue;
     3318 +                icmd = list_head(&iport->iport_abort_queue);
3263 3319          }
3264 3320  
3265 3321          /*
3266 3322           * Once a command gets on discovery queue, this is the only thread
3267 3323           * which can access it. So no need for the lock here.
3268 3324           */
3269 3325          mutex_exit(&iport->iport_worker_lock);
3270 3326  
3271      -        while ((icmd = *ppicmd) != NULL) {
     3327 +        while (icmd) {
3272 3328                  cmd = icmd->icmd_cmd;
3273 3329  
3274 3330                  /* Always remember that cmd->cmd_rp can be NULL */
3275 3331                  if ((icmd->icmd_flags & (ICMD_KNOWN_TO_FCA |
3276 3332                      ICMD_FCA_ABORT_CALLED)) == ICMD_KNOWN_TO_FCA) {
3277 3333                          atomic_or_32(&icmd->icmd_flags, ICMD_FCA_ABORT_CALLED);
3278 3334                          if (CMD_HANDLE_VALID(cmd->cmd_handle))
3279 3335                                  flags = 0;
3280 3336                          else
3281 3337                                  flags = FCT_IOF_FORCE_FCA_DONE;
↓ open down ↓ 12 lines elided ↑ open up ↑
3294 3350                                              "fct_cmd_terminator:"
3295 3351                                              " iport-%p, port_abort_cmd with "
3296 3352                                              "FORCE_FCA_DONE failed",
3297 3353                                              (void *)iport);
3298 3354                                          (void) fct_port_shutdown(
3299 3355                                              iport->iport_port,
3300 3356                                              STMF_RFLAG_FATAL_ERROR |
3301 3357                                              STMF_RFLAG_RESET, info);
3302 3358  
3303 3359                                          mutex_enter(&iport->iport_worker_lock);
3304      -                                        iport->iport_ppicmd_term = ppicmd;
     3360 +                                        iport->iport_ppicmd_term = icmd;
3305 3361                                          return (DISC_ACTION_DELAY_RESCAN);
3306 3362                                  }
3307 3363                                  atomic_and_32(&icmd->icmd_flags,
3308 3364                                      ~ICMD_FCA_ABORT_CALLED);
3309 3365                          } else if ((flags & FCT_IOF_FORCE_FCA_DONE) ||
3310 3366                              (abort_ret == FCT_ABORT_SUCCESS) ||
3311 3367                              (abort_ret == FCT_NOT_FOUND)) {
3312 3368                                  atomic_and_32(&icmd->icmd_flags,
3313 3369                                      ~ICMD_KNOWN_TO_FCA);
3314 3370                          }
↓ open down ↓ 7 lines elided ↑ open up ↑
3322 3378                  if ((icmd->icmd_flags & ICMD_KNOWN_TO_FCA) == 0)
3323 3379                          fca_done = 1;
3324 3380                  else
3325 3381                          fca_done = 0;
3326 3382                  if ((icmd->icmd_flags & ICMD_IN_IRP_QUEUE) == 0)
3327 3383                          fct_done = 1;
3328 3384                  else
3329 3385                          fct_done = 0;
3330 3386                  if ((fca_done || cmd_implicit) && fct_done) {
3331 3387                          mutex_enter(&iport->iport_worker_lock);
3332      -                        ASSERT(*ppicmd == icmd);
3333      -                        *ppicmd = (*ppicmd)->icmd_next;
     3388 +                        next = list_next(&iport->iport_abort_queue, icmd);
     3389 +                        list_remove(&iport->iport_abort_queue, icmd);
3334 3390                          mutex_exit(&iport->iport_worker_lock);
     3391 +
3335 3392                          if ((cmd->cmd_type == FCT_CMD_RCVD_ELS) ||
3336 3393                              (cmd->cmd_type == FCT_CMD_RCVD_ABTS)) {
3337 3394                                  /* Free the cmd */
3338 3395                                  fct_cmd_free(cmd);
3339 3396                          } else if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
3340 3397                                  fct_handle_sol_els_completion(iport, icmd);
3341 3398                                  if (icmd->icmd_flags & ICMD_IMPLICIT) {
3342 3399                                          if (IS_LOGO_ELS(icmd)) {
3343 3400                                                  /* IMPLICIT LOGO is special */
3344 3401                                                  fct_cmd_free(cmd);
↓ open down ↓ 55 lines elided ↑ open up ↑
3400 3457                                  st = cmd->cmd_comp_status;      /* gcc fix */
3401 3458                                  (void) snprintf(info, sizeof (info),
3402 3459                                      "fct_cmd_terminator:"
3403 3460                                      " iport-%p, cmd_type(0x%s),"
3404 3461                                      " reason(%llx)", (void *)iport, cmd_type,
3405 3462                                      st);
3406 3463                                  (void) fct_port_shutdown(port,
3407 3464                                      STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
3408 3465                                      info);
3409 3466                          }
3410      -                        ppicmd = &((*ppicmd)->icmd_next);
     3467 +                        mutex_enter(&iport->iport_worker_lock);
     3468 +                        next = list_next(&iport->iport_abort_queue, icmd);
     3469 +                        mutex_exit(&iport->iport_worker_lock);
3411 3470                  }
3412 3471  
3413 3472                  if (ddi_get_lbolt() > endtime) {
3414 3473                          mutex_enter(&iport->iport_worker_lock);
3415      -                        iport->iport_ppicmd_term = ppicmd;
     3474 +                        iport->iport_ppicmd_term = next;
3416 3475                          return (DISC_ACTION_DELAY_RESCAN);
     3476 +                } else {
     3477 +                        icmd = next;
3417 3478                  }
3418 3479          }
3419 3480          mutex_enter(&iport->iport_worker_lock);
3420      -        if (iport->iport_abort_queue)
     3481 +        if (!list_is_empty(&iport->iport_abort_queue))
3421 3482                  return (DISC_ACTION_DELAY_RESCAN);
3422 3483          if (ret == DISC_ACTION_NO_WORK)
3423 3484                  return (DISC_ACTION_RESCAN);
3424 3485          return (ret);
3425 3486  }
3426 3487  
3427 3488  /*
3428 3489   * Send a syslog event for adapter port level events.
3429 3490   */
3430 3491  void
3431 3492  fct_log_local_port_event(fct_local_port_t *port, char *subclass)
3432 3493  {
3433 3494          nvlist_t *attr_list;
3434 3495          int port_instance;
     3496 +        int rc, sleep = DDI_SLEEP;
3435 3497  
3436 3498          if (!fct_dip)
3437 3499                  return;
3438 3500          port_instance = ddi_get_instance(fct_dip);
3439 3501  
3440 3502          if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE,
3441 3503              KM_SLEEP) != DDI_SUCCESS) {
3442 3504                  goto alloc_failed;
3443 3505          }
3444 3506  
3445 3507          if (nvlist_add_uint32(attr_list, "instance", port_instance)
3446 3508              != DDI_SUCCESS) {
3447 3509                  goto error;
3448 3510          }
3449 3511  
3450 3512          if (nvlist_add_byte_array(attr_list, "port-wwn",
3451 3513              port->port_pwwn, 8) != DDI_SUCCESS) {
3452 3514                  goto error;
3453 3515          }
3454 3516  
3455      -        (void) ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
3456      -            subclass, attr_list, NULL, DDI_SLEEP);
     3517 +        if (fct_force_log == 0) {
     3518 +                sleep = DDI_NOSLEEP;
     3519 +        }
     3520 +        rc = ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
     3521 +            subclass, attr_list, NULL, sleep);
     3522 +        if (rc != DDI_SUCCESS) {
     3523 +                cmn_err(CE_WARN, "%s: queue full event lost", __func__);
     3524 +                goto error;
     3525 +        }
3457 3526  
3458 3527          nvlist_free(attr_list);
3459 3528          return;
3460 3529  
3461 3530  error:
3462 3531          nvlist_free(attr_list);
3463 3532  alloc_failed:
3464 3533          stmf_trace(((fct_i_local_port_t *)port->port_fct_private)->iport_alias,
3465 3534              "Unable to send %s event", subclass);
3466 3535  }
3467 3536  
3468 3537  void
3469 3538  fct_log_remote_port_event(fct_local_port_t *port, char *subclass,
3470 3539      uint8_t *rp_pwwn, uint32_t rp_id)
3471 3540  {
3472 3541          nvlist_t *attr_list;
3473 3542          int port_instance;
     3543 +        int rc, sleep = DDI_SLEEP;
3474 3544  
3475 3545          if (!fct_dip)
3476 3546                  return;
3477 3547          port_instance = ddi_get_instance(fct_dip);
3478 3548  
3479 3549          if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE,
3480 3550              KM_SLEEP) != DDI_SUCCESS) {
3481 3551                  goto alloc_failed;
3482 3552          }
3483 3553  
↓ open down ↓ 10 lines elided ↑ open up ↑
3494 3564          if (nvlist_add_byte_array(attr_list, "target-port-wwn",
3495 3565              rp_pwwn, 8) != DDI_SUCCESS) {
3496 3566                  goto error;
3497 3567          }
3498 3568  
3499 3569          if (nvlist_add_uint32(attr_list, "target-port-id",
3500 3570              rp_id) != DDI_SUCCESS) {
3501 3571                  goto error;
3502 3572          }
3503 3573  
3504      -        (void) ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
3505      -            subclass, attr_list, NULL, DDI_SLEEP);
     3574 +        if (fct_force_log == 0) {
     3575 +                sleep = DDI_NOSLEEP;
     3576 +        }
     3577 +        rc = ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
     3578 +            subclass, attr_list, NULL, sleep);
     3579 +        if (rc != DDI_SUCCESS) {
     3580 +                cmn_err(CE_WARN, "%s:event dropped", __func__);
     3581 +                goto error;
     3582 +        }
3506 3583  
3507 3584          nvlist_free(attr_list);
3508 3585          return;
3509 3586  
3510 3587  error:
3511 3588          nvlist_free(attr_list);
3512 3589  alloc_failed:
3513 3590          stmf_trace(((fct_i_local_port_t *)port->port_fct_private)->iport_alias,
3514 3591              "Unable to send %s event", subclass);
3515 3592  }
↓ open down ↓ 116 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX