Print this page
NEX-18919 Platform component fix for the MetroHA reboot -dn issue
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-17910 vhci_scsi_reset is too noisy
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-1049 System panic in module "scsi_vhci" due to a NULL pointer dereference
OS-62 slow io error detector is needed.
re #13247 rb4316 Large, fixed command timeouts impair command drop recovery
   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */

  21 /*
  22  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright (c) 2016 by Delphix. All rights reserved.
  27  */
  28 
  29 /*
  30  * Multiplexed I/O SCSI vHCI implementation
  31  */
  32 
  33 #include <sys/conf.h>
  34 #include <sys/file.h>
  35 #include <sys/ddi.h>
  36 #include <sys/sunddi.h>
  37 #include <sys/scsi/scsi.h>
  38 #include <sys/scsi/impl/scsi_reset_notify.h>
  39 #include <sys/scsi/impl/services.h>
  40 #include <sys/sunmdi.h>
  41 #include <sys/mdi_impldefs.h>
  42 #include <sys/scsi/adapters/scsi_vhci.h>
  43 #include <sys/disp.h>
  44 #include <sys/byteorder.h>
  45 
  46 extern uintptr_t scsi_callback_id;
  47 extern ddi_dma_attr_t scsi_alloc_attr;
  48 
  49 #ifdef  DEBUG
  50 int     vhci_debug = VHCI_DEBUG_DEFAULT_VAL;
  51 #endif
  52 
  53 /* retry for the vhci_do_prout command when a not ready is returned */
  54 int vhci_prout_not_ready_retry = 180;
  55 
  56 /*





  57  * These values are defined to support the internal retry of
  58  * SCSI packets for better sense code handling.
  59  */
  60 #define VHCI_CMD_CMPLT  0
  61 #define VHCI_CMD_RETRY  1
  62 #define VHCI_CMD_ERROR  -1
  63 
  64 #define PROPFLAGS (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)
  65 #define VHCI_SCSI_PERR          0x47
  66 #define VHCI_PGR_ILLEGALOP      -2
  67 #define VHCI_NUM_UPDATE_TASKQ   8
  68 /* changed to 132 to accomodate HDS */
  69 
  70 /*
  71  * Version Macros
  72  */
  73 #define VHCI_NAME_VERSION       "SCSI VHCI Driver"
  74 char            vhci_version_name[] = VHCI_NAME_VERSION;
  75 
  76 int             vhci_first_time = 0;


 115  * functions exported by scsi_vhci struct dev_ops
 116  */
 117 static int vhci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 118 static int vhci_attach(dev_info_t *, ddi_attach_cmd_t);
 119 static int vhci_detach(dev_info_t *, ddi_detach_cmd_t);
 120 
 121 /*
 122  * functions exported by scsi_vhci scsi_hba_tran_t transport table
 123  */
 124 static int vhci_scsi_tgt_init(dev_info_t *, dev_info_t *,
 125     scsi_hba_tran_t *, struct scsi_device *);
 126 static void vhci_scsi_tgt_free(dev_info_t *, dev_info_t *, scsi_hba_tran_t *,
 127     struct scsi_device *);
 128 static int vhci_pgr_register_start(scsi_vhci_lun_t *, struct scsi_pkt *);
 129 static int vhci_scsi_start(struct scsi_address *, struct scsi_pkt *);
 130 static int vhci_scsi_abort(struct scsi_address *, struct scsi_pkt *);
 131 static int vhci_scsi_reset(struct scsi_address *, int);
 132 static int vhci_scsi_reset_target(struct scsi_address *, int level,
 133     uint8_t select_path);
 134 static int vhci_scsi_reset_bus(struct scsi_address *);

 135 static int vhci_scsi_getcap(struct scsi_address *, char *, int);
 136 static int vhci_scsi_setcap(struct scsi_address *, char *, int, int);
 137 static int vhci_commoncap(struct scsi_address *, char *, int, int, int);
 138 static int vhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
 139     mdi_pathinfo_t *pip);
 140 static struct scsi_pkt *vhci_scsi_init_pkt(struct scsi_address *,
 141     struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
 142 static void vhci_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
 143 static void vhci_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
 144 static void vhci_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
 145 static int vhci_scsi_reset_notify(struct scsi_address *, int, void (*)(caddr_t),
 146     caddr_t);
 147 static int vhci_scsi_get_bus_addr(struct scsi_device *, char *, int);
 148 static int vhci_scsi_get_name(struct scsi_device *, char *, int);
 149 static int vhci_scsi_bus_power(dev_info_t *, void *, pm_bus_power_op_t,
 150     void *, void *);
 151 static int vhci_scsi_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
 152     void *, dev_info_t **);
 153 static int vhci_scsi_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
 154     void *);


1369                                  * fail for some other reason. There is not an
1370                                  * easy way how to recover though. Log a warning
1371                                  * and return.
1372                                  */
1373                                 p_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1374                                 vhci_log(CE_WARN, vhci->vhci_dip, "!Sending "
1375                                     "RELEASE(6) to %s failed, a potential "
1376                                     "reservation conflict ahead.",
1377                                     ddi_pathname(mdi_pi_get_phci(pip), p_path));
1378                                 kmem_free(p_path, MAXPATHLEN);
1379 
1380                                 if (restore_lbp)
1381                                         (void) mdi_set_lb_policy(cdip, lbp);
1382 
1383                                 /* no need to check pkt_reserve_cmd here */
1384                                 vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1385                                 return (TRAN_FATAL_ERROR);
1386                         }
1387 
1388                         rel_pkt->pkt_cdbp[0] = SCMD_RELEASE;
1389                         rel_pkt->pkt_time = 60;
1390 
1391                         /*
1392                          * Ignore the return value.  If it will fail
1393                          * then most likely it is no longer reserved
1394                          * anyway.
1395                          */
1396                         (void) vhci_do_scsi_cmd(rel_pkt);
1397                         VHCI_DEBUG(1, (CE_NOTE, NULL,
1398                             "!vhci_scsi_start: path 0x%p, issued SCSI-2"
1399                             " RELEASE\n", (void *)pip));
1400                         scsi_destroy_pkt(rel_pkt);
1401                         mdi_rele_path(pip);
1402                 }
1403         }
1404 
1405         VHCI_INCR_PATH_CMDCOUNT(svp);
1406 
1407         /*
1408          * Ensure that no other IOs raced ahead, while a RESERVE cmd was
1409          * QUIESCING the same lun.


1518         /* Do not destroy phci packet information for PKT_DMA_PARTIAL */
1519         if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1520                 scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
1521                 vpkt->vpkt_hba_pkt = NULL;
1522                 if (vpkt->vpkt_path) {
1523                         MDI_PI_ERRSTAT(vpkt->vpkt_path, MDI_PI_TRANSERR);
1524                         mdi_rele_path(vpkt->vpkt_path);
1525                         vpkt->vpkt_path = NULL;
1526                 }
1527         }
1528         return (TRAN_BUSY);
1529 }
1530 
1531 /*
1532  * Function name : vhci_scsi_reset()
1533  *
1534  * Return Values : 0 - reset failed
1535  *                 1 - reset succeeded
1536  */
1537 
1538 /* ARGSUSED */
1539 static int
1540 vhci_scsi_reset(struct scsi_address *ap, int level)
1541 {
1542         int rval = 0;
1543 
1544         cmn_err(CE_WARN, "!vhci_scsi_reset 0x%x", level);
1545         if ((level == RESET_TARGET) || (level == RESET_LUN)) {
1546                 return (vhci_scsi_reset_target(ap, level, TRUE));
1547         } else if (level == RESET_ALL) {
1548                 return (vhci_scsi_reset_bus(ap));


1549         }
1550 
1551         return (rval);
1552 }
1553 
1554 /*
1555  * vhci_recovery_reset:
1556  *      Issues reset to the device
1557  * Input:
1558  *      vlun - vhci lun pointer of the device
1559  *      ap - address of the device
1560  *      select_path:
1561  *              If select_path is FALSE, then the address specified in ap is
1562  *              the path on which reset will be issued.
1563  *              If select_path is TRUE, then path is obtained by calling
1564  *              mdi_select_path.
1565  *
1566  *      recovery_depth:
1567  *              Caller can specify the level of reset.
1568  *              VHCI_DEPTH_LUN -
1569  *                      Issues LUN RESET if device supports lun reset.
1570  *              VHCI_DEPTH_TARGET -
1571  *                      If Lun Reset fails or the device does not support


1597                 recovery_depth--;
1598         }
1599 
1600         if ((ret == 0) && recovery_depth) {
1601                 (void) scsi_reset(ap, RESET_ALL);
1602         }
1603 
1604         return (ret);
1605 }
1606 
1607 /*
1608  * Note: The scsi_address passed to this routine could be the scsi_address
1609  * for the virtual device or the physical device. No assumptions should be
1610  * made in this routine about the contents of the ap structure.
1611  * Further, note that the child dip would be the dip of the ssd node regardless
1612  * of the scsi_address passed in.
1613  */
1614 static int
1615 vhci_scsi_reset_target(struct scsi_address *ap, int level, uint8_t select_path)
1616 {
1617         dev_info_t              *vdip, *cdip;
1618         mdi_pathinfo_t          *pip = NULL;
1619         mdi_pathinfo_t          *npip = NULL;
1620         int                     rval = -1;
1621         scsi_vhci_priv_t        *svp = NULL;
1622         struct scsi_address     *pap = NULL;
1623         scsi_hba_tran_t         *hba = NULL;
1624         int                     sps;
1625         struct scsi_vhci        *vhci = NULL;
1626 
1627         if (select_path != TRUE) {
1628                 ASSERT(ap != NULL);
1629                 if (level == RESET_LUN) {
1630                         hba = ap->a_hba_tran;
1631                         ASSERT(hba != NULL);
1632                         return (hba->tran_reset(ap, RESET_LUN));
1633                 }
1634                 return (scsi_reset(ap, level));
1635         }
1636 




1637         cdip = ADDR2DIP(ap);



1638         ASSERT(cdip != NULL);
1639         vdip = ddi_get_parent(cdip);
1640         ASSERT(vdip != NULL);
1641         vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1642         ASSERT(vhci != NULL);
1643 
1644         rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
1645         if ((rval != MDI_SUCCESS) || (pip == NULL)) {
1646                 VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1647                     "Unable to get a path, dip 0x%p", (void *)cdip));
1648                 return (0);
1649         }
1650 again:
1651         svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
1652         if (svp == NULL) {
1653                 VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1654                     "priv is NULL, pip 0x%p", (void *)pip));
1655                 mdi_rele_path(pip);
1656                 return (0);
1657         }


1688                                 return (0);
1689                         }
1690                         mdi_rele_path(pip);
1691                         pip = npip;
1692                         goto again;
1693                 }
1694                 mdi_rele_path(pip);
1695                 mutex_enter(&vhci->vhci_mutex);
1696                 scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
1697                     &vhci->vhci_reset_notify_listf);
1698                 mutex_exit(&vhci->vhci_mutex);
1699                 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
1700                     "reset %d sent down pip:%p for cdip:%p\n", level,
1701                     (void *)pip, (void *)cdip));
1702                 return (1);
1703         }
1704         mdi_rele_path(pip);
1705         return (0);
1706 }
1707 
1708 
1709 /* ARGSUSED */
1710 static int
1711 vhci_scsi_reset_bus(struct scsi_address *ap)
1712 {
1713         return (1);
1714 }
1715 

















1716 
















































































1717 /*
1718  * called by vhci_getcap and vhci_setcap to get and set (respectively)
1719  * SCSI capabilities
1720  */
1721 /* ARGSUSED */
1722 static int
1723 vhci_commoncap(struct scsi_address *ap, char *cap,
1724     int val, int tgtonly, int doset)
1725 {
1726         struct scsi_vhci                *vhci = ADDR2VHCI(ap);
1727         struct scsi_vhci_lun            *vlun = ADDR2VLUN(ap);
1728         int                     cidx;
1729         int                     rval = 0;
1730 
1731         if (cap == (char *)0) {
1732                 VHCI_DEBUG(3, (CE_WARN, vhci->vhci_dip,
1733                     "!vhci_commoncap: invalid arg"));
1734                 return (rval);
1735         }
1736 


3169         char                    *cpath;
3170 
3171         ASSERT(vpkt != NULL);
3172         tpkt = vpkt->vpkt_tgt_pkt;
3173         ASSERT(tpkt != NULL);
3174         svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
3175         ASSERT(svp != NULL);
3176         vlun = svp->svp_svl;
3177         ASSERT(vlun != NULL);
3178         lpath = vpkt->vpkt_path;
3179 
3180         /*
3181          * sync up the target driver's pkt with the pkt that
3182          * we actually used
3183          */
3184         *(tpkt->pkt_scbp) = *(pkt->pkt_scbp);
3185         tpkt->pkt_resid = pkt->pkt_resid;
3186         tpkt->pkt_state = pkt->pkt_state;
3187         tpkt->pkt_statistics = pkt->pkt_statistics;
3188         tpkt->pkt_reason = pkt->pkt_reason;


3189 
3190         /* Return path_instance information back to the target driver. */
3191         if (scsi_pkt_allocated_correctly(tpkt)) {
3192                 if (scsi_pkt_allocated_correctly(pkt)) {
3193                         /*
3194                          * If both packets were correctly allocated,
3195                          * return path returned by pHCI.
3196                          */
3197                         tpkt->pkt_path_instance = pkt->pkt_path_instance;
3198                 } else {
3199                         /* Otherwise return path of pHCI we used */
3200                         tpkt->pkt_path_instance =
3201                             mdi_pi_get_path_instance(lpath);
3202                 }
3203         }
3204 
3205         if (pkt->pkt_cdbp[0] == SCMD_PROUT &&
3206             ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
3207             ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE)) {
3208                 if ((SCBP_C(pkt) != STATUS_GOOD) ||


3940                         }
3941 
3942                         /* Check for Reservation Conflict */
3943                         bp = scsi_alloc_consistent_buf(
3944                             &svp->svp_psd->sd_address, (struct buf *)NULL,
3945                             DEV_BSIZE, B_READ, NULL, NULL);
3946                         if (!bp) {
3947                                 VHCI_DEBUG(1, (CE_NOTE, NULL,
3948                                     "!vhci_update_pathstates: No resources "
3949                                     "(buf)\n"));
3950                                 mdi_rele_path(pip);
3951                                 goto done;
3952                         }
3953                         pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
3954                             CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
3955                             PKT_CONSISTENT, NULL, NULL);
3956                         if (pkt) {
3957                                 (void) scsi_setup_cdb((union scsi_cdb *)
3958                                     (uintptr_t)pkt->pkt_cdbp, SCMD_READ, 1, 1,
3959                                     0);
3960                                 pkt->pkt_time = 3*30;
3961                                 pkt->pkt_flags = FLAG_NOINTR;
3962                                 pkt->pkt_path_instance =
3963                                     mdi_pi_get_path_instance(pip);
3964 
3965                                 if ((scsi_transport(pkt) == TRAN_ACCEPT) &&
3966                                     (pkt->pkt_reason == CMD_CMPLT) &&
3967                                     (SCBP_C(pkt) ==
3968                                     STATUS_RESERVATION_CONFLICT)) {
3969                                         VHCI_DEBUG(1, (CE_NOTE, NULL,
3970                                             "!vhci_update_pathstates: reserv. "
3971                                             "conflict to be resolved on 0x%p\n",
3972                                             (void *)pip));
3973                                         svp_conflict = svp;
3974                                 }
3975                                 scsi_destroy_pkt(pkt);
3976                         }
3977                         scsi_free_consistent_buf(bp);
3978                 } else if ((opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) &&
3979                     !(MDI_PI_IS_STANDBY(pip))) {
3980                         VHCI_DEBUG(1, (CE_NOTE, NULL,


5205                 if ((vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) == 0) {
5206                         /*
5207                          * Issue SCSI-2 RELEASE only for the first time on
5208                          * a new path just in case the host rebooted and
5209                          * a reservation is still pending on this path.
5210                          * IBM Shark storage does not clear RESERVE upon
5211                          * host reboot.
5212                          */
5213                         pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0,
5214                             sizeof (struct scsi_arq_status), 0, 0,
5215                             SLEEP_FUNC, NULL);
5216                         if (pkt == NULL) {
5217                                 VHCI_DEBUG(1, (CE_NOTE, NULL,
5218                                     "!vhci_pathinfo_online: "
5219                                     "Release init_pkt failed :%p\n",
5220                                     (void *)pip));
5221                                 rval = MDI_FAILURE;
5222                                 goto failure;
5223                         }
5224                         pkt->pkt_cdbp[0] = SCMD_RELEASE;
5225                         pkt->pkt_time = 60;
5226 
5227                         VHCI_DEBUG(1, (CE_NOTE, NULL,
5228                             "!vhci_path_online: path:%p "
5229                             "Issued SCSI-2 RELEASE\n", (void *)pip));
5230 
5231                         /* Ignore the return value */
5232                         (void) vhci_do_scsi_cmd(pkt);
5233                         scsi_destroy_pkt(pkt);
5234                 }
5235         }
5236 
5237         rval = vhci_update_pathinfo(psd, pip, sfo, vlun, vhci);
5238         if (rval == MDI_FAILURE) {
5239                 goto failure;
5240         }
5241 
5242         /* Initialize MP-API data */
5243         vhci_update_mpapi_data(vhci, vlun, pip);
5244 
5245         /*


6132 
6133         case DEVCTL_DEVICE_RESET:
6134                 /*
6135                  * lookup and hold child device
6136                  */
6137                 if ((child = ndi_devi_find(self, ndi_dc_getname(dcp),
6138                     ndi_dc_getaddr(dcp))) == NULL) {
6139                         rv = ENXIO;
6140                         break;
6141                 }
6142                 retval = mdi_select_path(child, NULL,
6143                     (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH),
6144                     NULL, &pip);
6145                 if ((retval != MDI_SUCCESS) || (pip == NULL)) {
6146                         VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl:"
6147                             "Unable to get a path, dip 0x%p", (void *)child));
6148                         rv = ENXIO;
6149                         break;
6150                 }
6151                 svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
6152                 if (vhci_recovery_reset(svp->svp_svl,
6153                     &svp->svp_psd->sd_address, TRUE,
6154                     VHCI_DEPTH_TARGET) == 0) {
6155                         VHCI_DEBUG(1, (CE_NOTE, NULL,
6156                             "!vhci_ioctl(pip:%p): "
6157                             "reset failed\n", (void *)pip));



6158                         rv = ENXIO;
6159                 }
6160                 mdi_rele_path(pip);
6161                 break;
6162 
6163         case DEVCTL_BUS_QUIESCE:
6164         case DEVCTL_BUS_UNQUIESCE:
6165         case DEVCTL_BUS_RESET:
6166         case DEVCTL_BUS_RESETALL:
6167 #ifdef  DEBUG
6168         case DEVCTL_BUS_CONFIGURE:
6169         case DEVCTL_BUS_UNCONFIGURE:
6170 #endif
6171                 rv = ENOTSUP;
6172                 break;
6173 
6174         default:
6175                 rv = ENOTTY;
6176         } /* end of outer switch */
6177 


6961                 check_condition = 0;
6962                 UA_condition = 0;
6963 
6964                 bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
6965                     (struct buf *)NULL, DEV_BSIZE, B_READ, NULL, NULL);
6966                 if (!bp) {
6967                         VHCI_DEBUG(1, (CE_NOTE, NULL,
6968                             "vhci_failover !No resources (buf)\n"));
6969                         mdi_rele_path(npip);
6970                         goto done;
6971                 }
6972                 pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
6973                     CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
6974                     PKT_CONSISTENT, NULL, NULL);
6975                 if (pkt) {
6976                         (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)
6977                             pkt->pkt_cdbp, SCMD_READ, 1, 1, 0);
6978                         pkt->pkt_flags = FLAG_NOINTR;
6979 check_path_again:
6980                         pkt->pkt_path_instance = mdi_pi_get_path_instance(npip);
6981                         pkt->pkt_time = 3*30;
6982 
6983                         if (scsi_transport(pkt) == TRAN_ACCEPT) {
6984                                 switch (pkt->pkt_reason) {
6985                                 case CMD_CMPLT:
6986                                         switch (SCBP_C(pkt)) {
6987                                         case STATUS_GOOD:
6988                                                 /* Already failed over */
6989                                                 activation_done = 1;
6990                                                 break;
6991                                         case STATUS_RESERVATION_CONFLICT:
6992                                                 reserve_pending = 1;
6993                                                 break;
6994                                         case STATUS_CHECK:
6995                                                 check_condition = 1;
6996                                                 break;
6997                                         }
6998                                 }
6999                         }
7000                         if (check_condition &&
7001                             (pkt->pkt_state & STATE_ARQ_DONE)) {


8322             "vhci_uscsi_send_sense: enter: bp: %p pkt: %p scmd: %p",
8323             (void *)cmdbp, (void *)pkt, (void *)mp_uscmdp));
8324         /* set up the packet information and cdb */
8325         if ((rqbp = scsi_alloc_consistent_buf(mp_uscmdp->ap, NULL,
8326             SENSE_LENGTH, B_READ, NULL, NULL)) == NULL) {
8327                 return (-1);
8328         }
8329 
8330         if ((rqpkt = scsi_init_pkt(mp_uscmdp->ap, NULL, rqbp,
8331             CDB_GROUP0, 1, 0, PKT_CONSISTENT, NULL, NULL)) == NULL) {
8332                 scsi_free_consistent_buf(rqbp);
8333                 return (-1);
8334         }
8335 
8336         (void) scsi_setup_cdb((union scsi_cdb *)(intptr_t)rqpkt->pkt_cdbp,
8337             SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
8338 
8339         mp_uscmdp->rqbp = rqbp;
8340         rqbp->b_private = mp_uscmdp;
8341         rqpkt->pkt_flags |= FLAG_SENSING;
8342         rqpkt->pkt_time = 60;
8343         rqpkt->pkt_comp = vhci_uscsi_iodone;
8344         rqpkt->pkt_private = mp_uscmdp;
8345 
8346         /*
8347          * NOTE: This code path is related to MPAPI uscsi(7I), so path
8348          * selection is not based on path_instance.
8349          */
8350         if (scsi_pkt_allocated_correctly(rqpkt))
8351                 rqpkt->pkt_path_instance = 0;
8352 
8353         switch (scsi_transport(rqpkt)) {
8354         case TRAN_ACCEPT:
8355                 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8356                     "transport accepted."));
8357                 break;
8358         case TRAN_BUSY:
8359                 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8360                     "transport busy, setting timeout."));
8361                 vhci_restart_timeid = timeout(vhci_uscsi_restart_sense, rqpkt,
8362                     (drv_usectohz(5 * 1000000)));


8537         uscmdp = mp_uscmdp->uscmdp;
8538         if (uscmdp->uscsi_flags & USCSI_RQENABLE) {
8539                 stat_size = SENSE_LENGTH;
8540         } else {
8541                 stat_size = 1;
8542         }
8543 
8544         pkt = scsi_init_pkt(mp_uscmdp->ap, NULL, bp, uscmdp->uscsi_cdblen,
8545             stat_size, 0, 0, SLEEP_FUNC, NULL);
8546         if (pkt == NULL) {
8547                 VHCI_DEBUG(4, (CE_NOTE, NULL,
8548                     "vhci_uscsi_iostart: rval: EINVAL"));
8549                 bp->b_resid = bp->b_bcount;
8550                 uscmdp->uscsi_resid = bp->b_bcount;
8551                 bioerror(bp, EINVAL);
8552                 biodone(bp);
8553                 return (EINVAL);
8554         }
8555 
8556         pkt->pkt_time = uscmdp->uscsi_timeout;



8557         bcopy(uscmdp->uscsi_cdb, pkt->pkt_cdbp, (size_t)uscmdp->uscsi_cdblen);
8558         pkt->pkt_comp = vhci_uscsi_iodone;
8559         pkt->pkt_private = mp_uscmdp;
8560         if (uscmdp->uscsi_flags & USCSI_SILENT)
8561                 pkt->pkt_flags |= FLAG_SILENT;
8562         if (uscmdp->uscsi_flags & USCSI_ISOLATE)
8563                 pkt->pkt_flags |= FLAG_ISOLATE;
8564         if (uscmdp->uscsi_flags & USCSI_DIAGNOSE)
8565                 pkt->pkt_flags |= FLAG_DIAGNOSE;
8566         if (uscmdp->uscsi_flags & USCSI_RENEGOT) {
8567                 pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
8568         }
8569         VHCI_DEBUG(4, (CE_WARN, NULL,
8570             "vhci_uscsi_iostart: ap: %p pkt: %p pcdbp: %p uscmdp: %p"
8571             " ucdbp: %p pcdblen: %d bp: %p count: %ld pip: %p"
8572             " stat_size: %d",
8573             (void *)mp_uscmdp->ap, (void *)pkt, (void *)pkt->pkt_cdbp,
8574             (void *)uscmdp, (void *)uscmdp->uscsi_cdb, pkt->pkt_cdblen,
8575             (void *)bp, bp->b_bcount, (void *)mp_uscmdp->pip, stat_size));
8576 


   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc.


  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * Multiplexed I/O SCSI vHCI implementation
  30  */
  31 
  32 #include <sys/conf.h>
  33 #include <sys/file.h>
  34 #include <sys/ddi.h>
  35 #include <sys/sunddi.h>
  36 #include <sys/scsi/scsi.h>
  37 #include <sys/scsi/impl/scsi_reset_notify.h>
  38 #include <sys/scsi/impl/services.h>
  39 #include <sys/sunmdi.h>
  40 #include <sys/mdi_impldefs.h>
  41 #include <sys/scsi/adapters/scsi_vhci.h>
  42 #include <sys/disp.h>
  43 #include <sys/byteorder.h>
  44 
  45 extern uintptr_t scsi_callback_id;
  46 extern ddi_dma_attr_t scsi_alloc_attr;
  47 
  48 #ifdef  DEBUG
  49 int     vhci_debug = VHCI_DEBUG_DEFAULT_VAL;
  50 #endif
  51 
  52 /* retry for the vhci_do_prout command when a not ready is returned */
  53 int vhci_prout_not_ready_retry = 180;
  54 
  55 /*
  56  * Timeout in seconds for SCSI commands used by vHCI.
  57  */
  58 int vhci_io_time = 30;
  59 
  60 /*
  61  * These values are defined to support the internal retry of
  62  * SCSI packets for better sense code handling.
  63  */
  64 #define VHCI_CMD_CMPLT  0
  65 #define VHCI_CMD_RETRY  1
  66 #define VHCI_CMD_ERROR  -1
  67 
  68 #define PROPFLAGS (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)
  69 #define VHCI_SCSI_PERR          0x47
  70 #define VHCI_PGR_ILLEGALOP      -2
  71 #define VHCI_NUM_UPDATE_TASKQ   8
  72 /* changed to 132 to accomodate HDS */
  73 
  74 /*
  75  * Version Macros
  76  */
  77 #define VHCI_NAME_VERSION       "SCSI VHCI Driver"
  78 char            vhci_version_name[] = VHCI_NAME_VERSION;
  79 
  80 int             vhci_first_time = 0;


 119  * functions exported by scsi_vhci struct dev_ops
 120  */
 121 static int vhci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 122 static int vhci_attach(dev_info_t *, ddi_attach_cmd_t);
 123 static int vhci_detach(dev_info_t *, ddi_detach_cmd_t);
 124 
 125 /*
 126  * functions exported by scsi_vhci scsi_hba_tran_t transport table
 127  */
 128 static int vhci_scsi_tgt_init(dev_info_t *, dev_info_t *,
 129     scsi_hba_tran_t *, struct scsi_device *);
 130 static void vhci_scsi_tgt_free(dev_info_t *, dev_info_t *, scsi_hba_tran_t *,
 131     struct scsi_device *);
 132 static int vhci_pgr_register_start(scsi_vhci_lun_t *, struct scsi_pkt *);
 133 static int vhci_scsi_start(struct scsi_address *, struct scsi_pkt *);
 134 static int vhci_scsi_abort(struct scsi_address *, struct scsi_pkt *);
 135 static int vhci_scsi_reset(struct scsi_address *, int);
 136 static int vhci_scsi_reset_target(struct scsi_address *, int level,
 137     uint8_t select_path);
 138 static int vhci_scsi_reset_bus(struct scsi_address *);
 139 static int vhci_scsi_reset_all_paths(struct scsi_address *);
 140 static int vhci_scsi_getcap(struct scsi_address *, char *, int);
 141 static int vhci_scsi_setcap(struct scsi_address *, char *, int, int);
 142 static int vhci_commoncap(struct scsi_address *, char *, int, int, int);
 143 static int vhci_pHCI_cap(struct scsi_address *ap, char *cap, int val, int whom,
 144     mdi_pathinfo_t *pip);
 145 static struct scsi_pkt *vhci_scsi_init_pkt(struct scsi_address *,
 146     struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
 147 static void vhci_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
 148 static void vhci_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
 149 static void vhci_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
 150 static int vhci_scsi_reset_notify(struct scsi_address *, int, void (*)(caddr_t),
 151     caddr_t);
 152 static int vhci_scsi_get_bus_addr(struct scsi_device *, char *, int);
 153 static int vhci_scsi_get_name(struct scsi_device *, char *, int);
 154 static int vhci_scsi_bus_power(dev_info_t *, void *, pm_bus_power_op_t,
 155     void *, void *);
 156 static int vhci_scsi_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
 157     void *, dev_info_t **);
 158 static int vhci_scsi_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
 159     void *);


1374                                  * fail for some other reason. There is not an
1375                                  * easy way how to recover though. Log a warning
1376                                  * and return.
1377                                  */
1378                                 p_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1379                                 vhci_log(CE_WARN, vhci->vhci_dip, "!Sending "
1380                                     "RELEASE(6) to %s failed, a potential "
1381                                     "reservation conflict ahead.",
1382                                     ddi_pathname(mdi_pi_get_phci(pip), p_path));
1383                                 kmem_free(p_path, MAXPATHLEN);
1384 
1385                                 if (restore_lbp)
1386                                         (void) mdi_set_lb_policy(cdip, lbp);
1387 
1388                                 /* no need to check pkt_reserve_cmd here */
1389                                 vlun->svl_flags &= ~VLUN_QUIESCED_FLG;
1390                                 return (TRAN_FATAL_ERROR);
1391                         }
1392 
1393                         rel_pkt->pkt_cdbp[0] = SCMD_RELEASE;
1394                         rel_pkt->pkt_time = vhci_io_time;
1395 
1396                         /*
1397                          * Ignore the return value.  If it will fail
1398                          * then most likely it is no longer reserved
1399                          * anyway.
1400                          */
1401                         (void) vhci_do_scsi_cmd(rel_pkt);
1402                         VHCI_DEBUG(1, (CE_NOTE, NULL,
1403                             "!vhci_scsi_start: path 0x%p, issued SCSI-2"
1404                             " RELEASE\n", (void *)pip));
1405                         scsi_destroy_pkt(rel_pkt);
1406                         mdi_rele_path(pip);
1407                 }
1408         }
1409 
1410         VHCI_INCR_PATH_CMDCOUNT(svp);
1411 
1412         /*
1413          * Ensure that no other IOs raced ahead, while a RESERVE cmd was
1414          * QUIESCING the same lun.


1523         /* Do not destroy phci packet information for PKT_DMA_PARTIAL */
1524         if ((vpkt->vpkt_flags & CFLAG_DMA_PARTIAL) == 0) {
1525                 scsi_destroy_pkt(vpkt->vpkt_hba_pkt);
1526                 vpkt->vpkt_hba_pkt = NULL;
1527                 if (vpkt->vpkt_path) {
1528                         MDI_PI_ERRSTAT(vpkt->vpkt_path, MDI_PI_TRANSERR);
1529                         mdi_rele_path(vpkt->vpkt_path);
1530                         vpkt->vpkt_path = NULL;
1531                 }
1532         }
1533         return (TRAN_BUSY);
1534 }
1535 
1536 /*
1537  * Function name : vhci_scsi_reset()
1538  *
1539  * Return Values : 0 - reset failed
1540  *                 1 - reset succeeded
1541  */
1542 

1543 static int
1544 vhci_scsi_reset(struct scsi_address *ap, int level)
1545 {



1546         if ((level == RESET_TARGET) || (level == RESET_LUN)) {
1547                 return (vhci_scsi_reset_target(ap, level, TRUE));
1548         } else if (level == RESET_ALL) {
1549                 return (vhci_scsi_reset_bus(ap));
1550         } else {
1551                 return (0);
1552         }


1553 }
1554 
1555 /*
1556  * vhci_recovery_reset:
1557  *      Issues reset to the device
1558  * Input:
1559  *      vlun - vhci lun pointer of the device
1560  *      ap - address of the device
1561  *      select_path:
1562  *              If select_path is FALSE, then the address specified in ap is
1563  *              the path on which reset will be issued.
1564  *              If select_path is TRUE, then path is obtained by calling
1565  *              mdi_select_path.
1566  *
1567  *      recovery_depth:
1568  *              Caller can specify the level of reset.
1569  *              VHCI_DEPTH_LUN -
1570  *                      Issues LUN RESET if device supports lun reset.
1571  *              VHCI_DEPTH_TARGET -
1572  *                      If Lun Reset fails or the device does not support


1598                 recovery_depth--;
1599         }
1600 
1601         if ((ret == 0) && recovery_depth) {
1602                 (void) scsi_reset(ap, RESET_ALL);
1603         }
1604 
1605         return (ret);
1606 }
1607 
1608 /*
1609  * Note: The scsi_address passed to this routine could be the scsi_address
1610  * for the virtual device or the physical device. No assumptions should be
1611  * made in this routine about the contents of the ap structure.
1612  * Further, note that the child dip would be the dip of the ssd node regardless
1613  * of the scsi_address passed in.
1614  */
1615 static int
1616 vhci_scsi_reset_target(struct scsi_address *ap, int level, uint8_t select_path)
1617 {
1618         dev_info_t              *vdip, *cdip = NULL;
1619         mdi_pathinfo_t          *pip = NULL;
1620         mdi_pathinfo_t          *npip = NULL;
1621         int                     rval = -1;
1622         scsi_vhci_priv_t        *svp = NULL;
1623         struct scsi_address     *pap = NULL;
1624         scsi_hba_tran_t         *hba = NULL;
1625         int                     sps;
1626         struct scsi_vhci        *vhci = NULL;
1627 
1628         if (select_path != TRUE) {
1629                 ASSERT(ap != NULL);
1630                 if (level == RESET_LUN) {
1631                         hba = ap->a_hba_tran;
1632                         ASSERT(hba != NULL);
1633                         return (hba->tran_reset(ap, RESET_LUN));
1634                 }
1635                 return (scsi_reset(ap, level));
1636         }
1637 
1638         /*
1639          * SCSI address should be interpreted according to the pHBA flags.
1640          */
1641         if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
1642                 cdip = ADDR2DIP(ap);
1643         else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
1644                 cdip = ap->a_hba_tran->tran_sd->sd_dev;
1645 
1646         ASSERT(cdip != NULL);
1647         vdip = ddi_get_parent(cdip);
1648         ASSERT(vdip != NULL);
1649         vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
1650         ASSERT(vhci != NULL);
1651 
1652         rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
1653         if ((rval != MDI_SUCCESS) || (pip == NULL)) {
1654                 VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1655                     "Unable to get a path, dip 0x%p", (void *)cdip));
1656                 return (0);
1657         }
1658 again:
1659         svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
1660         if (svp == NULL) {
1661                 VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_scsi_reset_target: "
1662                     "priv is NULL, pip 0x%p", (void *)pip));
1663                 mdi_rele_path(pip);
1664                 return (0);
1665         }


1696                                 return (0);
1697                         }
1698                         mdi_rele_path(pip);
1699                         pip = npip;
1700                         goto again;
1701                 }
1702                 mdi_rele_path(pip);
1703                 mutex_enter(&vhci->vhci_mutex);
1704                 scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
1705                     &vhci->vhci_reset_notify_listf);
1706                 mutex_exit(&vhci->vhci_mutex);
1707                 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
1708                     "reset %d sent down pip:%p for cdip:%p\n", level,
1709                     (void *)pip, (void *)cdip));
1710                 return (1);
1711         }
1712         mdi_rele_path(pip);
1713         return (0);
1714 }
1715 

1716 /* ARGSUSED */
1717 static int
1718 vhci_scsi_reset_bus(struct scsi_address *ap)
1719 {
1720         return (1);
1721 }
1722 
1723 /*
1724  * This is a special version of LUN reset routine
1725  * which sends a reset down all available paths.
1726  */
1727 static int
1728 vhci_scsi_reset_all_paths(struct scsi_address *ap)
1729 {
1730         dev_info_t              *vdip, *cdip = NULL;
1731         mdi_pathinfo_t          *pip = NULL;
1732         mdi_pathinfo_t          *npip = NULL;
1733         int                     rval = -1;
1734         scsi_vhci_priv_t        *svp = NULL;
1735         struct scsi_address     *pap = NULL;
1736         scsi_hba_tran_t         *hba = NULL;
1737         int                     sps = MDI_SUCCESS;
1738         int                     reset_result = 0;
1739         struct scsi_vhci        *vhci = NULL;
1740 
1741         /*
1742          * SCSI address should be interpreted according to the pHBA flags.
1743          */
1744         if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
1745                 cdip = ADDR2DIP(ap);
1746         else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
1747                 cdip = ap->a_hba_tran->tran_sd->sd_dev;
1748 
1749         if (cdip == NULL || (vdip = ddi_get_parent(cdip)) == NULL ||
1750             (vhci = ddi_get_soft_state(vhci_softstate,
1751                 ddi_get_instance(vdip))) == NULL) {
1752                 VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
1753                     "Child info pointer NULL, cdip 0x%p",
1754                     __func__, (void *)cdip));
1755                 return (0);
1756         }
1757 
1758         rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
1759         if ((rval != MDI_SUCCESS) || (pip == NULL)) {
1760                 VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
1761                     "Unable to get a path, dip 0x%p",
1762                     __func__, (void *)cdip));
1763                 return (0);
1764         }
1765 again:
1766         svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
1767 
1768         if (svp == NULL || svp->svp_psd == NULL) {
1769                 VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
1770                     "private data is NULL, pip 0x%p",
1771                     __func__, (void *)pip));
1772                 mdi_rele_path(pip);
1773                 return (0);
1774         }
1775 
1776         pap = &svp->svp_psd->sd_address;
1777         hba = pap->a_hba_tran;
1778 
1779         if (pap != NULL && hba != NULL && hba->tran_reset != NULL) {
1780                 /*
1781                  * The following sends reset down all available paths
1782                  */
1783                 if (sps == MDI_SUCCESS) {
1784                         reset_result = hba->tran_reset(pap, RESET_LUN);
1785 
1786                         VHCI_DEBUG(2, (CE_WARN, vdip, "!%s%d: "
1787                             "path %s, reset LUN %s",
1788                             ddi_driver_name(cdip), ddi_get_instance(cdip),
1789                             mdi_pi_spathname(pip),
1790                             (reset_result ? "Success" : "Failed")));
1791 
1792                         /*
1793                          * Select next path and issue the reset, repeat
1794                          * until all paths are exhausted regardless of success
1795                          * or failure of the previous reset.
1796                          */
1797                         sps = mdi_select_path(cdip, NULL,
1798                             MDI_SELECT_ONLINE_PATH, pip, &npip);
1799                         if ((sps != MDI_SUCCESS) || (npip == NULL)) {
1800                                 mdi_rele_path(pip);
1801                                 return (0);
1802                         }
1803                         mdi_rele_path(pip);
1804                         pip = npip;
1805                         goto again;
1806                 }
1807                 mdi_rele_path(pip);
1808                 mutex_enter(&vhci->vhci_mutex);
1809                 scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
1810                     &vhci->vhci_reset_notify_listf);
1811                 mutex_exit(&vhci->vhci_mutex);
1812                 VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
1813                     "reset %d sent down pip:%p for cdip:%p\n", RESET_LUN,
1814                     (void *)pip, (void *)cdip));
1815                 return (1);
1816         }
1817         mdi_rele_path(pip);
1818         return (0);
1819 }
1820 
1821 /*
1822  * called by vhci_getcap and vhci_setcap to get and set (respectively)
1823  * SCSI capabilities
1824  */
1825 /* ARGSUSED */
1826 static int
1827 vhci_commoncap(struct scsi_address *ap, char *cap,
1828     int val, int tgtonly, int doset)
1829 {
1830         struct scsi_vhci                *vhci = ADDR2VHCI(ap);
1831         struct scsi_vhci_lun            *vlun = ADDR2VLUN(ap);
1832         int                     cidx;
1833         int                     rval = 0;
1834 
1835         if (cap == (char *)0) {
1836                 VHCI_DEBUG(3, (CE_WARN, vhci->vhci_dip,
1837                     "!vhci_commoncap: invalid arg"));
1838                 return (rval);
1839         }
1840 


3273         char                    *cpath;
3274 
3275         ASSERT(vpkt != NULL);
3276         tpkt = vpkt->vpkt_tgt_pkt;
3277         ASSERT(tpkt != NULL);
3278         svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(vpkt->vpkt_path);
3279         ASSERT(svp != NULL);
3280         vlun = svp->svp_svl;
3281         ASSERT(vlun != NULL);
3282         lpath = vpkt->vpkt_path;
3283 
3284         /*
3285          * sync up the target driver's pkt with the pkt that
3286          * we actually used
3287          */
3288         *(tpkt->pkt_scbp) = *(pkt->pkt_scbp);
3289         tpkt->pkt_resid = pkt->pkt_resid;
3290         tpkt->pkt_state = pkt->pkt_state;
3291         tpkt->pkt_statistics = pkt->pkt_statistics;
3292         tpkt->pkt_reason = pkt->pkt_reason;
3293         tpkt->pkt_start = pkt->pkt_start;
3294         tpkt->pkt_stop = pkt->pkt_stop;
3295 
3296         /* Return path_instance information back to the target driver. */
3297         if (scsi_pkt_allocated_correctly(tpkt)) {
3298                 if (scsi_pkt_allocated_correctly(pkt)) {
3299                         /*
3300                          * If both packets were correctly allocated,
3301                          * return path returned by pHCI.
3302                          */
3303                         tpkt->pkt_path_instance = pkt->pkt_path_instance;
3304                 } else {
3305                         /* Otherwise return path of pHCI we used */
3306                         tpkt->pkt_path_instance =
3307                             mdi_pi_get_path_instance(lpath);
3308                 }
3309         }
3310 
3311         if (pkt->pkt_cdbp[0] == SCMD_PROUT &&
3312             ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_REGISTER) ||
3313             ((pkt->pkt_cdbp[1] & 0x1f) == VHCI_PROUT_R_AND_IGNORE)) {
3314                 if ((SCBP_C(pkt) != STATUS_GOOD) ||


4046                         }
4047 
4048                         /* Check for Reservation Conflict */
4049                         bp = scsi_alloc_consistent_buf(
4050                             &svp->svp_psd->sd_address, (struct buf *)NULL,
4051                             DEV_BSIZE, B_READ, NULL, NULL);
4052                         if (!bp) {
4053                                 VHCI_DEBUG(1, (CE_NOTE, NULL,
4054                                     "!vhci_update_pathstates: No resources "
4055                                     "(buf)\n"));
4056                                 mdi_rele_path(pip);
4057                                 goto done;
4058                         }
4059                         pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
4060                             CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
4061                             PKT_CONSISTENT, NULL, NULL);
4062                         if (pkt) {
4063                                 (void) scsi_setup_cdb((union scsi_cdb *)
4064                                     (uintptr_t)pkt->pkt_cdbp, SCMD_READ, 1, 1,
4065                                     0);
4066                                 pkt->pkt_time = 2 * vhci_io_time;
4067                                 pkt->pkt_flags = FLAG_NOINTR;
4068                                 pkt->pkt_path_instance =
4069                                     mdi_pi_get_path_instance(pip);
4070 
4071                                 if ((scsi_transport(pkt) == TRAN_ACCEPT) &&
4072                                     (pkt->pkt_reason == CMD_CMPLT) &&
4073                                     (SCBP_C(pkt) ==
4074                                     STATUS_RESERVATION_CONFLICT)) {
4075                                         VHCI_DEBUG(1, (CE_NOTE, NULL,
4076                                             "!vhci_update_pathstates: reserv. "
4077                                             "conflict to be resolved on 0x%p\n",
4078                                             (void *)pip));
4079                                         svp_conflict = svp;
4080                                 }
4081                                 scsi_destroy_pkt(pkt);
4082                         }
4083                         scsi_free_consistent_buf(bp);
4084                 } else if ((opinfo.opinfo_path_state == SCSI_PATH_INACTIVE) &&
4085                     !(MDI_PI_IS_STANDBY(pip))) {
4086                         VHCI_DEBUG(1, (CE_NOTE, NULL,


5311                 if ((vlun->svl_flags & VLUN_RESERVE_ACTIVE_FLG) == 0) {
5312                         /*
5313                          * Issue SCSI-2 RELEASE only for the first time on
5314                          * a new path just in case the host rebooted and
5315                          * a reservation is still pending on this path.
5316                          * IBM Shark storage does not clear RESERVE upon
5317                          * host reboot.
5318                          */
5319                         pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0,
5320                             sizeof (struct scsi_arq_status), 0, 0,
5321                             SLEEP_FUNC, NULL);
5322                         if (pkt == NULL) {
5323                                 VHCI_DEBUG(1, (CE_NOTE, NULL,
5324                                     "!vhci_pathinfo_online: "
5325                                     "Release init_pkt failed :%p\n",
5326                                     (void *)pip));
5327                                 rval = MDI_FAILURE;
5328                                 goto failure;
5329                         }
5330                         pkt->pkt_cdbp[0] = SCMD_RELEASE;
5331                         pkt->pkt_time = vhci_io_time;
5332 
5333                         VHCI_DEBUG(1, (CE_NOTE, NULL,
5334                             "!vhci_path_online: path:%p "
5335                             "Issued SCSI-2 RELEASE\n", (void *)pip));
5336 
5337                         /* Ignore the return value */
5338                         (void) vhci_do_scsi_cmd(pkt);
5339                         scsi_destroy_pkt(pkt);
5340                 }
5341         }
5342 
5343         rval = vhci_update_pathinfo(psd, pip, sfo, vlun, vhci);
5344         if (rval == MDI_FAILURE) {
5345                 goto failure;
5346         }
5347 
5348         /* Initialize MP-API data */
5349         vhci_update_mpapi_data(vhci, vlun, pip);
5350 
5351         /*


6238 
6239         case DEVCTL_DEVICE_RESET:
6240                 /*
6241                  * lookup and hold child device
6242                  */
6243                 if ((child = ndi_devi_find(self, ndi_dc_getname(dcp),
6244                     ndi_dc_getaddr(dcp))) == NULL) {
6245                         rv = ENXIO;
6246                         break;
6247                 }
6248                 retval = mdi_select_path(child, NULL,
6249                     (MDI_SELECT_ONLINE_PATH | MDI_SELECT_STANDBY_PATH),
6250                     NULL, &pip);
6251                 if ((retval != MDI_SUCCESS) || (pip == NULL)) {
6252                         VHCI_DEBUG(2, (CE_WARN, NULL, "!vhci_ioctl:"
6253                             "Unable to get a path, dip 0x%p", (void *)child));
6254                         rv = ENXIO;
6255                         break;
6256                 }
6257                 svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
6258 
6259                 VHCI_DEBUG(2, (CE_NOTE, NULL,
6260                     "!reset %s@%s on all available paths",
6261                     ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)));
6262 
6263                 if (vhci_scsi_reset_all_paths(&svp->svp_psd->sd_address) != 0) {
6264                         VHCI_DEBUG(2, (CE_WARN, NULL,
6265                             "!vhci_ioctl(pip:%p): reset failed\n",
6266                             (void *)pip));
6267                         rv = ENXIO;
6268                 }
6269                 mdi_rele_path(pip);
6270                 break;
6271 
6272         case DEVCTL_BUS_QUIESCE:
6273         case DEVCTL_BUS_UNQUIESCE:
6274         case DEVCTL_BUS_RESET:
6275         case DEVCTL_BUS_RESETALL:
6276 #ifdef  DEBUG
6277         case DEVCTL_BUS_CONFIGURE:
6278         case DEVCTL_BUS_UNCONFIGURE:
6279 #endif
6280                 rv = ENOTSUP;
6281                 break;
6282 
6283         default:
6284                 rv = ENOTTY;
6285         } /* end of outer switch */
6286 


7070                 check_condition = 0;
7071                 UA_condition = 0;
7072 
7073                 bp = scsi_alloc_consistent_buf(&svp->svp_psd->sd_address,
7074                     (struct buf *)NULL, DEV_BSIZE, B_READ, NULL, NULL);
7075                 if (!bp) {
7076                         VHCI_DEBUG(1, (CE_NOTE, NULL,
7077                             "vhci_failover !No resources (buf)\n"));
7078                         mdi_rele_path(npip);
7079                         goto done;
7080                 }
7081                 pkt = scsi_init_pkt(&svp->svp_psd->sd_address, NULL, bp,
7082                     CDB_GROUP1, sizeof (struct scsi_arq_status), 0,
7083                     PKT_CONSISTENT, NULL, NULL);
7084                 if (pkt) {
7085                         (void) scsi_setup_cdb((union scsi_cdb *)(uintptr_t)
7086                             pkt->pkt_cdbp, SCMD_READ, 1, 1, 0);
7087                         pkt->pkt_flags = FLAG_NOINTR;
7088 check_path_again:
7089                         pkt->pkt_path_instance = mdi_pi_get_path_instance(npip);
7090                         pkt->pkt_time = 2 * vhci_io_time;
7091 
7092                         if (scsi_transport(pkt) == TRAN_ACCEPT) {
7093                                 switch (pkt->pkt_reason) {
7094                                 case CMD_CMPLT:
7095                                         switch (SCBP_C(pkt)) {
7096                                         case STATUS_GOOD:
7097                                                 /* Already failed over */
7098                                                 activation_done = 1;
7099                                                 break;
7100                                         case STATUS_RESERVATION_CONFLICT:
7101                                                 reserve_pending = 1;
7102                                                 break;
7103                                         case STATUS_CHECK:
7104                                                 check_condition = 1;
7105                                                 break;
7106                                         }
7107                                 }
7108                         }
7109                         if (check_condition &&
7110                             (pkt->pkt_state & STATE_ARQ_DONE)) {


8431             "vhci_uscsi_send_sense: enter: bp: %p pkt: %p scmd: %p",
8432             (void *)cmdbp, (void *)pkt, (void *)mp_uscmdp));
8433         /* set up the packet information and cdb */
8434         if ((rqbp = scsi_alloc_consistent_buf(mp_uscmdp->ap, NULL,
8435             SENSE_LENGTH, B_READ, NULL, NULL)) == NULL) {
8436                 return (-1);
8437         }
8438 
8439         if ((rqpkt = scsi_init_pkt(mp_uscmdp->ap, NULL, rqbp,
8440             CDB_GROUP0, 1, 0, PKT_CONSISTENT, NULL, NULL)) == NULL) {
8441                 scsi_free_consistent_buf(rqbp);
8442                 return (-1);
8443         }
8444 
8445         (void) scsi_setup_cdb((union scsi_cdb *)(intptr_t)rqpkt->pkt_cdbp,
8446             SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
8447 
8448         mp_uscmdp->rqbp = rqbp;
8449         rqbp->b_private = mp_uscmdp;
8450         rqpkt->pkt_flags |= FLAG_SENSING;
8451         rqpkt->pkt_time = vhci_io_time;
8452         rqpkt->pkt_comp = vhci_uscsi_iodone;
8453         rqpkt->pkt_private = mp_uscmdp;
8454 
8455         /*
8456          * NOTE: This code path is related to MPAPI uscsi(7I), so path
8457          * selection is not based on path_instance.
8458          */
8459         if (scsi_pkt_allocated_correctly(rqpkt))
8460                 rqpkt->pkt_path_instance = 0;
8461 
8462         switch (scsi_transport(rqpkt)) {
8463         case TRAN_ACCEPT:
8464                 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8465                     "transport accepted."));
8466                 break;
8467         case TRAN_BUSY:
8468                 VHCI_DEBUG(1, (CE_NOTE, NULL, "vhci_uscsi_send_sense: "
8469                     "transport busy, setting timeout."));
8470                 vhci_restart_timeid = timeout(vhci_uscsi_restart_sense, rqpkt,
8471                     (drv_usectohz(5 * 1000000)));


8646         uscmdp = mp_uscmdp->uscmdp;
8647         if (uscmdp->uscsi_flags & USCSI_RQENABLE) {
8648                 stat_size = SENSE_LENGTH;
8649         } else {
8650                 stat_size = 1;
8651         }
8652 
8653         pkt = scsi_init_pkt(mp_uscmdp->ap, NULL, bp, uscmdp->uscsi_cdblen,
8654             stat_size, 0, 0, SLEEP_FUNC, NULL);
8655         if (pkt == NULL) {
8656                 VHCI_DEBUG(4, (CE_NOTE, NULL,
8657                     "vhci_uscsi_iostart: rval: EINVAL"));
8658                 bp->b_resid = bp->b_bcount;
8659                 uscmdp->uscsi_resid = bp->b_bcount;
8660                 bioerror(bp, EINVAL);
8661                 biodone(bp);
8662                 return (EINVAL);
8663         }
8664 
8665         pkt->pkt_time = uscmdp->uscsi_timeout;
8666         if (pkt->pkt_time == 0)
8667                 pkt->pkt_time = vhci_io_time;
8668 
8669         bcopy(uscmdp->uscsi_cdb, pkt->pkt_cdbp, (size_t)uscmdp->uscsi_cdblen);
8670         pkt->pkt_comp = vhci_uscsi_iodone;
8671         pkt->pkt_private = mp_uscmdp;
8672         if (uscmdp->uscsi_flags & USCSI_SILENT)
8673                 pkt->pkt_flags |= FLAG_SILENT;
8674         if (uscmdp->uscsi_flags & USCSI_ISOLATE)
8675                 pkt->pkt_flags |= FLAG_ISOLATE;
8676         if (uscmdp->uscsi_flags & USCSI_DIAGNOSE)
8677                 pkt->pkt_flags |= FLAG_DIAGNOSE;
8678         if (uscmdp->uscsi_flags & USCSI_RENEGOT) {
8679                 pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
8680         }
8681         VHCI_DEBUG(4, (CE_WARN, NULL,
8682             "vhci_uscsi_iostart: ap: %p pkt: %p pcdbp: %p uscmdp: %p"
8683             " ucdbp: %p pcdblen: %d bp: %p count: %ld pip: %p"
8684             " stat_size: %d",
8685             (void *)mp_uscmdp->ap, (void *)pkt, (void *)pkt->pkt_cdbp,
8686             (void *)uscmdp, (void *)uscmdp->uscsi_cdb, pkt->pkt_cdblen,
8687             (void *)bp, bp->b_bcount, (void *)mp_uscmdp->pip, stat_size));
8688