[SCSI] mptspi: Fix for incorrect data underrun errata

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>
This commit is contained in:
Kashyap, Desai 2009-10-07 11:27:40 +05:30 committed by James Bottomley
parent e39e145dfb
commit 9b53b39243
1 changed files with 81 additions and 5 deletions

View 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