scsi: ses: Retry failed Send/Receive Diagnostic commands
authorWen Xiong <wenxiong@linux.ibm.com>
Fri, 17 Sep 2021 03:24:21 +0000 (22:24 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 9 Oct 2021 12:40:57 +0000 (14:40 +0200)
[ Upstream commit fbdac19e642899455b4e64c63aafe2325df7aafa ]

Setting SCSI logging level with error=3, we saw some errors from enclosues:

[108017.360833] ses 0:0:9:0: tag#641 Done: NEEDS_RETRY Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK cmd_age=0s
[108017.360838] ses 0:0:9:0: tag#641 CDB: Receive Diagnostic 1c 01 01 00 20 00
[108017.427778] ses 0:0:9:0: Power-on or device reset occurred
[108017.427784] ses 0:0:9:0: tag#641 Done: SUCCESS Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s
[108017.427788] ses 0:0:9:0: tag#641 CDB: Receive Diagnostic 1c 01 01 00 20 00
[108017.427791] ses 0:0:9:0: tag#641 Sense Key : Unit Attention [current]
[108017.427793] ses 0:0:9:0: tag#641 Add. Sense: Bus device reset function occurred
[108017.427801] ses 0:0:9:0: Failed to get diagnostic page 0x1
[108017.427804] ses 0:0:9:0: Failed to bind enclosure -19
[108017.427895] ses 0:0:10:0: Attached Enclosure device
[108017.427942] ses 0:0:10:0: Attached scsi generic sg18 type 13

Retry if the Send/Receive Diagnostic commands complete with a transient
error status (NOT_READY or UNIT_ATTENTION with ASC 0x29).

Link: https://lore.kernel.org/r/1631849061-10210-2-git-send-email-wenxiong@linux.ibm.com
Reviewed-by: Brian King <brking@linux.ibm.com>
Reviewed-by: James Bottomley <jejb@linux.ibm.com>
Signed-off-by: Wen Xiong <wenxiong@linux.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/ses.c

index c2afba2..43e6822 100644 (file)
@@ -87,9 +87,16 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
                0
        };
        unsigned char recv_page_code;
+       unsigned int retries = SES_RETRIES;
+       struct scsi_sense_hdr sshdr;
+
+       do {
+               ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+                                      &sshdr, SES_TIMEOUT, 1, NULL);
+       } while (ret > 0 && --retries && scsi_sense_valid(&sshdr) &&
+                (sshdr.sense_key == NOT_READY ||
+                 (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
 
-       ret =  scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
-                               NULL, SES_TIMEOUT, SES_RETRIES, NULL);
        if (unlikely(ret))
                return ret;
 
@@ -121,9 +128,16 @@ static int ses_send_diag(struct scsi_device *sdev, int page_code,
                bufflen & 0xff,
                0
        };
+       struct scsi_sense_hdr sshdr;
+       unsigned int retries = SES_RETRIES;
+
+       do {
+               result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
+                                         &sshdr, SES_TIMEOUT, 1, NULL);
+       } while (result > 0 && --retries && scsi_sense_valid(&sshdr) &&
+                (sshdr.sense_key == NOT_READY ||
+                 (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
 
-       result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
-                                 NULL, SES_TIMEOUT, SES_RETRIES, NULL);
        if (result)
                sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n",
                            result);