--- old/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c	Mon Aug  5 17:31:33 2019
+++ new/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c	Mon Aug  5 17:31:33 2019
@@ -18,11 +18,10 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-/*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.
  * Copyright (c) 2016 by Delphix. All rights reserved.
  */
 
@@ -54,6 +53,11 @@
 int vhci_prout_not_ready_retry = 180;
 
 /*
+ * Timeout in seconds for SCSI commands used by vHCI.
+ */
+int vhci_io_time = 30;
+
+/*
  * These values are defined to support the internal retry of
  * SCSI packets for better sense code handling.
  */
@@ -132,6 +136,7 @@
 static int vhci_scsi_reset_target(struct scsi_address *, int level,
     uint8_t select_path);
 static int vhci_scsi_reset_bus(struct scsi_address *);
+static int vhci_scsi_reset_all_paths(struct scsi_address *);
 static int vhci_scsi_getcap(struct scsi_address *, char *, int);
 static int vhci_scsi_setcap(struct scsi_address *, char *, int, int);
 static int vhci_commoncap(struct scsi_address *, char *, int, int, int);
@@ -1386,7 +1391,7 @@
 			}
 
 			rel_pkt->pkt_cdbp[0] = SCMD_RELEASE;
-			rel_pkt->pkt_time = 60;
+			rel_pkt->pkt_time = vhci_io_time;
 
 			/*
 			 * Ignore the return value.  If it will fail
@@ -1535,20 +1540,16 @@
  *		   1 - reset succeeded
  */
 
-/* ARGSUSED */
 static int
 vhci_scsi_reset(struct scsi_address *ap, int level)
 {
-	int rval = 0;
-
-	cmn_err(CE_WARN, "!vhci_scsi_reset 0x%x", level);
 	if ((level == RESET_TARGET) || (level == RESET_LUN)) {
 		return (vhci_scsi_reset_target(ap, level, TRUE));
 	} else if (level == RESET_ALL) {
 		return (vhci_scsi_reset_bus(ap));
+	} else {
+		return (0);
 	}
-
-	return (rval);
 }
 
 /*
@@ -1614,7 +1615,7 @@
 static int
 vhci_scsi_reset_target(struct scsi_address *ap, int level, uint8_t select_path)
 {
-	dev_info_t		*vdip, *cdip;
+	dev_info_t		*vdip, *cdip = NULL;
 	mdi_pathinfo_t		*pip = NULL;
 	mdi_pathinfo_t		*npip = NULL;
 	int			rval = -1;
@@ -1634,7 +1635,14 @@
 		return (scsi_reset(ap, level));
 	}
 
-	cdip = ADDR2DIP(ap);
+	/*
+	 * SCSI address should be interpreted according to the pHBA flags.
+	 */
+	if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
+		cdip = ADDR2DIP(ap);
+	else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
+		cdip = ap->a_hba_tran->tran_sd->sd_dev;
+
 	ASSERT(cdip != NULL);
 	vdip = ddi_get_parent(cdip);
 	ASSERT(vdip != NULL);
@@ -1705,7 +1713,6 @@
 	return (0);
 }
 
-
 /* ARGSUSED */
 static int
 vhci_scsi_reset_bus(struct scsi_address *ap)
@@ -1713,7 +1720,104 @@
 	return (1);
 }
 
+/*
+ * This is a special version of LUN reset routine
+ * which sends a reset down all available paths.
+ */
+static int
+vhci_scsi_reset_all_paths(struct scsi_address *ap)
+{
+	dev_info_t		*vdip, *cdip = NULL;
+	mdi_pathinfo_t		*pip = NULL;
+	mdi_pathinfo_t		*npip = NULL;
+	int			rval = -1;
+	scsi_vhci_priv_t	*svp = NULL;
+	struct scsi_address	*pap = NULL;
+	scsi_hba_tran_t		*hba = NULL;
+	int			sps = MDI_SUCCESS;
+	int			reset_result = 0;
+	struct scsi_vhci	*vhci = NULL;
 
+	/*
+	 * SCSI address should be interpreted according to the pHBA flags.
+	 */
+	if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX)
+		cdip = ADDR2DIP(ap);
+	else if (ap->a_hba_tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
+		cdip = ap->a_hba_tran->tran_sd->sd_dev;
+
+	if (cdip == NULL || (vdip = ddi_get_parent(cdip)) == NULL ||
+	    (vhci = ddi_get_soft_state(vhci_softstate,
+		ddi_get_instance(vdip))) == NULL) {
+		VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
+		    "Child info pointer NULL, cdip 0x%p",
+		    __func__, (void *)cdip));
+		return (0);
+	}
+
+	rval = mdi_select_path(cdip, NULL, MDI_SELECT_ONLINE_PATH, NULL, &pip);
+	if ((rval != MDI_SUCCESS) || (pip == NULL)) {
+		VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
+		    "Unable to get a path, dip 0x%p",
+		    __func__, (void *)cdip));
+		return (0);
+	}
+again:
+	svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
+
+	if (svp == NULL || svp->svp_psd == NULL) {
+		VHCI_DEBUG(2, (CE_WARN, NULL, "!%s: "
+		    "private data is NULL, pip 0x%p",
+		    __func__, (void *)pip));
+		mdi_rele_path(pip);
+		return (0);
+	}
+
+	pap = &svp->svp_psd->sd_address;
+	hba = pap->a_hba_tran;
+
+	if (pap != NULL && hba != NULL && hba->tran_reset != NULL) {
+		/*
+		 * The following sends reset down all available paths
+		 */
+		if (sps == MDI_SUCCESS) {
+			reset_result = hba->tran_reset(pap, RESET_LUN);
+
+			VHCI_DEBUG(2, (CE_WARN, vdip, "!%s%d: "
+			    "path %s, reset LUN %s",
+			    ddi_driver_name(cdip), ddi_get_instance(cdip),
+			    mdi_pi_spathname(pip),
+			    (reset_result ? "Success" : "Failed")));
+
+			/*
+			 * Select next path and issue the reset, repeat
+			 * until all paths are exhausted regardless of success
+			 * or failure of the previous reset.
+			 */
+			sps = mdi_select_path(cdip, NULL,
+			    MDI_SELECT_ONLINE_PATH, pip, &npip);
+			if ((sps != MDI_SUCCESS) || (npip == NULL)) {
+				mdi_rele_path(pip);
+				return (0);
+			}
+			mdi_rele_path(pip);
+			pip = npip;
+			goto again;
+		}
+		mdi_rele_path(pip);
+		mutex_enter(&vhci->vhci_mutex);
+		scsi_hba_reset_notify_callback(&vhci->vhci_mutex,
+		    &vhci->vhci_reset_notify_listf);
+		mutex_exit(&vhci->vhci_mutex);
+		VHCI_DEBUG(6, (CE_NOTE, NULL, "!vhci_scsi_reset_target: "
+		    "reset %d sent down pip:%p for cdip:%p\n", RESET_LUN,
+		    (void *)pip, (void *)cdip));
+		return (1);
+	}
+	mdi_rele_path(pip);
+	return (0);
+}
+
 /*
  * called by vhci_getcap and vhci_setcap to get and set (respectively)
  * SCSI capabilities
@@ -3186,6 +3290,8 @@
 	tpkt->pkt_state = pkt->pkt_state;
 	tpkt->pkt_statistics = pkt->pkt_statistics;
 	tpkt->pkt_reason = pkt->pkt_reason;
+	tpkt->pkt_start = pkt->pkt_start;
+	tpkt->pkt_stop = pkt->pkt_stop;
 
 	/* Return path_instance information back to the target driver. */
 	if (scsi_pkt_allocated_correctly(tpkt)) {
@@ -3957,7 +4063,7 @@
 				(void) scsi_setup_cdb((union scsi_cdb *)
 				    (uintptr_t)pkt->pkt_cdbp, SCMD_READ, 1, 1,
 				    0);
-				pkt->pkt_time = 3*30;
+				pkt->pkt_time = 2 * vhci_io_time;
 				pkt->pkt_flags = FLAG_NOINTR;
 				pkt->pkt_path_instance =
 				    mdi_pi_get_path_instance(pip);
@@ -5222,7 +5328,7 @@
 				goto failure;
 			}
 			pkt->pkt_cdbp[0] = SCMD_RELEASE;
-			pkt->pkt_time = 60;
+			pkt->pkt_time = vhci_io_time;
 
 			VHCI_DEBUG(1, (CE_NOTE, NULL,
 			    "!vhci_path_online: path:%p "
@@ -6149,12 +6255,15 @@
 			break;
 		}
 		svp = (scsi_vhci_priv_t *)mdi_pi_get_vhci_private(pip);
-		if (vhci_recovery_reset(svp->svp_svl,
-		    &svp->svp_psd->sd_address, TRUE,
-		    VHCI_DEPTH_TARGET) == 0) {
-			VHCI_DEBUG(1, (CE_NOTE, NULL,
-			    "!vhci_ioctl(pip:%p): "
-			    "reset failed\n", (void *)pip));
+
+		VHCI_DEBUG(2, (CE_NOTE, NULL,
+		    "!reset %s@%s on all available paths",
+		    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)));
+
+		if (vhci_scsi_reset_all_paths(&svp->svp_psd->sd_address) != 0) {
+			VHCI_DEBUG(2, (CE_WARN, NULL,
+			    "!vhci_ioctl(pip:%p): reset failed\n",
+			    (void *)pip));
 			rv = ENXIO;
 		}
 		mdi_rele_path(pip);
@@ -6978,7 +7087,7 @@
 			pkt->pkt_flags = FLAG_NOINTR;
 check_path_again:
 			pkt->pkt_path_instance = mdi_pi_get_path_instance(npip);
-			pkt->pkt_time = 3*30;
+			pkt->pkt_time = 2 * vhci_io_time;
 
 			if (scsi_transport(pkt) == TRAN_ACCEPT) {
 				switch (pkt->pkt_reason) {
@@ -8339,7 +8448,7 @@
 	mp_uscmdp->rqbp = rqbp;
 	rqbp->b_private = mp_uscmdp;
 	rqpkt->pkt_flags |= FLAG_SENSING;
-	rqpkt->pkt_time = 60;
+	rqpkt->pkt_time = vhci_io_time;
 	rqpkt->pkt_comp = vhci_uscsi_iodone;
 	rqpkt->pkt_private = mp_uscmdp;
 
@@ -8554,6 +8663,9 @@
 	}
 
 	pkt->pkt_time = uscmdp->uscsi_timeout;
+	if (pkt->pkt_time == 0)
+		pkt->pkt_time = vhci_io_time;
+
 	bcopy(uscmdp->uscsi_cdb, pkt->pkt_cdbp, (size_t)uscmdp->uscsi_cdblen);
 	pkt->pkt_comp = vhci_uscsi_iodone;
 	pkt->pkt_private = mp_uscmdp;
