Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


1145                     "fct: %s driver version mismatch",
1146                     port->port_default_alias);
1147                 return (FCT_FAILURE);
1148         }
1149         if (port->port_default_alias) {
1150                 int l = strlen(port->port_default_alias);
1151 
1152                 if (l < 16) {
1153                         iport->iport_alias = iport->iport_alias_mem;
1154                 } else {
1155                         iport->iport_alias =
1156                             (char *)kmem_zalloc(l+1, KM_SLEEP);
1157                 }
1158                 (void) strcpy(iport->iport_alias, port->port_default_alias);
1159         } else {
1160                 iport->iport_alias = NULL;
1161         }
1162         stmf_wwn_to_devid_desc((scsi_devid_desc_t *)iport->iport_id,
1163             port->port_pwwn, PROTOCOL_FIBRE_CHANNEL);
1164         (void) snprintf(taskq_name, sizeof (taskq_name), "stmf_fct_taskq_%d",
1165             atomic_add_32_nv(&taskq_cntr, 1));
1166         if ((iport->iport_worker_taskq = ddi_taskq_create(NULL,
1167             taskq_name, 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1168                 return (FCT_FAILURE);
1169         }
1170         mutex_init(&iport->iport_worker_lock, NULL, MUTEX_DRIVER, NULL);
1171         cv_init(&iport->iport_worker_cv, NULL, CV_DRIVER, NULL);
1172         rw_init(&iport->iport_lock, NULL, RW_DRIVER, NULL);
1173         sema_init(&iport->iport_rls_sema, 0, NULL, SEMA_DRIVER, NULL);
1174 
1175         /* Remote port mgmt */
1176         iport->iport_rp_slots = (fct_i_remote_port_t **)kmem_zalloc(
1177             port->port_max_logins * sizeof (fct_i_remote_port_t *), KM_SLEEP);
1178         iport->iport_rp_tb = kmem_zalloc(rportid_table_size *
1179             sizeof (fct_i_remote_port_t *), KM_SLEEP);
1180 
1181         /* fct_cmds for SCSI traffic */
1182         iport->iport_total_alloced_ncmds = 0;
1183         iport->iport_cached_ncmds = 0;
1184         port->port_fca_fcp_cmd_size =
1185             (port->port_fca_fcp_cmd_size + 7) & ~7;


1423         iport->iport_rp_tb[hash_key] = irp;
1424         iport->iport_nrps++;
1425 }
1426 
1427 /*
1428  * Called with irp_lock and iport_lock held as writer.
1429  */
1430 void
1431 fct_deque_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp)
1432 {
1433         fct_i_remote_port_t     *irp_next = NULL;
1434         fct_i_remote_port_t     *irp_last = NULL;
1435         int hash_key                      =
1436             FCT_PORTID_HASH_FUNC(irp->irp_portid);
1437 
1438         irp_next = iport->iport_rp_tb[hash_key];
1439         irp_last = NULL;
1440         while (irp_next != NULL) {
1441                 if (irp == irp_next) {
1442                         if (irp->irp_flags & IRP_PLOGI_DONE) {
1443                                 atomic_add_32(&iport->iport_nrps_login, -1);
1444                         }
1445                         atomic_and_32(&irp->irp_flags,
1446                             ~(IRP_PLOGI_DONE | IRP_PRLI_DONE));
1447                         break;
1448                 }
1449                 irp_last = irp_next;
1450                 irp_next = irp_next->irp_next;
1451         }
1452 
1453         if (irp_next) {
1454                 if (irp_last == NULL) {
1455                         iport->iport_rp_tb[hash_key] =
1456                             irp->irp_next;
1457                 } else {
1458                         irp_last->irp_next = irp->irp_next;
1459                 }
1460                 irp->irp_next = NULL;
1461                 iport->iport_nrps--;
1462         }
1463 }


1661                 iport->iport_cached_ncmds--;
1662                 cmd = icmd->icmd_cmd;
1663         } else {
1664                 icmd = NULL;
1665         }
1666         mutex_exit(&iport->iport_cached_cmd_lock);
1667         if (icmd == NULL) {
1668                 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_FCP_XCHG,
1669                     port->port_fca_fcp_cmd_size, 0);
1670                 if (cmd == NULL) {
1671                         rw_exit(&irp->irp_lock);
1672                         rw_exit(&iport->iport_lock);
1673                         stmf_trace(iport->iport_alias, "Ran out of "
1674                             "memory, port=%p", port);
1675                         return (NULL);
1676                 }
1677 
1678                 icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1679                 icmd->icmd_next = NULL;
1680                 cmd->cmd_port = port;
1681                 atomic_add_32(&iport->iport_total_alloced_ncmds, 1);
1682         }
1683 
1684         /*
1685          * The accuracy of iport_max_active_ncmds is not important
1686          */
1687         if ((iport->iport_total_alloced_ncmds - iport->iport_cached_ncmds) >
1688             iport->iport_max_active_ncmds) {
1689                 iport->iport_max_active_ncmds =
1690                     iport->iport_total_alloced_ncmds -
1691                     iport->iport_cached_ncmds;
1692         }
1693 
1694         /* Lets get a slot */
1695         cmd_slot = fct_alloc_cmd_slot(iport, cmd);
1696         if (cmd_slot == FCT_SLOT_EOL) {
1697                 rw_exit(&irp->irp_lock);
1698                 rw_exit(&iport->iport_lock);
1699                 stmf_trace(iport->iport_alias, "Ran out of xchg resources");
1700                 cmd->cmd_handle = 0;
1701                 fct_cmd_free(cmd);
1702                 return (NULL);
1703         }
1704         atomic_add_16(&irp->irp_fcp_xchg_count, 1);
1705         cmd->cmd_rp = rp;
1706         icmd->icmd_flags |= ICMD_IN_TRANSITION | ICMD_KNOWN_TO_FCA;
1707         rw_exit(&irp->irp_lock);
1708         rw_exit(&iport->iport_lock);
1709 
1710         icmd->icmd_start_time = ddi_get_lbolt();
1711 
1712         cmd->cmd_specific = stmf_task_alloc(port->port_lport, irp->irp_session,
1713             lun, cdb_length, task_ext);
1714         if ((task = (scsi_task_t *)cmd->cmd_specific) != NULL) {
1715                 task->task_port_private = cmd;
1716                 return (cmd);
1717         }
1718 
1719         fct_cmd_free(cmd);
1720 
1721         return (NULL);
1722 }
1723 
1724 void


1809         ASSERT(0);
1810 }
1811 
1812 /*
1813  * This function bypasses fct_handle_els()
1814  */
1815 void
1816 fct_post_implicit_logo(fct_cmd_t *cmd)
1817 {
1818         fct_local_port_t *port = cmd->cmd_port;
1819         fct_i_local_port_t *iport =
1820             (fct_i_local_port_t *)port->port_fct_private;
1821         fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1822         fct_remote_port_t *rp = cmd->cmd_rp;
1823         fct_i_remote_port_t *irp = (fct_i_remote_port_t *)rp->rp_fct_private;
1824 
1825         icmd->icmd_start_time = ddi_get_lbolt();
1826 
1827         rw_enter(&irp->irp_lock, RW_WRITER);
1828         atomic_or_32(&icmd->icmd_flags, ICMD_IMPLICIT_CMD_HAS_RESOURCE);
1829         atomic_add_16(&irp->irp_nonfcp_xchg_count, 1);
1830         atomic_add_16(&irp->irp_sa_elses_count, 1);
1831         /*
1832          * An implicit LOGO can also be posted to a irp where a PLOGI might
1833          * be in process. That PLOGI will reset this flag and decrement the
1834          * iport_nrps_login counter.
1835          */
1836         if (irp->irp_flags & IRP_PLOGI_DONE) {
1837                 atomic_add_32(&iport->iport_nrps_login, -1);
1838         }
1839         atomic_and_32(&irp->irp_flags, ~(IRP_PLOGI_DONE | IRP_PRLI_DONE));
1840         atomic_or_32(&icmd->icmd_flags, ICMD_SESSION_AFFECTING);
1841         fct_post_to_discovery_queue(iport, irp, icmd);
1842         rw_exit(&irp->irp_lock);
1843 }
1844 
1845 /*
1846  * called with iport_lock held, return the slot number
1847  */
1848 uint16_t
1849 fct_alloc_cmd_slot(fct_i_local_port_t *iport, fct_cmd_t *cmd)
1850 {
1851         uint16_t cmd_slot;
1852         uint32_t old, new;
1853         fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1854 
1855         do {
1856                 old = iport->iport_next_free_slot;
1857                 cmd_slot = old & 0xFFFF;
1858                 if (cmd_slot == FCT_SLOT_EOL)
1859                         return (cmd_slot);
1860                 /*
1861                  * We use high order 16 bits as a counter which keeps on
1862                  * incrementing to avoid ABA issues with atomic lists.
1863                  */
1864                 new = ((old + (0x10000)) & 0xFFFF0000);
1865                 new |= iport->iport_cmd_slots[cmd_slot].slot_next;
1866         } while (atomic_cas_32(&iport->iport_next_free_slot, old, new) != old);
1867 
1868         atomic_add_16(&iport->iport_nslots_free, -1);
1869         iport->iport_cmd_slots[cmd_slot].slot_cmd = icmd;
1870         cmd->cmd_handle = (uint32_t)cmd_slot | 0x80000000 |
1871             (((uint32_t)(iport->iport_cmd_slots[cmd_slot].slot_uniq_cntr))
1872             << 24);
1873         return (cmd_slot);
1874 }
1875 
1876 /*
1877  * If icmd is not NULL, irp_lock must be held
1878  */
1879 void
1880 fct_post_to_discovery_queue(fct_i_local_port_t *iport,
1881     fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
1882 {
1883         fct_i_cmd_t     **p;
1884 
1885         ASSERT(!MUTEX_HELD(&iport->iport_worker_lock));
1886         if (icmd) {
1887                 icmd->icmd_next = NULL;
1888                 for (p = &irp->irp_els_list; *p != NULL;


2055                 }
2056 
2057                 if ((icmd->icmd_flags & ICMD_ABTS_RECEIVED) &&
2058                     (cmd->cmd_link != NULL)) {
2059                         do_abts_acc = 1;
2060                 }
2061 
2062                 /* XXX Validate slot before freeing */
2063 
2064                 slot = &iport->iport_cmd_slots[n];
2065                 slot->slot_uniq_cntr++;
2066                 slot->slot_cmd = NULL;
2067                 do {
2068                         old = iport->iport_next_free_slot;
2069                         slot->slot_next = old & 0xFFFF;
2070                         new = (old + 0x10000) & 0xFFFF0000;
2071                         new |= slot->slot_no;
2072                 } while (atomic_cas_32(&iport->iport_next_free_slot,
2073                     old, new) != old);
2074                 cmd->cmd_handle = 0;
2075                 atomic_add_16(&iport->iport_nslots_free, 1);
2076                 if (cmd->cmd_rp) {
2077                         irp = (fct_i_remote_port_t *)
2078                             cmd->cmd_rp->rp_fct_private;
2079                         if (cmd->cmd_type == FCT_CMD_FCP_XCHG)
2080                                 atomic_add_16(&irp->irp_fcp_xchg_count, -1);
2081                         else
2082                                 atomic_add_16(&irp->irp_nonfcp_xchg_count, -1);
2083                 }
2084                 rw_exit(&iport->iport_lock);
2085         } else if ((icmd->icmd_flags & ICMD_IMPLICIT) &&
2086             (icmd->icmd_flags & ICMD_IMPLICIT_CMD_HAS_RESOURCE)) {
2087                 /* for implicit cmd, no cmd slot is used */
2088                 if (cmd->cmd_rp) {
2089                         irp = (fct_i_remote_port_t *)
2090                             cmd->cmd_rp->rp_fct_private;
2091                         if (cmd->cmd_type == FCT_CMD_FCP_XCHG)
2092                                 atomic_add_16(&irp->irp_fcp_xchg_count, -1);
2093                         else
2094                                 atomic_add_16(&irp->irp_nonfcp_xchg_count, -1);
2095                 }
2096         }
2097 
2098         if (do_abts_acc) {
2099                 fct_cmd_t *lcmd = cmd->cmd_link;
2100                 fct_fill_abts_acc(lcmd);
2101                 if (port->port_send_cmd_response(lcmd,
2102                     FCT_IOF_FORCE_FCA_DONE) != FCT_SUCCESS) {
2103                         /*
2104                          * XXX Throw HBA fatal error event
2105                          * Later shutdown svc will terminate the ABTS in the end
2106                          */
2107                         (void) snprintf(info, sizeof (info),
2108                             "fct_cmd_free: iport-%p, ABTS_ACC"
2109                             " port_send_cmd_response failed", (void *)iport);
2110                         (void) fct_port_shutdown(iport->iport_port,
2111                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
2112                         return;
2113                 } else {
2114                         fct_cmd_free(lcmd);
2115                         cmd->cmd_link = NULL;
2116                 }
2117         }
2118 
2119         /* Free the cmd */
2120         if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
2121                 if (iport->iport_cached_ncmds < max_cached_ncmds) {
2122                         icmd->icmd_flags = 0;
2123                         mutex_enter(&iport->iport_cached_cmd_lock);
2124                         icmd->icmd_next = iport->iport_cached_cmdlist;
2125                         iport->iport_cached_cmdlist = icmd;
2126                         iport->iport_cached_ncmds++;
2127                         mutex_exit(&iport->iport_cached_cmd_lock);
2128                 } else {
2129                         atomic_add_32(&iport->iport_total_alloced_ncmds, -1);
2130                         fct_free(cmd);
2131                 }
2132         } else {
2133                 fct_free(cmd);
2134         }
2135 }
2136 
2137 /* ARGSUSED */
2138 stmf_status_t
2139 fct_scsi_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
2140                                                         uint32_t flags)
2141 {
2142         stmf_status_t ret = STMF_SUCCESS;
2143         scsi_task_t *task;
2144         fct_cmd_t *cmd;
2145         fct_i_cmd_t *icmd;
2146         fct_local_port_t *port;
2147         uint32_t old, new;
2148 
2149         ASSERT(abort_cmd == STMF_LPORT_ABORT_TASK);




1145                     "fct: %s driver version mismatch",
1146                     port->port_default_alias);
1147                 return (FCT_FAILURE);
1148         }
1149         if (port->port_default_alias) {
1150                 int l = strlen(port->port_default_alias);
1151 
1152                 if (l < 16) {
1153                         iport->iport_alias = iport->iport_alias_mem;
1154                 } else {
1155                         iport->iport_alias =
1156                             (char *)kmem_zalloc(l+1, KM_SLEEP);
1157                 }
1158                 (void) strcpy(iport->iport_alias, port->port_default_alias);
1159         } else {
1160                 iport->iport_alias = NULL;
1161         }
1162         stmf_wwn_to_devid_desc((scsi_devid_desc_t *)iport->iport_id,
1163             port->port_pwwn, PROTOCOL_FIBRE_CHANNEL);
1164         (void) snprintf(taskq_name, sizeof (taskq_name), "stmf_fct_taskq_%d",
1165             atomic_inc_32_nv(&taskq_cntr));
1166         if ((iport->iport_worker_taskq = ddi_taskq_create(NULL,
1167             taskq_name, 1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1168                 return (FCT_FAILURE);
1169         }
1170         mutex_init(&iport->iport_worker_lock, NULL, MUTEX_DRIVER, NULL);
1171         cv_init(&iport->iport_worker_cv, NULL, CV_DRIVER, NULL);
1172         rw_init(&iport->iport_lock, NULL, RW_DRIVER, NULL);
1173         sema_init(&iport->iport_rls_sema, 0, NULL, SEMA_DRIVER, NULL);
1174 
1175         /* Remote port mgmt */
1176         iport->iport_rp_slots = (fct_i_remote_port_t **)kmem_zalloc(
1177             port->port_max_logins * sizeof (fct_i_remote_port_t *), KM_SLEEP);
1178         iport->iport_rp_tb = kmem_zalloc(rportid_table_size *
1179             sizeof (fct_i_remote_port_t *), KM_SLEEP);
1180 
1181         /* fct_cmds for SCSI traffic */
1182         iport->iport_total_alloced_ncmds = 0;
1183         iport->iport_cached_ncmds = 0;
1184         port->port_fca_fcp_cmd_size =
1185             (port->port_fca_fcp_cmd_size + 7) & ~7;


1423         iport->iport_rp_tb[hash_key] = irp;
1424         iport->iport_nrps++;
1425 }
1426 
1427 /*
1428  * Called with irp_lock and iport_lock held as writer.
1429  */
1430 void
1431 fct_deque_rp(fct_i_local_port_t *iport, fct_i_remote_port_t *irp)
1432 {
1433         fct_i_remote_port_t     *irp_next = NULL;
1434         fct_i_remote_port_t     *irp_last = NULL;
1435         int hash_key                      =
1436             FCT_PORTID_HASH_FUNC(irp->irp_portid);
1437 
1438         irp_next = iport->iport_rp_tb[hash_key];
1439         irp_last = NULL;
1440         while (irp_next != NULL) {
1441                 if (irp == irp_next) {
1442                         if (irp->irp_flags & IRP_PLOGI_DONE) {
1443                                 atomic_dec_32(&iport->iport_nrps_login);
1444                         }
1445                         atomic_and_32(&irp->irp_flags,
1446                             ~(IRP_PLOGI_DONE | IRP_PRLI_DONE));
1447                         break;
1448                 }
1449                 irp_last = irp_next;
1450                 irp_next = irp_next->irp_next;
1451         }
1452 
1453         if (irp_next) {
1454                 if (irp_last == NULL) {
1455                         iport->iport_rp_tb[hash_key] =
1456                             irp->irp_next;
1457                 } else {
1458                         irp_last->irp_next = irp->irp_next;
1459                 }
1460                 irp->irp_next = NULL;
1461                 iport->iport_nrps--;
1462         }
1463 }


1661                 iport->iport_cached_ncmds--;
1662                 cmd = icmd->icmd_cmd;
1663         } else {
1664                 icmd = NULL;
1665         }
1666         mutex_exit(&iport->iport_cached_cmd_lock);
1667         if (icmd == NULL) {
1668                 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_FCP_XCHG,
1669                     port->port_fca_fcp_cmd_size, 0);
1670                 if (cmd == NULL) {
1671                         rw_exit(&irp->irp_lock);
1672                         rw_exit(&iport->iport_lock);
1673                         stmf_trace(iport->iport_alias, "Ran out of "
1674                             "memory, port=%p", port);
1675                         return (NULL);
1676                 }
1677 
1678                 icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1679                 icmd->icmd_next = NULL;
1680                 cmd->cmd_port = port;
1681                 atomic_inc_32(&iport->iport_total_alloced_ncmds);
1682         }
1683 
1684         /*
1685          * The accuracy of iport_max_active_ncmds is not important
1686          */
1687         if ((iport->iport_total_alloced_ncmds - iport->iport_cached_ncmds) >
1688             iport->iport_max_active_ncmds) {
1689                 iport->iport_max_active_ncmds =
1690                     iport->iport_total_alloced_ncmds -
1691                     iport->iport_cached_ncmds;
1692         }
1693 
1694         /* Lets get a slot */
1695         cmd_slot = fct_alloc_cmd_slot(iport, cmd);
1696         if (cmd_slot == FCT_SLOT_EOL) {
1697                 rw_exit(&irp->irp_lock);
1698                 rw_exit(&iport->iport_lock);
1699                 stmf_trace(iport->iport_alias, "Ran out of xchg resources");
1700                 cmd->cmd_handle = 0;
1701                 fct_cmd_free(cmd);
1702                 return (NULL);
1703         }
1704         atomic_inc_16(&irp->irp_fcp_xchg_count);
1705         cmd->cmd_rp = rp;
1706         icmd->icmd_flags |= ICMD_IN_TRANSITION | ICMD_KNOWN_TO_FCA;
1707         rw_exit(&irp->irp_lock);
1708         rw_exit(&iport->iport_lock);
1709 
1710         icmd->icmd_start_time = ddi_get_lbolt();
1711 
1712         cmd->cmd_specific = stmf_task_alloc(port->port_lport, irp->irp_session,
1713             lun, cdb_length, task_ext);
1714         if ((task = (scsi_task_t *)cmd->cmd_specific) != NULL) {
1715                 task->task_port_private = cmd;
1716                 return (cmd);
1717         }
1718 
1719         fct_cmd_free(cmd);
1720 
1721         return (NULL);
1722 }
1723 
1724 void


1809         ASSERT(0);
1810 }
1811 
1812 /*
1813  * This function bypasses fct_handle_els()
1814  */
1815 void
1816 fct_post_implicit_logo(fct_cmd_t *cmd)
1817 {
1818         fct_local_port_t *port = cmd->cmd_port;
1819         fct_i_local_port_t *iport =
1820             (fct_i_local_port_t *)port->port_fct_private;
1821         fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1822         fct_remote_port_t *rp = cmd->cmd_rp;
1823         fct_i_remote_port_t *irp = (fct_i_remote_port_t *)rp->rp_fct_private;
1824 
1825         icmd->icmd_start_time = ddi_get_lbolt();
1826 
1827         rw_enter(&irp->irp_lock, RW_WRITER);
1828         atomic_or_32(&icmd->icmd_flags, ICMD_IMPLICIT_CMD_HAS_RESOURCE);
1829         atomic_inc_16(&irp->irp_nonfcp_xchg_count);
1830         atomic_inc_16(&irp->irp_sa_elses_count);
1831         /*
1832          * An implicit LOGO can also be posted to a irp where a PLOGI might
1833          * be in process. That PLOGI will reset this flag and decrement the
1834          * iport_nrps_login counter.
1835          */
1836         if (irp->irp_flags & IRP_PLOGI_DONE) {
1837                 atomic_dec_32(&iport->iport_nrps_login);
1838         }
1839         atomic_and_32(&irp->irp_flags, ~(IRP_PLOGI_DONE | IRP_PRLI_DONE));
1840         atomic_or_32(&icmd->icmd_flags, ICMD_SESSION_AFFECTING);
1841         fct_post_to_discovery_queue(iport, irp, icmd);
1842         rw_exit(&irp->irp_lock);
1843 }
1844 
1845 /*
1846  * called with iport_lock held, return the slot number
1847  */
1848 uint16_t
1849 fct_alloc_cmd_slot(fct_i_local_port_t *iport, fct_cmd_t *cmd)
1850 {
1851         uint16_t cmd_slot;
1852         uint32_t old, new;
1853         fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
1854 
1855         do {
1856                 old = iport->iport_next_free_slot;
1857                 cmd_slot = old & 0xFFFF;
1858                 if (cmd_slot == FCT_SLOT_EOL)
1859                         return (cmd_slot);
1860                 /*
1861                  * We use high order 16 bits as a counter which keeps on
1862                  * incrementing to avoid ABA issues with atomic lists.
1863                  */
1864                 new = ((old + (0x10000)) & 0xFFFF0000);
1865                 new |= iport->iport_cmd_slots[cmd_slot].slot_next;
1866         } while (atomic_cas_32(&iport->iport_next_free_slot, old, new) != old);
1867 
1868         atomic_dec_16(&iport->iport_nslots_free);
1869         iport->iport_cmd_slots[cmd_slot].slot_cmd = icmd;
1870         cmd->cmd_handle = (uint32_t)cmd_slot | 0x80000000 |
1871             (((uint32_t)(iport->iport_cmd_slots[cmd_slot].slot_uniq_cntr))
1872             << 24);
1873         return (cmd_slot);
1874 }
1875 
1876 /*
1877  * If icmd is not NULL, irp_lock must be held
1878  */
1879 void
1880 fct_post_to_discovery_queue(fct_i_local_port_t *iport,
1881     fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
1882 {
1883         fct_i_cmd_t     **p;
1884 
1885         ASSERT(!MUTEX_HELD(&iport->iport_worker_lock));
1886         if (icmd) {
1887                 icmd->icmd_next = NULL;
1888                 for (p = &irp->irp_els_list; *p != NULL;


2055                 }
2056 
2057                 if ((icmd->icmd_flags & ICMD_ABTS_RECEIVED) &&
2058                     (cmd->cmd_link != NULL)) {
2059                         do_abts_acc = 1;
2060                 }
2061 
2062                 /* XXX Validate slot before freeing */
2063 
2064                 slot = &iport->iport_cmd_slots[n];
2065                 slot->slot_uniq_cntr++;
2066                 slot->slot_cmd = NULL;
2067                 do {
2068                         old = iport->iport_next_free_slot;
2069                         slot->slot_next = old & 0xFFFF;
2070                         new = (old + 0x10000) & 0xFFFF0000;
2071                         new |= slot->slot_no;
2072                 } while (atomic_cas_32(&iport->iport_next_free_slot,
2073                     old, new) != old);
2074                 cmd->cmd_handle = 0;
2075                 atomic_inc_16(&iport->iport_nslots_free);
2076                 if (cmd->cmd_rp) {
2077                         irp = (fct_i_remote_port_t *)
2078                             cmd->cmd_rp->rp_fct_private;
2079                         if (cmd->cmd_type == FCT_CMD_FCP_XCHG)
2080                                 atomic_dec_16(&irp->irp_fcp_xchg_count);
2081                         else
2082                                 atomic_dec_16(&irp->irp_nonfcp_xchg_count);
2083                 }
2084                 rw_exit(&iport->iport_lock);
2085         } else if ((icmd->icmd_flags & ICMD_IMPLICIT) &&
2086             (icmd->icmd_flags & ICMD_IMPLICIT_CMD_HAS_RESOURCE)) {
2087                 /* for implicit cmd, no cmd slot is used */
2088                 if (cmd->cmd_rp) {
2089                         irp = (fct_i_remote_port_t *)
2090                             cmd->cmd_rp->rp_fct_private;
2091                         if (cmd->cmd_type == FCT_CMD_FCP_XCHG)
2092                                 atomic_dec_16(&irp->irp_fcp_xchg_count);
2093                         else
2094                                 atomic_dec_16(&irp->irp_nonfcp_xchg_count);
2095                 }
2096         }
2097 
2098         if (do_abts_acc) {
2099                 fct_cmd_t *lcmd = cmd->cmd_link;
2100                 fct_fill_abts_acc(lcmd);
2101                 if (port->port_send_cmd_response(lcmd,
2102                     FCT_IOF_FORCE_FCA_DONE) != FCT_SUCCESS) {
2103                         /*
2104                          * XXX Throw HBA fatal error event
2105                          * Later shutdown svc will terminate the ABTS in the end
2106                          */
2107                         (void) snprintf(info, sizeof (info),
2108                             "fct_cmd_free: iport-%p, ABTS_ACC"
2109                             " port_send_cmd_response failed", (void *)iport);
2110                         (void) fct_port_shutdown(iport->iport_port,
2111                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
2112                         return;
2113                 } else {
2114                         fct_cmd_free(lcmd);
2115                         cmd->cmd_link = NULL;
2116                 }
2117         }
2118 
2119         /* Free the cmd */
2120         if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
2121                 if (iport->iport_cached_ncmds < max_cached_ncmds) {
2122                         icmd->icmd_flags = 0;
2123                         mutex_enter(&iport->iport_cached_cmd_lock);
2124                         icmd->icmd_next = iport->iport_cached_cmdlist;
2125                         iport->iport_cached_cmdlist = icmd;
2126                         iport->iport_cached_ncmds++;
2127                         mutex_exit(&iport->iport_cached_cmd_lock);
2128                 } else {
2129                         atomic_dec_32(&iport->iport_total_alloced_ncmds);
2130                         fct_free(cmd);
2131                 }
2132         } else {
2133                 fct_free(cmd);
2134         }
2135 }
2136 
2137 /* ARGSUSED */
2138 stmf_status_t
2139 fct_scsi_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
2140                                                         uint32_t flags)
2141 {
2142         stmf_status_t ret = STMF_SUCCESS;
2143         scsi_task_t *task;
2144         fct_cmd_t *cmd;
2145         fct_i_cmd_t *icmd;
2146         fct_local_port_t *port;
2147         uint32_t old, new;
2148 
2149         ASSERT(abort_cmd == STMF_LPORT_ABORT_TASK);