--- old/usr/src/uts/common/io/scsi/targets/sd.c	Tue Jul  3 21:12:49 2018
+++ new/usr/src/uts/common/io/scsi/targets/sd.c	Tue Jul  3 21:12:49 2018
@@ -8551,26 +8551,31 @@
 	dev_t			dev;
 	dev_info_t		*pdip = ddi_get_parent(devi);
 	int			instance = ddi_get_instance(devi);
+	int			devigone = DEVI(devi)->devi_gone;
 
 	mutex_enter(&sd_detach_mutex);
 
 	/*
 	 * Fail the detach for any of the following:
-	 *  - Unable to get the sd_lun struct for the instance
-	 *  - A layered driver has an outstanding open on the instance
-	 *  - Another thread is already detaching this instance
-	 *  - Another thread is currently performing an open
+	 * - Unable to get the sd_lun struct for the instance
+	 * - Another thread is already detaching this instance
+	 * - Another thread is currently performing an open
+	 *
+	 * Additionaly, if "device gone" flag is not set:
+	 * - There are outstanding commands in driver
+	 * - There are outstanding commands in transport
 	 */
 	devp = ddi_get_driver_private(devi);
-	if ((devp == NULL) ||
-	    ((un = (struct sd_lun *)devp->sd_private) == NULL) ||
-	    (un->un_ncmds_in_driver != 0) || (un->un_layer_count != 0) ||
-	    (un->un_detach_count != 0) || (un->un_opens_in_progress != 0)) {
+	if (devp == NULL || (un = (struct sd_lun *)devp->sd_private) == NULL ||
+	    un->un_detach_count != 0 || un->un_opens_in_progress != 0 ||
+	    (!devigone && (un->un_ncmds_in_driver != 0 ||
+	    un->un_ncmds_in_transport != 0 ||
+	    un->un_state == SD_STATE_RWAIT))) {
 		mutex_exit(&sd_detach_mutex);
 		return (DDI_FAILURE);
 	}
 
-	SD_TRACE(SD_LOG_ATTACH_DETACH, un, "sd_unit_detach: entry 0x%p\n", un);
+	SD_TRACE(SD_LOG_ATTACH_DETACH, un, "%s: entry 0x%p\n", __func__, un);
 
 	/*
 	 * Mark this instance as currently in a detach, to inhibit any
@@ -8584,10 +8589,6 @@
 
 	dev = sd_make_device(SD_DEVINFO(un));
 
-#ifndef lint
-	_NOTE(COMPETING_THREADS_NOW);
-#endif
-
 	mutex_enter(SD_MUTEX(un));
 
 	/*
@@ -8601,24 +8602,10 @@
 	}
 
 	/*
-	 * Verify there are NO outstanding commands issued to this device.
-	 * ie, un_ncmds_in_transport == 0.
-	 * It's possible to have outstanding commands through the physio
-	 * code path, even though everything's closed.
-	 */
-	if ((un->un_ncmds_in_transport != 0) || (un->un_retry_timeid != NULL) ||
-	    (un->un_direct_priority_timeid != NULL) ||
-	    (un->un_state == SD_STATE_RWAIT)) {
-		mutex_exit(SD_MUTEX(un));
-		SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-		    "sd_dr_detach: Detach failure due to outstanding cmds\n");
-		goto err_stillbusy;
-	}
-
-	/*
 	 * If we have the device reserved, release the reservation.
 	 */
-	if ((un->un_resvd_status & SD_RESERVE) &&
+	if (!devigone &&
+	    (un->un_resvd_status & SD_RESERVE) &&
 	    !(un->un_resvd_status & SD_LOST_RESERVE)) {
 		mutex_exit(SD_MUTEX(un));
 		/*
@@ -8627,7 +8614,7 @@
 		 */
 		if (sd_reserve_release(dev, SD_RELEASE) != 0) {
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-			    "sd_dr_detach: Cannot release reservation \n");
+			    "%s: cannot release reservation\n", __func__);
 		}
 	} else {
 		mutex_exit(SD_MUTEX(un));
@@ -8684,6 +8671,13 @@
 	sd_rmv_resv_reclaim_req(dev);
 
 	mutex_enter(SD_MUTEX(un));
+	if (un->un_retry_timeid != NULL) {
+		timeout_id_t temp_id = un->un_retry_timeid;
+		un->un_retry_timeid = NULL;
+		mutex_exit(SD_MUTEX(un));
+		(void) untimeout(temp_id);
+		mutex_enter(SD_MUTEX(un));
+	}
 
 	/* Cancel any pending callbacks for SD_PATH_DIRECT_PRIORITY cmd. */
 	if (un->un_direct_priority_timeid != NULL) {
@@ -8701,7 +8695,7 @@
 		if (scsi_watch_request_terminate(un->un_mhd_token,
 		    SCSI_WATCH_TERMINATE_NOWAIT)) {
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-			    "sd_dr_detach: Cannot cancel mhd watch request\n");
+			    "%s: cannot cancel mhd watch request\n", __func__);
 			/*
 			 * Note: We are returning here after having removed
 			 * some driver timeouts above. This is consistent with
@@ -8720,7 +8714,7 @@
 		if (scsi_watch_request_terminate(un->un_swr_token,
 		    SCSI_WATCH_TERMINATE_NOWAIT)) {
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-			    "sd_dr_detach: Cannot cancel swr watch request\n");
+			    "%s: cannot cancel swr watch request\n", __func__);
 			/*
 			 * Note: We are returning here after having removed
 			 * some driver timeouts above. This is consistent with
@@ -8733,13 +8727,12 @@
 		un->un_swr_token = NULL;
 	}
 
-	mutex_exit(SD_MUTEX(un));
-
 	/*
 	 * Clear any scsi_reset_notifies. We clear the reset notifies
 	 * if we have not registered one.
 	 * Note: The sd_mhd_reset_notify_cb() fn tries to acquire SD_MUTEX!
 	 */
+	mutex_exit(SD_MUTEX(un));
 	(void) scsi_reset_notify(SD_ADDRESS(un), SCSI_RESET_CANCEL,
 	    sd_mhd_reset_notify_cb, (caddr_t)un);
 
@@ -8791,9 +8784,9 @@
 		    (pm_lower_power(SD_DEVINFO(un), 0, SD_PM_STATE_STOPPED(un))
 		    != DDI_SUCCESS)) {
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-		    "sd_dr_detach: Lower power request failed, ignoring.\n");
+			    "%s: lower power request failed, ignoring\n",
+			    __func__);
 			/*
-			 * Fix for bug: 4297749, item # 13
 			 * The above test now includes a check to see if PM is
 			 * supported by this device before call
 			 * pm_lower_power().
@@ -8856,7 +8849,7 @@
 			 * be the right thing to do.
 			 */
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-			    "sd_dr_detach: Cannot cancel insert event\n");
+			    "%s: cannot cancel insert event\n", __func__);
 			goto err_remove_event;
 		}
 		un->un_insert_event = NULL;
@@ -8871,7 +8864,7 @@
 			 * be the right thing to do.
 			 */
 			SD_ERROR(SD_LOG_ATTACH_DETACH, un,
-			    "sd_dr_detach: Cannot cancel remove event\n");
+			    "%s: cannot cancel remove event\n", __func__);
 			goto err_remove_event;
 		}
 		un->un_remove_event = NULL;
@@ -9014,7 +9007,7 @@
 	un->un_detach_count--;
 	mutex_exit(&sd_detach_mutex);
 
-	SD_TRACE(SD_LOG_ATTACH_DETACH, un, "sd_unit_detach: exit failure\n");
+	SD_TRACE(SD_LOG_ATTACH_DETACH, un, "%s: exit failure\n", __func__);
 	return (DDI_FAILURE);
 }
 
