diff options
author | Eric Moore <eric.moore@lsil.com> | 2006-07-11 19:32:33 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-07-13 09:30:49 -0400 |
commit | 3dc0b03fec73339199a995acd5a47478da0b4dc4 (patch) | |
tree | 4ab936aea919f385c095e336f366fd59081e6651 /drivers/message/fusion/mptscsih.c | |
parent | bf4515227c36fde1887f3fc0afc25a9bb4726842 (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>
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 52 |
1 files changed, 37 insertions, 15 deletions
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); | |||
128 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); | 128 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); |
129 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); | 129 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); |
130 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); | 130 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); |
131 | static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); | 131 | static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); |
132 | 132 | ||
133 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); | 133 | static 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 | ||
2476 | static u32 | 2498 | static int |
2477 | SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) | 2499 | SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) |
2478 | { | 2500 | { |
2479 | MPT_SCSI_HOST *hd; | 2501 | MPT_SCSI_HOST *hd; |