[SCSI] mptspi: Fix for incorrect data underrun errata
authorKashyap, Desai <kashyap.desai@lsi.com>
Wed, 7 Oct 2009 05:57:40 +0000 (11:27 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Thu, 29 Oct 2009 17:03:24 +0000 (13:03 -0400)
Errata:
Certain conditions on the scsi bus may casue the 53C1030 to incorrectly signal
a SCSI_DATA_UNDERRUN to the host.

Workaround 1:
For an Errata on LSI53C1030 When the length of request data
and transfer data are different with result of command (READ or VERIFY),
DID_SOFT_ERROR is set.

Workaround 2:
For potential trouble on LSI53C1030. It is checked whether the length of
request data is equal to the length of transfer and residual.
MEDIUM_ERROR is set by incorrect data.

Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/message/fusion/mptscsih.c

index c295786..f68ec48 100644 (file)
@@ -792,11 +792,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                         *  precedence!
                         */
                        sc->result = (DID_OK << 16) | scsi_status;
-                       if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
-                               /* Have already saved the status and sense data
+                       if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
+
+                               /*
+                                * For an Errata on LSI53C1030
+                                * When the length of request data
+                                * and transfer data are different
+                                * with result of command (READ or VERIFY),
+                                * DID_SOFT_ERROR is set.
                                 */
-                               ;
-                       } else {
+                               if (ioc->bus_type == SPI) {
+                                       if (pScsiReq->CDB[0] == READ_6  ||
+                                           pScsiReq->CDB[0] == READ_10 ||
+                                           pScsiReq->CDB[0] == READ_12 ||
+                                           pScsiReq->CDB[0] == READ_16 ||
+                                           pScsiReq->CDB[0] == VERIFY  ||
+                                           pScsiReq->CDB[0] == VERIFY_16) {
+                                               if (scsi_bufflen(sc) !=
+                                                       xfer_cnt) {
+                                                       sc->result =
+                                                       DID_SOFT_ERROR << 16;
+                                                   printk(KERN_WARNING "Errata"
+                                                   "on LSI53C1030 occurred."
+                                                   "sc->req_bufflen=0x%02x,"
+                                                   "xfer_cnt=0x%02x\n",
+                                                   scsi_bufflen(sc),
+                                                   xfer_cnt);
+                                               }
+                                       }
+                               }
+
                                if (xfer_cnt < sc->underflow) {
                                        if (scsi_status == SAM_STAT_BUSY)
                                                sc->result = SAM_STAT_BUSY;
@@ -835,7 +860,58 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        sc->result = (DID_OK << 16) | scsi_status;
                        if (scsi_state == 0) {
                                ;
-                       } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+                       } else if (scsi_state &
+                           MPI_SCSI_STATE_AUTOSENSE_VALID) {
+
+                               /*
+                                * For potential trouble on LSI53C1030.
+                                * (date:2007.xx.)
+                                * It is checked whether the length of
+                                * request data is equal to
+                                * the length of transfer and residual.
+                                * MEDIUM_ERROR is set by incorrect data.
+                                */
+                               if ((ioc->bus_type == SPI) &&
+                                       (sc->sense_buffer[2] & 0x20)) {
+                                       u32      difftransfer;
+                                       difftransfer =
+                                       sc->sense_buffer[3] << 24 |
+                                       sc->sense_buffer[4] << 16 |
+                                       sc->sense_buffer[5] << 8 |
+                                       sc->sense_buffer[6];
+                                       if (((sc->sense_buffer[3] & 0x80) ==
+                                               0x80) && (scsi_bufflen(sc)
+                                               != xfer_cnt)) {
+                                               sc->sense_buffer[2] =
+                                                   MEDIUM_ERROR;
+                                               sc->sense_buffer[12] = 0xff;
+                                               sc->sense_buffer[13] = 0xff;
+                                               printk(KERN_WARNING"Errata"
+                                               "on LSI53C1030 occurred."
+                                               "sc->req_bufflen=0x%02x,"
+                                               "xfer_cnt=0x%02x\n" ,
+                                               scsi_bufflen(sc),
+                                               xfer_cnt);
+                                       }
+                                       if (((sc->sense_buffer[3] & 0x80)
+                                               != 0x80) &&
+                                               (scsi_bufflen(sc) !=
+                                               xfer_cnt + difftransfer)) {
+                                               sc->sense_buffer[2] =
+                                                       MEDIUM_ERROR;
+                                               sc->sense_buffer[12] = 0xff;
+                                               sc->sense_buffer[13] = 0xff;
+                                               printk(KERN_WARNING
+                                               "Errata on LSI53C1030 occurred"
+                                               "sc->req_bufflen=0x%02x,"
+                                               " xfer_cnt=0x%02x,"
+                                               "difftransfer=0x%02x\n",
+                                               scsi_bufflen(sc),
+                                               xfer_cnt,
+                                               difftransfer);
+                                       }
+                               }
+
                                /*
                                 * If running against circa 200003dd 909 MPT f/w,
                                 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL