diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-10-07 01:57:40 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-29 13:03:24 -0400 |
commit | 9b53b39243cf23a0b68eaa16c37ce16eada69a46 (patch) | |
tree | 3802e17dde9b8329b342f781b8e5b238472d7c38 /drivers/message/fusion/mptscsih.c | |
parent | e39e145dfb78d4e20d89139d2576306b4279c126 (diff) |
[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>
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c29578614504..f68ec48a881e 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -792,11 +792,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
792 | * precedence! | 792 | * precedence! |
793 | */ | 793 | */ |
794 | sc->result = (DID_OK << 16) | scsi_status; | 794 | sc->result = (DID_OK << 16) | scsi_status; |
795 | if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 795 | if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) { |
796 | /* Have already saved the status and sense data | 796 | |
797 | /* | ||
798 | * For an Errata on LSI53C1030 | ||
799 | * When the length of request data | ||
800 | * and transfer data are different | ||
801 | * with result of command (READ or VERIFY), | ||
802 | * DID_SOFT_ERROR is set. | ||
797 | */ | 803 | */ |
798 | ; | 804 | if (ioc->bus_type == SPI) { |
799 | } else { | 805 | if (pScsiReq->CDB[0] == READ_6 || |
806 | pScsiReq->CDB[0] == READ_10 || | ||
807 | pScsiReq->CDB[0] == READ_12 || | ||
808 | pScsiReq->CDB[0] == READ_16 || | ||
809 | pScsiReq->CDB[0] == VERIFY || | ||
810 | pScsiReq->CDB[0] == VERIFY_16) { | ||
811 | if (scsi_bufflen(sc) != | ||
812 | xfer_cnt) { | ||
813 | sc->result = | ||
814 | DID_SOFT_ERROR << 16; | ||
815 | printk(KERN_WARNING "Errata" | ||
816 | "on LSI53C1030 occurred." | ||
817 | "sc->req_bufflen=0x%02x," | ||
818 | "xfer_cnt=0x%02x\n", | ||
819 | scsi_bufflen(sc), | ||
820 | xfer_cnt); | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | |||
800 | if (xfer_cnt < sc->underflow) { | 825 | if (xfer_cnt < sc->underflow) { |
801 | if (scsi_status == SAM_STAT_BUSY) | 826 | if (scsi_status == SAM_STAT_BUSY) |
802 | sc->result = SAM_STAT_BUSY; | 827 | sc->result = SAM_STAT_BUSY; |
@@ -835,7 +860,58 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
835 | sc->result = (DID_OK << 16) | scsi_status; | 860 | sc->result = (DID_OK << 16) | scsi_status; |
836 | if (scsi_state == 0) { | 861 | if (scsi_state == 0) { |
837 | ; | 862 | ; |
838 | } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 863 | } else if (scsi_state & |
864 | MPI_SCSI_STATE_AUTOSENSE_VALID) { | ||
865 | |||
866 | /* | ||
867 | * For potential trouble on LSI53C1030. | ||
868 | * (date:2007.xx.) | ||
869 | * It is checked whether the length of | ||
870 | * request data is equal to | ||
871 | * the length of transfer and residual. | ||
872 | * MEDIUM_ERROR is set by incorrect data. | ||
873 | */ | ||
874 | if ((ioc->bus_type == SPI) && | ||
875 | (sc->sense_buffer[2] & 0x20)) { | ||
876 | u32 difftransfer; | ||
877 | difftransfer = | ||
878 | sc->sense_buffer[3] << 24 | | ||
879 | sc->sense_buffer[4] << 16 | | ||
880 | sc->sense_buffer[5] << 8 | | ||
881 | sc->sense_buffer[6]; | ||
882 | if (((sc->sense_buffer[3] & 0x80) == | ||
883 | 0x80) && (scsi_bufflen(sc) | ||
884 | != xfer_cnt)) { | ||
885 | sc->sense_buffer[2] = | ||
886 | MEDIUM_ERROR; | ||
887 | sc->sense_buffer[12] = 0xff; | ||
888 | sc->sense_buffer[13] = 0xff; | ||
889 | printk(KERN_WARNING"Errata" | ||
890 | "on LSI53C1030 occurred." | ||
891 | "sc->req_bufflen=0x%02x," | ||
892 | "xfer_cnt=0x%02x\n" , | ||
893 | scsi_bufflen(sc), | ||
894 | xfer_cnt); | ||
895 | } | ||
896 | if (((sc->sense_buffer[3] & 0x80) | ||
897 | != 0x80) && | ||
898 | (scsi_bufflen(sc) != | ||
899 | xfer_cnt + difftransfer)) { | ||
900 | sc->sense_buffer[2] = | ||
901 | MEDIUM_ERROR; | ||
902 | sc->sense_buffer[12] = 0xff; | ||
903 | sc->sense_buffer[13] = 0xff; | ||
904 | printk(KERN_WARNING | ||
905 | "Errata on LSI53C1030 occurred" | ||
906 | "sc->req_bufflen=0x%02x," | ||
907 | " xfer_cnt=0x%02x," | ||
908 | "difftransfer=0x%02x\n", | ||
909 | scsi_bufflen(sc), | ||
910 | xfer_cnt, | ||
911 | difftransfer); | ||
912 | } | ||
913 | } | ||
914 | |||
839 | /* | 915 | /* |
840 | * If running against circa 200003dd 909 MPT f/w, | 916 | * If running against circa 200003dd 909 MPT f/w, |
841 | * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL | 917 | * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL |