From: Tomas Henzl <thenzl@redhat.com> Date: Thu, 15 Oct 2009 12:11:28 +0200 Subject: [scsi] mpt: errata 28 fix on LSI53C1030 Message-id: 4AD6F550.1010700@redhat.com O-Subject: [RHEL5.5 Patch] mpt: errata 28 fix on LSI53C1030 Bugzilla: 518689 RH-Acked-by: David Milburn <dmilburn@redhat.com> This is for BZ#518689 We were asked to include a patch for 'errata 28 on LSI53C1030'. The customer is facing this issue : "After issuing a "SCSI READ command" to a tape device, "Read Compare Error" can occur in the data comparison, and the data doesn't transfer correctly like the following. Problem No.1: The received data lengths shorten. Problem No.2: The received data lengths are correct, but the last two bytes are filled with NULL forcibly " >From the reporter : "However, I don't have a test environment that reproduces this matter currently. Therefore, I confirmed only the boot, and the route. I also checked the source and the fix logic was the same as RHEL4 that was proven, so I concluded that there was no problem." This patch is in RHEL4 for more then a year and is also in the 'in house' LSI driver. Kashyap (LSI) accepted this patch and promised now that they (LSI) will work on upstream posting. Tomas diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index fefcaf3..60db8e4 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -787,11 +787,32 @@ 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 (sc->request_bufflen != + xfer_cnt) { + sc->result = DID_SOFT_ERROR << 16; + printk(KERN_WARNING "Errata" + "on LSI53C1030 occurred. sc->request_bufflen=0x%02x, " + "xfer_cnt=0x%02x\n", sc->request_bufflen, xfer_cnt); + } + } + } + if (xfer_cnt < sc->underflow) { if (scsi_status == SAM_STAT_BUSY) sc->result = SAM_STAT_BUSY; @@ -831,6 +852,44 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if (scsi_state == 0) { ; } 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){ + if (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) { + if (sc->request_bufflen != 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->request_bufflen=0x%02x," + "xfer_cnt=0x%02x\n" ,sc->request_bufflen, xfer_cnt); + } + } else { + if (sc->request_bufflen != 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->request_bufflen=0x%02x," + " xfer_cnt=0x%02x, difftransfer=0x%02x\n", + sc->request_bufflen , xfer_cnt, difftransfer); + } + } + } + } + /* * If running against circa 200003dd 909 MPT f/w, * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL