Print this page
NEX-10223 Return of Fibre Channel ports stuck in offline state and unable to clear
Reviewed by: Evan Layton <evan.layton@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-3277 Panic of both nodes in failover time (FC clients)
        Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
        Reviewed by: Gordon Ross <gordon.ross@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/discovery.c
          +++ new/usr/src/uts/common/io/comstar/port/fct/discovery.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  23   24   */
  24   25  
  25   26  #include <sys/sysmacros.h>
  26   27  #include <sys/conf.h>
  27   28  #include <sys/file.h>
  28   29  #include <sys/ddi.h>
  29   30  #include <sys/sunddi.h>
  30   31  #include <sys/modctl.h>
  31   32  #include <sys/scsi/scsi.h>
  32   33  #include <sys/scsi/impl/scsi_reset_notify.h>
↓ open down ↓ 106 lines elided ↑ open up ↑
 139  140                   */
 140  141                  if ((iport->iport_link_state == PORT_STATE_LINK_INIT_START) &&
 141  142                      !(iport->iport_li_state & (LI_STATE_FLAG_CMD_WAITING |
 142  143                      LI_STATE_FLAG_NO_LI_YET))) {
 143  144                          suggested_action |= fct_process_link_init(iport);
 144  145                  }
 145  146  
 146  147                  /*
 147  148                   * We process cmd aborting in the end
 148  149                   */
 149      -                if (iport->iport_abort_queue) {
      150 +                if (!list_is_empty(&iport->iport_abort_queue)) {
 150  151                          suggested_action |= fct_cmd_terminator(iport);
 151  152                  }
 152  153  
 153  154                  /*
 154  155                   * Check cmd max/free
 155  156                   */
 156  157                  if (iport->iport_cmdcheck_clock <= ddi_get_lbolt()) {
 157  158                          suggested_action |= fct_check_cmdlist(iport);
 158  159                          iport->iport_cmdcheck_clock = ddi_get_lbolt() +
 159  160                              drv_usectohz(FCT_CMDLIST_CHECK_SECONDS * 1000000);
↓ open down ↓ 454 lines elided ↑ open up ↑
 614  615                                              " ret=%llx, forcing link down",
 615  616                                              iport->iport_li_comp_status);
 616  617                                          mutex_exit(&iport->iport_worker_lock);
 617  618                                          fct_handle_event(iport->iport_port,
 618  619                                              FCT_EVENT_LINK_DOWN, 0, 0);
 619  620                                          mutex_enter(&iport->iport_worker_lock);
 620  621                                  }
 621  622                          }
 622  623                  }
 623  624                  /* Find out if we need to do PLOGI at all */
      625 +                rw_enter(&iport->iport_lock, RW_READER);
 624  626                  if (iport->iport_nrps_login) {
 625  627                          iport->iport_li_state++;
 626  628                          atomic_and_32(&iport->iport_flags,
 627  629                              ~IPORT_ALLOW_UNSOL_FLOGI);
      630 +                        rw_exit(&iport->iport_lock);
 628  631                          goto check_state_again;
      632 +                } else {
      633 +                        rw_exit(&iport->iport_lock);
 629  634                  }
 630  635                  if ((ddi_get_lbolt() >= iport->iport_li_cmd_timeout) &&
 631  636                      (!fct_lport_has_bigger_wwn(iport))) {
 632  637                          /* Cant wait forever */
 633  638                          stmf_trace(iport->iport_alias, "N2N: Remote port is "
 634  639                              "not logging in, forcing from our side");
 635  640                          force_login = 1;
 636  641                  } else {
 637  642                          force_login = 0;
 638  643                  }
↓ open down ↓ 263 lines elided ↑ open up ↑
 902  907                          /* drop the lock while we do allocations */
 903  908                          rw_exit(&iport->iport_lock);
 904  909                          rp = fct_alloc(FCT_STRUCT_REMOTE_PORT,
 905  910                              port->port_fca_rp_private_size, 0);
 906  911                          if (rp == NULL) {
 907  912                                  fct_queue_cmd_for_termination(cmd,
 908  913                                      FCT_ALLOC_FAILURE);
 909  914                                  return;
 910  915                          }
 911  916                          irp = (fct_i_remote_port_t *)rp->rp_fct_private;
      917 +                        list_create(&irp->irp_els_list, sizeof (fct_i_cmd_t),
      918 +                            offsetof(fct_i_cmd_t, icmd_node));
 912  919                          rw_init(&irp->irp_lock, 0, RW_DRIVER, 0);
 913  920                          irp->irp_rp = rp;
 914  921                          irp->irp_portid = cmd->cmd_rportid;
 915  922                          rp->rp_port = port;
 916  923                          rp->rp_id = cmd->cmd_rportid;
 917  924                          rp->rp_handle = FCT_HANDLE_NONE;
 918  925                          /*
 919  926                           * Grab port lock as writer since we are going
 920  927                           * to modify the local port struct.
 921  928                           */
↓ open down ↓ 58 lines elided ↑ open up ↑
 980  987          } else {
 981  988                  /*
 982  989                   * Tell the framework that fct_cmd_free() can decrement the
 983  990                   * irp_nonfcp_xchg_count variable.
 984  991                   */
 985  992                  atomic_or_32(&icmd->icmd_flags, ICMD_IMPLICIT_CMD_HAS_RESOURCE);
 986  993          }
 987  994          atomic_inc_16(&irp->irp_nonfcp_xchg_count);
 988  995  
 989  996          /*
      997 +         * The iport_lock is currently held as a Reader lock, protocol
      998 +         * dictates that to modify iport_nrps_login the lock must be held
      999 +         * as a Writer.
     1000 +         */
     1001 +        rw_exit(&iport->iport_lock);
     1002 +        rw_enter(&iport->iport_lock, RW_WRITER);
     1003 +
     1004 +        /*
 990 1005           * Grab the remote port lock while we modify the port state.
 991 1006           * we should not drop the fca port lock (as a reader) until we
 992 1007           * modify the remote port state.
 993 1008           */
 994 1009          rw_enter(&irp->irp_lock, RW_WRITER);
 995 1010          if ((op == ELS_OP_PLOGI) || (op == ELS_OP_PRLI) ||
 996 1011              (op == ELS_OP_LOGO) || (op == ELS_OP_PRLO) ||
 997 1012              (op == ELS_OP_TPRLO)) {
 998 1013                  uint32_t rf = IRP_PRLI_DONE;
 999 1014                  if ((op == ELS_OP_PLOGI) || (op == ELS_OP_LOGO)) {
↓ open down ↓ 50 lines elided ↑ open up ↑
1050 1065                          unhandled++;
1051 1066                          continue;
1052 1067                  }
1053 1068  
1054 1069                  cmd = icmd->icmd_cmd;
1055 1070                  if (cmd->cmd_rp != rp) {
1056 1071                          skipped++;
1057 1072                          continue;
1058 1073                  }
1059 1074                  if (cmd->cmd_type & ttc) {
1060      -                        if (cmd->cmd_type == FCT_CMD_FCP_XCHG)
     1075 +                        if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
1061 1076                                  fct_queue_scsi_task_for_termination(cmd,
1062 1077                                      FCT_ABORTED);
1063      -                        else
     1078 +                        } else {
     1079 +                                fct_cmd_unlink_els(irp, icmd);
1064 1080                                  fct_q_for_termination_lock_held(iport, icmd,
1065 1081                                      FCT_ABORTED);
     1082 +                        }
1066 1083                          cleaned++;
1067 1084                  } else {
1068 1085                          skipped++;
1069 1086                  }
1070 1087          }
1071 1088          if (((cleaned + skipped) == total) && (unhandled == 0)) {
1072 1089                  ret = 1;
1073 1090          } else {
1074 1091                  /*
1075 1092                   * XXX: handle this situation.
↓ open down ↓ 10 lines elided ↑ open up ↑
1086 1103          rw_exit(&iport->iport_lock);
1087 1104          return (ret);
1088 1105  }
1089 1106  
1090 1107  void
1091 1108  fct_dequeue_els(fct_i_remote_port_t *irp)
1092 1109  {
1093 1110          fct_i_cmd_t *icmd;
1094 1111  
1095 1112          rw_enter(&irp->irp_lock, RW_WRITER);
1096      -        icmd = irp->irp_els_list;
1097      -        irp->irp_els_list = icmd->icmd_next;
     1113 +        icmd = list_remove_head(&irp->irp_els_list);
1098 1114          atomic_and_32(&icmd->icmd_flags, ~ICMD_IN_IRP_QUEUE);
1099 1115          rw_exit(&irp->irp_lock);
1100 1116  }
1101 1117  
1102 1118  fct_status_t
1103 1119  fct_register_remote_port(fct_local_port_t *port, fct_remote_port_t *rp,
1104 1120                                  fct_cmd_t *cmd)
1105 1121  {
1106 1122          fct_status_t ret;
1107 1123          fct_i_local_port_t      *iport;
↓ open down ↓ 74 lines elided ↑ open up ↑
1182 1198  }
1183 1199  
1184 1200  fct_status_t
1185 1201  fct_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
1186 1202  {
1187 1203          fct_status_t             ret   = FCT_SUCCESS;
1188 1204          fct_i_local_port_t      *iport = PORT_TO_IPORT(port);
1189 1205          fct_i_remote_port_t     *irp   = RP_TO_IRP(rp);
1190 1206  
1191 1207          if (irp->irp_snn) {
1192      -                kmem_free(irp->irp_snn, strlen(irp->irp_snn) + 1);
     1208 +                kmem_free(irp->irp_snn, irp->irp_snn_len);
1193 1209                  irp->irp_snn = NULL;
     1210 +                irp->irp_snn_len = 0;
1194 1211          }
1195 1212          if (irp->irp_spn) {
1196      -                kmem_free(irp->irp_spn, strlen(irp->irp_spn) + 1);
     1213 +                kmem_free(irp->irp_spn, irp->irp_spn_len);
1197 1214                  irp->irp_spn = NULL;
     1215 +                irp->irp_spn_len = 0;
1198 1216          }
1199 1217  
1200 1218          if ((ret = port->port_deregister_remote_port(port, rp)) !=
1201 1219              FCT_SUCCESS) {
1202 1220                  return (ret);
1203 1221          }
1204 1222  
1205 1223          if (irp->irp_flags & IRP_HANDLE_OPENED) {
1206 1224                  atomic_and_32(&irp->irp_flags, ~IRP_HANDLE_OPENED);
1207 1225                  iport->iport_rp_slots[rp->rp_handle] = NULL;
↓ open down ↓ 34 lines elided ↑ open up ↑
1242 1260          disc_action_t           suggested_action = DISC_ACTION_NO_WORK;
1243 1261          fct_i_remote_port_t     *irp_dereg_list = NULL;
1244 1262          fct_i_remote_port_t     *irp_cur_item = NULL;
1245 1263  
1246 1264          for (pirp = &iport->iport_rpwe_head; *pirp != NULL; ) {
1247 1265                  fct_i_remote_port_t *irp = *pirp;
1248 1266                  disc_action_t ret = DISC_ACTION_NO_WORK;
1249 1267                  int do_deregister = 0;
1250 1268                  int irp_deregister_timer = 0;
1251 1269  
1252      -                if (irp->irp_els_list) {
     1270 +                if (!list_is_empty(&irp->irp_els_list)) {
1253 1271                          ret |= fct_process_els(iport, irp);
1254 1272                  }
1255 1273  
1256 1274                  irp_deregister_timer = irp->irp_deregister_timer;
1257 1275                  if (irp_deregister_timer) {
1258 1276                          if (ddi_get_lbolt() >= irp_deregister_timer) {
1259 1277                                  do_deregister = 1;
1260 1278                          } else {
1261 1279                                  ret |= DISC_ACTION_DELAY_RESCAN;
1262 1280                          }
1263 1281                  }
1264 1282                  suggested_action |= ret;
1265 1283  
1266      -                if (irp->irp_els_list == NULL) {
     1284 +                if (list_is_empty(&irp->irp_els_list)) {
1267 1285                          mutex_exit(&iport->iport_worker_lock);
1268 1286                          rw_enter(&iport->iport_lock, RW_WRITER);
1269 1287                          rw_enter(&irp->irp_lock, RW_WRITER);
1270 1288                          mutex_enter(&iport->iport_worker_lock);
1271      -                        if (irp->irp_els_list == NULL) {
     1289 +                        if (list_is_empty(&irp->irp_els_list)) {
1272 1290                                  if (!irp_deregister_timer ||
1273 1291                                      (do_deregister &&
1274 1292                                      !irp->irp_sa_elses_count &&
1275 1293                                      !irp->irp_nsa_elses_count &&
1276 1294                                      !irp->irp_fcp_xchg_count &&
1277 1295                                      !irp->irp_nonfcp_xchg_count)) {
1278 1296                                          /* dequeue irp from discovery queue */
1279 1297                                          atomic_and_32(&irp->irp_flags,
1280 1298                                              ~IRP_IN_DISCOVERY_QUEUE);
1281 1299                                          *pirp = irp->irp_discovery_next;
↓ open down ↓ 227 lines elided ↑ open up ↑
1509 1527                                      ~ICMD_KNOWN_TO_FCA);
1510 1528                                  atomic_and_32(&irp->irp_flags,
1511 1529                                      ~IRP_SOL_PLOGI_IN_PROGRESS);
1512 1530                          }
1513 1531                  }
1514 1532          }
1515 1533          atomic_dec_16(&irp->irp_sa_elses_count);
1516 1534  
1517 1535          if (ret == FCT_SUCCESS) {
1518 1536                  if (cmd_type == FCT_CMD_RCVD_ELS) {
     1537 +                        rw_enter(&iport->iport_lock, RW_WRITER);
     1538 +                        rw_enter(&irp->irp_lock, RW_WRITER);
1519 1539                          atomic_or_32(&irp->irp_flags, IRP_PLOGI_DONE);
1520 1540                          atomic_inc_32(&iport->iport_nrps_login);
1521 1541                          if (irp->irp_deregister_timer)
1522 1542                                  irp->irp_deregister_timer = 0;
     1543 +                        rw_exit(&irp->irp_lock);
     1544 +                        rw_exit(&iport->iport_lock);
1523 1545                  }
1524 1546                  if (icmd_flags & ICMD_IMPLICIT) {
1525 1547                          DTRACE_FC_5(rport__login__end,
1526 1548                              fct_cmd_t, cmd,
1527 1549                              fct_local_port_t, port,
1528 1550                              fct_i_remote_port_t, irp,
1529 1551                              int, (cmd_type != FCT_CMD_RCVD_ELS),
1530 1552                              int, FCT_SUCCESS);
1531 1553  
1532 1554                          p = els->els_resp_payload;
↓ open down ↓ 462 lines elided ↑ open up ↑
1995 2017          } else {
1996 2018                  ASSERT(0);
1997 2019          }
1998 2020  
1999 2021          return (DISC_ACTION_RESCAN);
2000 2022  }
2001 2023  
2002 2024  disc_action_t
2003 2025  fct_process_els(fct_i_local_port_t *iport, fct_i_remote_port_t *irp)
2004 2026  {
2005      -        fct_i_cmd_t     *cmd_to_abort = NULL;
2006      -        fct_i_cmd_t     **ppcmd, *icmd;
     2027 +        list_t          cmd_to_abort;
     2028 +        fct_i_cmd_t     *next, *icmd;
2007 2029          fct_cmd_t       *cmd;
2008 2030          fct_els_t       *els;
2009 2031          int             dq;
2010 2032          disc_action_t   ret = DISC_ACTION_NO_WORK;
2011 2033          uint8_t         op;
2012 2034  
2013 2035          mutex_exit(&iport->iport_worker_lock);
2014 2036  
2015 2037          /*
2016 2038           * Do some cleanup based on the following.
2017 2039           * - We can only have one session affecting els pending.
2018 2040           * - If any session affecting els is pending no other els is allowed.
2019 2041           * - If PLOGI is not done, nothing except PLOGI or LOGO is allowed.
2020 2042           * NOTE: If port is down the cleanup is done outside of this
2021 2043           *      function.
2022 2044           * NOTE: There is a side effect, if a sa ELS (non PLOGI) is received
2023 2045           * while a PLOGI is pending, it will kill itself and the PLOGI.
2024 2046           * which is probably ok.
2025 2047           */
2026 2048          rw_enter(&irp->irp_lock, RW_WRITER);
2027      -        ppcmd = &irp->irp_els_list;
2028      -        while ((*ppcmd) != NULL) {
     2049 +        icmd = list_head(&irp->irp_els_list);
     2050 +        list_create(&cmd_to_abort, sizeof (fct_i_cmd_t),
     2051 +            offsetof(fct_i_cmd_t, icmd_node));
     2052 +        while (icmd != NULL) {
2029 2053                  int special_prli_cond = 0;
2030 2054                  dq = 0;
2031 2055  
2032      -                els = (fct_els_t *)((*ppcmd)->icmd_cmd)->cmd_specific;
     2056 +                els = (fct_els_t *)(icmd->icmd_cmd)->cmd_specific;
2033 2057  
2034      -                if (((*ppcmd)->icmd_cmd->cmd_type == FCT_CMD_RCVD_ELS) &&
     2058 +                if ((icmd->icmd_cmd->cmd_type == FCT_CMD_RCVD_ELS) &&
2035 2059                      (els->els_req_payload[0] == ELS_OP_PRLI) &&
2036 2060                      (irp->irp_flags & IRP_SOL_PLOGI_IN_PROGRESS)) {
2037 2061                          /*
2038 2062                           * The initiator sent a PRLI right after responding
2039 2063                           * to PLOGI and we have not yet finished processing
2040 2064                           * the PLOGI completion. We should not kill the PRLI
2041 2065                           * as the initiator may not retry it.
2042 2066                           */
2043 2067                          special_prli_cond = 1;
2044 2068                  }
2045 2069  
2046      -                if ((*ppcmd)->icmd_flags & ICMD_BEING_ABORTED) {
     2070 +                if (icmd->icmd_flags & ICMD_BEING_ABORTED) {
2047 2071                          dq = 1;
2048 2072                  } else if (irp->irp_sa_elses_count > 1) {
2049 2073                          dq = 1;
2050 2074                          /* This els might have set the CLEANUP flag */
2051 2075                          atomic_and_32(&irp->irp_flags, ~IRP_SESSION_CLEANUP);
2052 2076                          stmf_trace(iport->iport_alias, "Killing ELS %x cond 1",
2053 2077                              els->els_req_payload[0]);
2054 2078                  } else if (irp->irp_sa_elses_count &&
2055      -                    (((*ppcmd)->icmd_flags & ICMD_SESSION_AFFECTING) == 0)) {
     2079 +                    ((icmd->icmd_flags & ICMD_SESSION_AFFECTING) == 0)) {
2056 2080                          stmf_trace(iport->iport_alias, "Killing ELS %x cond 2",
2057 2081                              els->els_req_payload[0]);
2058 2082                          dq = 1;
2059 2083                  } else if (((irp->irp_flags & IRP_PLOGI_DONE) == 0) &&
2060 2084                      (els->els_req_payload[0] != ELS_OP_PLOGI) &&
2061 2085                      (els->els_req_payload[0] != ELS_OP_LOGO) &&
2062 2086                      (special_prli_cond == 0)) {
2063 2087                          stmf_trace(iport->iport_alias, "Killing ELS %x cond 3",
2064 2088                              els->els_req_payload[0]);
2065 2089                          dq = 1;
2066 2090                  }
2067 2091  
     2092 +                next = list_next(&irp->irp_els_list, icmd);
2068 2093                  if (dq) {
2069      -                        fct_i_cmd_t *c = (*ppcmd)->icmd_next;
2070      -
2071      -                        if ((*ppcmd)->icmd_flags & ICMD_SESSION_AFFECTING)
     2094 +                        list_remove(&irp->irp_els_list, icmd);
     2095 +                        if (icmd->icmd_flags & ICMD_SESSION_AFFECTING)
2072 2096                                  atomic_dec_16(&irp->irp_sa_elses_count);
2073 2097                          else
2074 2098                                  atomic_dec_16(&irp->irp_nsa_elses_count);
2075      -                        (*ppcmd)->icmd_next = cmd_to_abort;
2076      -                        cmd_to_abort = *ppcmd;
2077      -                        *ppcmd = c;
2078      -                } else {
2079      -                        ppcmd = &((*ppcmd)->icmd_next);
     2099 +                        list_insert_head(&cmd_to_abort, icmd);
2080 2100                  }
     2101 +                icmd = next;
2081 2102          }
2082 2103          rw_exit(&irp->irp_lock);
2083 2104  
2084      -        while (cmd_to_abort) {
2085      -                fct_i_cmd_t *c = cmd_to_abort->icmd_next;
     2105 +        while (!list_is_empty(&cmd_to_abort)) {
     2106 +                fct_i_cmd_t *c = list_remove_head(&cmd_to_abort);
2086 2107  
2087      -                atomic_and_32(&cmd_to_abort->icmd_flags, ~ICMD_IN_IRP_QUEUE);
2088      -                fct_queue_cmd_for_termination(cmd_to_abort->icmd_cmd,
2089      -                    FCT_ABORTED);
2090      -                cmd_to_abort = c;
     2108 +                atomic_and_32(&c->icmd_flags, ~ICMD_IN_IRP_QUEUE);
     2109 +                fct_queue_cmd_for_termination(c->icmd_cmd, FCT_ABORTED);
2091 2110          }
2092 2111  
2093 2112          /*
2094 2113           * pick from the top of the queue
2095 2114           */
2096      -        icmd = irp->irp_els_list;
     2115 +        icmd = list_head(&irp->irp_els_list);
2097 2116          if (icmd == NULL) {
2098 2117                  /*
2099 2118                   * The cleanup took care of everything.
2100 2119                   */
2101 2120  
2102 2121                  mutex_enter(&iport->iport_worker_lock);
2103 2122                  return (DISC_ACTION_RESCAN);
2104 2123          }
2105 2124  
2106 2125          cmd = icmd->icmd_cmd;
↓ open down ↓ 65 lines elided ↑ open up ↑
2172 2191                  irp = ICMD_TO_IRP(icmd);
2173 2192          }
2174 2193          if (icmd->icmd_cmd->cmd_rp &&
2175 2194              (icmd->icmd_cmd->cmd_comp_status == FCT_SUCCESS) &&
2176 2195              (els->els_req_payload[0] == ELS_OP_PLOGI)) {
2177 2196                  bcopy(els->els_resp_payload + 20, irp->irp_rp->rp_pwwn, 8);
2178 2197                  bcopy(els->els_resp_payload + 28, irp->irp_rp->rp_nwwn, 8);
2179 2198  
2180 2199                  stmf_wwn_to_devid_desc((scsi_devid_desc_t *)irp->irp_id,
2181 2200                      irp->irp_rp->rp_pwwn, PROTOCOL_FIBRE_CHANNEL);
     2201 +                rw_enter(&iport->iport_lock, RW_WRITER);
     2202 +                rw_enter(&irp->irp_lock, RW_WRITER);
2182 2203                  atomic_or_32(&irp->irp_flags, IRP_PLOGI_DONE);
2183 2204                  atomic_inc_32(&iport->iport_nrps_login);
2184 2205                  if (irp->irp_deregister_timer) {
2185 2206                          irp->irp_deregister_timer = 0;
2186 2207                          irp->irp_dereg_count = 0;
2187 2208                  }
     2209 +                rw_exit(&irp->irp_lock);
     2210 +                rw_exit(&iport->iport_lock);
2188 2211          }
2189 2212  
2190 2213          if (irp && (els->els_req_payload[0] == ELS_OP_PLOGI)) {
     2214 +                rw_enter(&irp->irp_lock, RW_WRITER);
2191 2215                  atomic_and_32(&irp->irp_flags, ~IRP_SOL_PLOGI_IN_PROGRESS);
     2216 +                rw_exit(&irp->irp_lock);
2192 2217          }
2193 2218          atomic_or_32(&icmd->icmd_flags, ICMD_CMD_COMPLETE);
2194 2219          stmf_trace(iport->iport_alias, "Sol ELS %x (%s) completed with "
2195 2220              "status %llx, did/%x", op, FCT_ELS_NAME(op),
2196 2221              icmd->icmd_cmd->cmd_comp_status, icmd->icmd_cmd->cmd_rportid);
2197 2222  }
2198 2223  
2199 2224  static disc_action_t
2200 2225  fct_check_cmdlist(fct_i_local_port_t *iport)
2201 2226  {
↓ open down ↓ 9 lines elided ↑ open up ↑
2211 2236          if (total <= max_active)
2212 2237                  return (DISC_ACTION_NO_WORK);
2213 2238          /*
2214 2239           * Everytime, we release half of the difference
2215 2240           */
2216 2241          num_to_release = (total + 1 - max_active) / 2;
2217 2242  
2218 2243          mutex_exit(&iport->iport_worker_lock);
2219 2244          for (ndx = 0; ndx < num_to_release; ndx++) {
2220 2245                  mutex_enter(&iport->iport_cached_cmd_lock);
2221      -                icmd = iport->iport_cached_cmdlist;
2222      -                if (icmd == NULL) {
     2246 +                if (list_is_empty(&iport->iport_cached_cmdlist)) {
2223 2247                          mutex_exit(&iport->iport_cached_cmd_lock);
2224 2248                          break;
2225 2249                  }
2226      -                iport->iport_cached_cmdlist = icmd->icmd_next;
     2250 +                icmd = list_remove_head(&iport->iport_cached_cmdlist);
2227 2251                  iport->iport_cached_ncmds--;
2228 2252                  mutex_exit(&iport->iport_cached_cmd_lock);
2229 2253                  atomic_dec_32(&iport->iport_total_alloced_ncmds);
2230 2254                  fct_free(icmd->icmd_cmd);
2231 2255          }
2232 2256          mutex_enter(&iport->iport_worker_lock);
2233 2257          return (DISC_ACTION_RESCAN);
2234 2258  }
2235 2259  
2236 2260  /*
↓ open down ↓ 48 lines elided ↑ open up ↑
2285 2309                                  iport->iport_solcmd_queue = next_icmd;
2286 2310                          } else {
2287 2311                                  prev_icmd = iport->iport_solcmd_queue;
2288 2312                                  while (prev_icmd->icmd_solcmd_next != icmd) {
2289 2313                                          prev_icmd = prev_icmd->icmd_solcmd_next;
2290 2314                                  }
2291 2315                                  prev_icmd->icmd_solcmd_next = next_icmd;
2292 2316                          }
2293 2317  
2294 2318                          icmd->icmd_cb = NULL;
     2319 +
     2320 +                        /*
     2321 +                         * If the command has none-zero icmd_node pointers
     2322 +                         * it means it's been linked onto the iport_abort_queue.
     2323 +                         * Since the iport_worker_lock is held the command
     2324 +                         * can be removed before it's freed.
     2325 +                         */
     2326 +                        if (icmd->icmd_node.list_next != NULL) {
     2327 +                                list_remove(&iport->iport_abort_queue, icmd);
     2328 +                        }
     2329 +
2295 2330                          mutex_exit(&iport->iport_worker_lock);
2296 2331                          fct_cmd_free(icmd->icmd_cmd);
2297 2332                          mutex_enter(&iport->iport_worker_lock);
2298 2333                  } else {
2299 2334                          /*
2300 2335                           * This solicited cmd is still ongoing.
2301 2336                           * We need check if it's time to abort this cmd
2302 2337                           */
2303 2338                          if (((icmd->icmd_start_time + drv_usectohz(
2304 2339                              USEC_SOL_TIMEOUT)) < ddi_get_lbolt()) &&
↓ open down ↓ 116 lines elided ↑ open up ↑
2421 2456          } else {
2422 2457                  snlen = ICMD_TO_CT(icmd)->ct_resp_payload[16];
2423 2458          }
2424 2459  
2425 2460          if (query_irp && snlen) {
2426 2461                  /*
2427 2462                   * Release previous resource, then allocate needed resource
2428 2463                   */
2429 2464                  sn = query_irp->irp_snn;
2430 2465                  if (sn) {
2431      -                        kmem_free(sn, strlen(sn) + 1);
     2466 +                        kmem_free(sn, query_irp->irp_snn_len);
2432 2467                  }
2433 2468  
2434 2469                  query_irp->irp_snn = NULL;
     2470 +                query_irp->irp_snn_len = 0;
2435 2471                  sn = kmem_zalloc(snlen + 1, KM_SLEEP);
2436 2472                  (void) strncpy(sn, (char *)
2437 2473                      ICMD_TO_CT(icmd)->ct_resp_payload + 17, snlen);
2438 2474                  if (strlen(sn) != snlen) {
2439 2475                          stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias,
2440 2476                              "fct_gsnn_cb: %s, but len=%d", sn, snlen);
2441 2477                          kmem_free(sn, snlen + 1);
2442 2478                          sn = NULL;
2443 2479                  }
2444 2480  
2445 2481                  /*
2446 2482                   * Update symbolic node name
2447 2483                   */
2448 2484                  query_irp->irp_snn = sn;
     2485 +                if (sn != NULL)
     2486 +                        query_irp->irp_snn_len = snlen + 1;
2449 2487                  if ((query_irp->irp_flags & IRP_SCSI_SESSION_STARTED) &&
2450 2488                      (query_irp->irp_session)) {
2451 2489                          query_irp->irp_session->ss_rport_alias =
2452 2490                              query_irp->irp_snn;
2453 2491                  }
2454 2492          } else {
2455 2493                  stmf_trace(ICMD_TO_IPORT(icmd)->iport_alias, "fct_gsnn_cb: "
2456 2494                      "irp/%p, snlen/%d", query_irp, snlen);
2457 2495          }
2458 2496  
↓ open down ↓ 190 lines elided ↑ open up ↑
2649 2687          query_portid = (req[17] << 16) | (req[18] << 8) | req[19];
2650 2688  
2651 2689          rw_enter(&iport->iport_lock, RW_READER);
2652 2690          mutex_enter(&iport->iport_worker_lock);
2653 2691          query_irp = fct_portid_to_portptr(iport, query_portid);
2654 2692          if (query_irp) {
2655 2693                  spnlen = resp[16];
2656 2694                  if (spnlen > 0) {
2657 2695                          if (query_irp->irp_spn) {
2658 2696                                  kmem_free(query_irp->irp_spn,
2659      -                                    strlen(query_irp->irp_spn) + 1);
     2697 +                                    query_irp->irp_spn_len);
2660 2698                          }
2661      -                        query_irp->irp_spn = kmem_zalloc(spnlen + 1, KM_SLEEP);
     2699 +                        query_irp->irp_spn_len = spnlen + 1;
     2700 +                        query_irp->irp_spn = kmem_zalloc(
     2701 +                            query_irp->irp_spn_len, KM_SLEEP);
2662 2702                          (void) strncpy(query_irp->irp_spn,
2663 2703                              (char *)resp + 17, spnlen);
2664 2704                  }
2665 2705          }
2666 2706          rw_exit(&iport->iport_lock);
2667 2707  }
2668 2708  
2669 2709  void
2670 2710  fct_rls_cb(fct_i_cmd_t *icmd)
2671 2711  {
↓ open down ↓ 176 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX