From: Joe Handzik <joseph.t.hand...@hp.com>

improve ioaccel2 error handling, including better handling of
underrun statuses

Reviewed-by: Scott Teel <scott.t...@pmcs.com>
Reviewed-by: Kevin Barnett <kevin.barn...@pmcs.com>
Signed-off-by: Joe Handzik <joseph.t.hand...@hp.com>
Signed-off-by: Don Brace <don.br...@pmcs.com>
---
 drivers/scsi/hpsa.c     |   33 ++++++++++++++++++++++++++++-----
 drivers/scsi/hpsa_cmd.h |    6 ++++++
 2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 0a3ea37..ba89375a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1898,6 +1898,7 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h,
 {
        int data_len;
        int retry = 0;
+       u32 ioaccel2_resid = 0;
 
        switch (c2->error_data.serv_response) {
        case IOACCEL2_SERV_RESPONSE_COMPLETE:
@@ -1956,11 +1957,33 @@ static int handle_ioaccel_mode2_error(struct ctlr_info 
*h,
                }
                break;
        case IOACCEL2_SERV_RESPONSE_FAILURE:
-               /* don't expect to get here. */
-               dev_warn(&h->pdev->dev,
-                       "unexpected delivery or target failure, status = 
0x%02x\n",
-                       c2->error_data.status);
-               retry = 1;
+               switch (c2->error_data.status) {
+               case IOACCEL2_STATUS_SR_IO_ERROR:
+               case IOACCEL2_STATUS_SR_IO_ABORTED:
+               case IOACCEL2_STATUS_SR_OVERRUN:
+                       retry = 1;
+                       break;
+               case IOACCEL2_STATUS_SR_UNDERRUN:
+                       cmd->result = (DID_OK << 16);           /* host byte */
+                       cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
+                       ioaccel2_resid = c2->error_data.resid_cnt[3] << 24;
+                       ioaccel2_resid |= c2->error_data.resid_cnt[2] << 16;
+                       ioaccel2_resid |= c2->error_data.resid_cnt[1] << 8;
+                       ioaccel2_resid |= c2->error_data.resid_cnt[0];
+                       scsi_set_resid(cmd, ioaccel2_resid);
+                       break;
+               case IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE:
+               case IOACCEL2_STATUS_SR_INVALID_DEVICE:
+               case IOACCEL2_STATUS_SR_IOACCEL_DISABLED:
+                       /* We will get an event from ctlr to trigger rescan */
+                       retry = 1;
+                       break;
+               default:
+                       retry = 1;
+                       dev_warn(&h->pdev->dev,
+                               "unexpected delivery or target failure, status 
= 0x%02x\n",
+                               c2->error_data.status);
+               }
                break;
        case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE:
                break;
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 0efb6f2b..cecb62b 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -532,6 +532,12 @@ struct io_accel2_scsi_response {
 #define IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL  0x28
 #define IOACCEL2_STATUS_SR_TASK_COMP_ABORTED   0x40
 #define IOACCEL2_STATUS_SR_IOACCEL_DISABLED    0x0E
+#define IOACCEL2_STATUS_SR_IO_ERROR            0x01
+#define IOACCEL2_STATUS_SR_IO_ABORTED          0x02
+#define IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE   0x03
+#define IOACCEL2_STATUS_SR_INVALID_DEVICE      0x04
+#define IOACCEL2_STATUS_SR_UNDERRUN            0x51
+#define IOACCEL2_STATUS_SR_OVERRUN             0x75
        u8 data_present;                /* low 2 bits */
 #define IOACCEL2_NO_DATAPRESENT                0x000
 #define IOACCEL2_RESPONSE_DATAPRESENT  0x001

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to