aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsil.com>2006-07-11 19:32:33 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-07-13 09:30:49 -0400
commit3dc0b03fec73339199a995acd5a47478da0b4dc4 (patch)
tree4ab936aea919f385c095e336f366fd59081e6651
parentbf4515227c36fde1887f3fc0afc25a9bb4726842 (diff)
[SCSI] mptfusion: task abort fix's
Fix's to insure proper status is returned to midlayer when a task abort failed to be aborted by controller firmware. Also sanity checks to prevent scsi cmd from being double completed during error recovery. Signed-off-by: Eric Moore <Eric.Moore@lsil.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/message/fusion/mptbase.h7
-rw-r--r--drivers/message/fusion/mptscsih.c52
2 files changed, 41 insertions, 18 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index ea92a55da4aa..d9e3860f9b10 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS
307 u32 HostIndex; /* 50 Host Index register */ 307 u32 HostIndex; /* 50 Host Index register */
308 u32 Reserved4[15]; /* 54-8F */ 308 u32 Reserved4[15]; /* 54-8F */
309 u32 Fubar; /* 90 For Fubar usage */ 309 u32 Fubar; /* 90 For Fubar usage */
310 u32 Reserved5[1050];/* 94-10F8 */ 310 u32 Reserved5[1050];/* 94-10F8 */
311 u32 Reset_1078; /* 10FC Reset 1078 */ 311 u32 Reset_1078; /* 10FC Reset 1078 */
312} SYSIF_REGS; 312} SYSIF_REGS;
313 313
314/* 314/*
@@ -981,7 +981,8 @@ typedef struct _MPT_SCSI_HOST {
981 wait_queue_head_t scandv_waitq; 981 wait_queue_head_t scandv_waitq;
982 int scandv_wait_done; 982 int scandv_wait_done;
983 long last_queue_full; 983 long last_queue_full;
984 u8 mpt_pq_filter; 984 u8 mpt_pq_filter;
985 u16 tm_iocstatus;
985} MPT_SCSI_HOST; 986} MPT_SCSI_HOST;
986 987
987/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 988/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index bc099651df73..30524dc54b16 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -128,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
128static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); 128static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
129static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); 129static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
130static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); 130static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
131static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); 131static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
132 132
133static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); 133static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
134 134
@@ -569,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
569 } 569 }
570 570
571 sc = hd->ScsiLookup[req_idx]; 571 sc = hd->ScsiLookup[req_idx];
572 hd->ScsiLookup[req_idx] = NULL;
572 if (sc == NULL) { 573 if (sc == NULL) {
573 MPIHeader_t *hdr = (MPIHeader_t *)mf; 574 MPIHeader_t *hdr = (MPIHeader_t *)mf;
574 575
@@ -584,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
584 return 1; 585 return 1;
585 } 586 }
586 587
588 if ((unsigned char *)mf != sc->host_scribble) {
589 mptscsih_freeChainBuffers(ioc, req_idx);
590 return 1;
591 }
592
593 sc->host_scribble = NULL;
587 sc->result = DID_OK << 16; /* Set default reply as OK */ 594 sc->result = DID_OK << 16; /* Set default reply as OK */
588 pScsiReq = (SCSIIORequest_t *) mf; 595 pScsiReq = (SCSIIORequest_t *) mf;
589 pScsiReply = (SCSIIOReply_t *) mr; 596 pScsiReply = (SCSIIOReply_t *) mr;
@@ -715,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
715 sc->result=DID_SOFT_ERROR << 16; 722 sc->result=DID_SOFT_ERROR << 16;
716 else /* Sufficient data transfer occurred */ 723 else /* Sufficient data transfer occurred */
717 sc->result = (DID_OK << 16) | scsi_status; 724 sc->result = (DID_OK << 16) | scsi_status;
718 dreplyprintk((KERN_NOTICE 725 dreplyprintk((KERN_NOTICE
719 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); 726 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
720 break; 727 break;
721 728
@@ -841,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
841 sc->request_bufflen, sc->sc_data_direction); 848 sc->request_bufflen, sc->sc_data_direction);
842 } 849 }
843 850
844 hd->ScsiLookup[req_idx] = NULL;
845
846 sc->scsi_done(sc); /* Issue the command callback */ 851 sc->scsi_done(sc); /* Issue the command callback */
847 852
848 /* Free Chain buffers */ 853 /* Free Chain buffers */
@@ -884,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
884 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", 889 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
885 mf, SCpnt)); 890 mf, SCpnt));
886 891
892 /* Free Chain buffers */
893 mptscsih_freeChainBuffers(ioc, ii);
894
895 /* Free Message frames */
896 mpt_free_msg_frame(ioc, mf);
897
898 if ((unsigned char *)mf != SCpnt->host_scribble)
899 continue;
900
887 /* Set status, free OS resources (SG DMA buffers) 901 /* Set status, free OS resources (SG DMA buffers)
888 * Do OS callback 902 * Do OS callback
889 * Free driver resources (chain, msg buffers)
890 */ 903 */
891 if (SCpnt->use_sg) { 904 if (SCpnt->use_sg) {
892 pci_unmap_sg(ioc->pcidev, 905 pci_unmap_sg(ioc->pcidev,
@@ -902,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
902 SCpnt->result = DID_RESET << 16; 915 SCpnt->result = DID_RESET << 16;
903 SCpnt->host_scribble = NULL; 916 SCpnt->host_scribble = NULL;
904 917
905 /* Free Chain buffers */
906 mptscsih_freeChainBuffers(ioc, ii);
907
908 /* Free Message frames */
909 mpt_free_msg_frame(ioc, mf);
910
911 SCpnt->scsi_done(SCpnt); /* Issue the command callback */ 918 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
912 } 919 }
913 } 920 }
@@ -944,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
944 if ((sc = hd->ScsiLookup[ii]) != NULL) { 951 if ((sc = hd->ScsiLookup[ii]) != NULL) {
945 952
946 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); 953 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
947 954 if (mf == NULL)
955 continue;
948 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", 956 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
949 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); 957 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
950
951 if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) 958 if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
952 continue; 959 continue;
953 960
@@ -956,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
956 hd->ScsiLookup[ii] = NULL; 963 hd->ScsiLookup[ii] = NULL;
957 mptscsih_freeChainBuffers(hd->ioc, ii); 964 mptscsih_freeChainBuffers(hd->ioc, ii);
958 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); 965 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
966 if ((unsigned char *)mf != sc->host_scribble)
967 continue;
959 if (sc->use_sg) { 968 if (sc->use_sg) {
960 pci_unmap_sg(hd->ioc->pcidev, 969 pci_unmap_sg(hd->ioc->pcidev,
961 (struct scatterlist *) sc->request_buffer, 970 (struct scatterlist *) sc->request_buffer,
@@ -1398,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1398 goto fail; 1407 goto fail;
1399 } 1408 }
1400 1409
1410 SCpnt->host_scribble = (unsigned char *)mf;
1401 hd->ScsiLookup[my_idx] = SCpnt; 1411 hd->ScsiLookup[my_idx] = SCpnt;
1402 SCpnt->host_scribble = NULL;
1403 1412
1404 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); 1413 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1405 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", 1414 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
@@ -1586,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
1586 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); 1595 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1587 } 1596 }
1588 1597
1598 /*
1599 * Check IOCStatus from TM reply message
1600 */
1601 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1602 rc = FAILED;
1603
1589 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); 1604 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1590 1605
1591 return rc; 1606 return rc;
@@ -1711,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1711 int scpnt_idx; 1726 int scpnt_idx;
1712 int retval; 1727 int retval;
1713 VirtDevice *vdev; 1728 VirtDevice *vdev;
1729 ulong sn = SCpnt->serial_number;
1714 1730
1715 /* If we can't locate our host adapter structure, return FAILED status. 1731 /* If we can't locate our host adapter structure, return FAILED status.
1716 */ 1732 */
@@ -1764,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1764 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, 1780 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
1765 ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); 1781 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1766 1782
1783 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1784 SCpnt->serial_number == sn) {
1785 retval = FAILED;
1786 }
1787
1767 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", 1788 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1768 hd->ioc->name, 1789 hd->ioc->name,
1769 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1790 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2080,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
2080 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); 2101 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2081 2102
2082 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; 2103 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2104 hd->tm_iocstatus = iocstatus;
2083 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", 2105 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2084 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); 2106 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2085 /* Error? (anything non-zero?) */ 2107 /* Error? (anything non-zero?) */
@@ -2473,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
2473 } 2495 }
2474} 2496}
2475 2497
2476static u32 2498static int
2477SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) 2499SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2478{ 2500{
2479 MPT_SCSI_HOST *hd; 2501 MPT_SCSI_HOST *hd;