scsi: mpi3mr: Avoid escalating to higher level reset when target is removed
authorRanjan Kumar <ranjan.kumar@broadcom.com>
Thu, 16 Mar 2023 11:02:05 +0000 (16:32 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 17 Mar 2023 03:54:29 +0000 (23:54 -0400)
SCSI error handling has taken place for timed out I/Os on a drive and the
corresponding drive is removed. Stop escalating to higher level of reset by
returning the TUR with "I_T NEXUS LOSS OCCURRED" sense key.

Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
Link: https://lore.kernel.org/r/20230316110209.60145-5-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpi3mr/mpi3mr_os.c

index 7ebd00dfd3965b40e25ee631a6a36d2c5558c166..b5daa76e8628373c7b61e4362e6c697dea93b3ee 100644 (file)
@@ -4015,10 +4015,14 @@ static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd)
        stgt_priv_data = sdev_priv_data->tgt_priv_data;
        dev_handle = stgt_priv_data->dev_handle;
        if (stgt_priv_data->dev_removed) {
+               struct scmd_priv *cmd_priv = scsi_cmd_priv(scmd);
                sdev_printk(KERN_INFO, scmd->device,
                    "%s:target(handle = 0x%04x) is removed, target reset is not issued\n",
                    mrioc->name, dev_handle);
-               retval = FAILED;
+               if (!cmd_priv->in_lld_scope || cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID)
+                       retval = SUCCESS;
+               else
+                       retval = FAILED;
                goto out;
        }
        sdev_printk(KERN_INFO, scmd->device,
@@ -4083,10 +4087,14 @@ static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd)
        stgt_priv_data = sdev_priv_data->tgt_priv_data;
        dev_handle = stgt_priv_data->dev_handle;
        if (stgt_priv_data->dev_removed) {
+               struct scmd_priv *cmd_priv = scsi_cmd_priv(scmd);
                sdev_printk(KERN_INFO, scmd->device,
                    "%s: device(handle = 0x%04x) is removed, device(LUN) reset is not issued\n",
                    mrioc->name, dev_handle);
-               retval = FAILED;
+               if (!cmd_priv->in_lld_scope || cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID)
+                       retval = SUCCESS;
+               else
+                       retval = FAILED;
                goto out;
        }
        sdev_printk(KERN_INFO, scmd->device,
@@ -4644,13 +4652,24 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
                goto out;
        }
 
+       stgt_priv_data = sdev_priv_data->tgt_priv_data;
+       dev_handle = stgt_priv_data->dev_handle;
+
+       /* Avoid error handling escalation when device is removed or blocked */
+
+       if (scmd->device->host->shost_state == SHOST_RECOVERY &&
+               scmd->cmnd[0] == TEST_UNIT_READY &&
+               (stgt_priv_data->dev_removed || (dev_handle == MPI3MR_INVALID_DEV_HANDLE))) {
+               scsi_build_sense(scmd, 0, UNIT_ATTENTION, 0x29, 0x07);
+               scsi_done(scmd);
+               goto out;
+       }
+
        if (mrioc->reset_in_progress) {
                retval = SCSI_MLQUEUE_HOST_BUSY;
                goto out;
        }
 
-       stgt_priv_data = sdev_priv_data->tgt_priv_data;
-
        if (atomic_read(&stgt_priv_data->block_io)) {
                if (mrioc->stop_drv_processing) {
                        scmd->result = DID_NO_CONNECT << 16;
@@ -4661,7 +4680,6 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
                goto out;
        }
 
-       dev_handle = stgt_priv_data->dev_handle;
        if (dev_handle == MPI3MR_INVALID_DEV_HANDLE) {
                scmd->result = DID_NO_CONNECT << 16;
                scsi_done(scmd);