aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptscsih.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r--drivers/message/fusion/mptscsih.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index c29578614504..6796597dcee0 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -46,6 +46,7 @@
46 46
47#include <linux/module.h> 47#include <linux/module.h>
48#include <linux/kernel.h> 48#include <linux/kernel.h>
49#include <linux/slab.h>
49#include <linux/init.h> 50#include <linux/init.h>
50#include <linux/errno.h> 51#include <linux/errno.h>
51#include <linux/kdev_t.h> 52#include <linux/kdev_t.h>
@@ -792,11 +793,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
792 * precedence! 793 * precedence!
793 */ 794 */
794 sc->result = (DID_OK << 16) | scsi_status; 795 sc->result = (DID_OK << 16) | scsi_status;
795 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { 796 if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
796 /* Have already saved the status and sense data 797
798 /*
799 * For an Errata on LSI53C1030
800 * When the length of request data
801 * and transfer data are different
802 * with result of command (READ or VERIFY),
803 * DID_SOFT_ERROR is set.
797 */ 804 */
798 ; 805 if (ioc->bus_type == SPI) {
799 } else { 806 if (pScsiReq->CDB[0] == READ_6 ||
807 pScsiReq->CDB[0] == READ_10 ||
808 pScsiReq->CDB[0] == READ_12 ||
809 pScsiReq->CDB[0] == READ_16 ||
810 pScsiReq->CDB[0] == VERIFY ||
811 pScsiReq->CDB[0] == VERIFY_16) {
812 if (scsi_bufflen(sc) !=
813 xfer_cnt) {
814 sc->result =
815 DID_SOFT_ERROR << 16;
816 printk(KERN_WARNING "Errata"
817 "on LSI53C1030 occurred."
818 "sc->req_bufflen=0x%02x,"
819 "xfer_cnt=0x%02x\n",
820 scsi_bufflen(sc),
821 xfer_cnt);
822 }
823 }
824 }
825
800 if (xfer_cnt < sc->underflow) { 826 if (xfer_cnt < sc->underflow) {
801 if (scsi_status == SAM_STAT_BUSY) 827 if (scsi_status == SAM_STAT_BUSY)
802 sc->result = SAM_STAT_BUSY; 828 sc->result = SAM_STAT_BUSY;
@@ -835,7 +861,58 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
835 sc->result = (DID_OK << 16) | scsi_status; 861 sc->result = (DID_OK << 16) | scsi_status;
836 if (scsi_state == 0) { 862 if (scsi_state == 0) {
837 ; 863 ;
838 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { 864 } else if (scsi_state &
865 MPI_SCSI_STATE_AUTOSENSE_VALID) {
866
867 /*
868 * For potential trouble on LSI53C1030.
869 * (date:2007.xx.)
870 * It is checked whether the length of
871 * request data is equal to
872 * the length of transfer and residual.
873 * MEDIUM_ERROR is set by incorrect data.
874 */
875 if ((ioc->bus_type == SPI) &&
876 (sc->sense_buffer[2] & 0x20)) {
877 u32 difftransfer;
878 difftransfer =
879 sc->sense_buffer[3] << 24 |
880 sc->sense_buffer[4] << 16 |
881 sc->sense_buffer[5] << 8 |
882 sc->sense_buffer[6];
883 if (((sc->sense_buffer[3] & 0x80) ==
884 0x80) && (scsi_bufflen(sc)
885 != xfer_cnt)) {
886 sc->sense_buffer[2] =
887 MEDIUM_ERROR;
888 sc->sense_buffer[12] = 0xff;
889 sc->sense_buffer[13] = 0xff;
890 printk(KERN_WARNING"Errata"
891 "on LSI53C1030 occurred."
892 "sc->req_bufflen=0x%02x,"
893 "xfer_cnt=0x%02x\n" ,
894 scsi_bufflen(sc),
895 xfer_cnt);
896 }
897 if (((sc->sense_buffer[3] & 0x80)
898 != 0x80) &&
899 (scsi_bufflen(sc) !=
900 xfer_cnt + difftransfer)) {
901 sc->sense_buffer[2] =
902 MEDIUM_ERROR;
903 sc->sense_buffer[12] = 0xff;
904 sc->sense_buffer[13] = 0xff;
905 printk(KERN_WARNING
906 "Errata on LSI53C1030 occurred"
907 "sc->req_bufflen=0x%02x,"
908 " xfer_cnt=0x%02x,"
909 "difftransfer=0x%02x\n",
910 scsi_bufflen(sc),
911 xfer_cnt,
912 difftransfer);
913 }
914 }
915
839 /* 916 /*
840 * If running against circa 200003dd 909 MPT f/w, 917 * If running against circa 200003dd 909 MPT f/w,
841 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL 918 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
@@ -1362,9 +1439,14 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1362 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) 1439 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1363 && (SCpnt->device->tagged_supported)) { 1440 && (SCpnt->device->tagged_supported)) {
1364 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; 1441 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1365 } else { 1442 if (SCpnt->request && SCpnt->request->ioprio) {
1443 if (((SCpnt->request->ioprio & 0x7) == 1) ||
1444 !(SCpnt->request->ioprio & 0x7))
1445 scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
1446 }
1447 } else
1366 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; 1448 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1367 } 1449
1368 1450
1369 /* Use the above information to set up the message frame 1451 /* Use the above information to set up the message frame
1370 */ 1452 */
@@ -1720,7 +1802,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1720 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " 1802 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
1721 "Command not in the active list! (sc=%p)\n", ioc->name, 1803 "Command not in the active list! (sc=%p)\n", ioc->name,
1722 SCpnt)); 1804 SCpnt));
1723 retval = 0; 1805 retval = SUCCESS;
1724 goto out; 1806 goto out;
1725 } 1807 }
1726 1808
@@ -2275,11 +2357,12 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
2275 * mptscsih_change_queue_depth - This function will set a devices queue depth 2357 * mptscsih_change_queue_depth - This function will set a devices queue depth
2276 * @sdev: per scsi_device pointer 2358 * @sdev: per scsi_device pointer
2277 * @qdepth: requested queue depth 2359 * @qdepth: requested queue depth
2360 * @reason: calling context
2278 * 2361 *
2279 * Adding support for new 'change_queue_depth' api. 2362 * Adding support for new 'change_queue_depth' api.
2280*/ 2363*/
2281int 2364int
2282mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) 2365mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
2283{ 2366{
2284 MPT_SCSI_HOST *hd = shost_priv(sdev->host); 2367 MPT_SCSI_HOST *hd = shost_priv(sdev->host);
2285 VirtTarget *vtarget; 2368 VirtTarget *vtarget;
@@ -2291,6 +2374,9 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2291 starget = scsi_target(sdev); 2374 starget = scsi_target(sdev);
2292 vtarget = starget->hostdata; 2375 vtarget = starget->hostdata;
2293 2376
2377 if (reason != SCSI_QDEPTH_DEFAULT)
2378 return -EOPNOTSUPP;
2379
2294 if (ioc->bus_type == SPI) { 2380 if (ioc->bus_type == SPI) {
2295 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) 2381 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2296 max_depth = 1; 2382 max_depth = 1;
@@ -2357,7 +2443,8 @@ mptscsih_slave_configure(struct scsi_device *sdev)
2357 ioc->name, vtarget->negoFlags, vtarget->maxOffset, 2443 ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2358 vtarget->minSyncFactor)); 2444 vtarget->minSyncFactor));
2359 2445
2360 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); 2446 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
2447 SCSI_QDEPTH_DEFAULT);
2361 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2448 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2362 "tagged %d, simple %d, ordered %d\n", 2449 "tagged %d, simple %d, ordered %d\n",
2363 ioc->name,sdev->tagged_supported, sdev->simple_tags, 2450 ioc->name,sdev->tagged_supported, sdev->simple_tags,