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.c118
1 files changed, 102 insertions, 16 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 8242b16e3168..30524dc54b16 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -66,6 +66,7 @@
66 66
67#include "mptbase.h" 67#include "mptbase.h"
68#include "mptscsih.h" 68#include "mptscsih.h"
69#include "lsi/mpi_log_sas.h"
69 70
70/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 71/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71#define my_NAME "Fusion MPT SCSI Host driver" 72#define my_NAME "Fusion MPT SCSI Host driver"
@@ -127,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
127static 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);
128static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); 129static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
129static 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 );
130static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); 131static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
131 132
132static 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);
133 134
@@ -497,6 +498,34 @@ nextSGEset:
497 return SUCCESS; 498 return SUCCESS;
498} /* mptscsih_AddSGE() */ 499} /* mptscsih_AddSGE() */
499 500
501static void
502mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
503 U32 SlotStatus)
504{
505 MPT_FRAME_HDR *mf;
506 SEPRequest_t *SEPMsg;
507
508 if (ioc->bus_type == FC)
509 return;
510
511 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
512 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
513 ioc->name,__FUNCTION__));
514 return;
515 }
516
517 SEPMsg = (SEPRequest_t *)mf;
518 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
519 SEPMsg->Bus = vtarget->bus_id;
520 SEPMsg->TargetID = vtarget->target_id;
521 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
522 SEPMsg->SlotStatus = SlotStatus;
523 devtverboseprintk((MYIOC_s_WARN_FMT
524 "Sending SEP cmd=%x id=%d bus=%d\n",
525 ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
526 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
527}
528
500/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 529/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
501/* 530/*
502 * mptscsih_io_done - Main SCSI IO callback routine registered to 531 * mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -520,6 +549,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
520 SCSIIORequest_t *pScsiReq; 549 SCSIIORequest_t *pScsiReq;
521 SCSIIOReply_t *pScsiReply; 550 SCSIIOReply_t *pScsiReply;
522 u16 req_idx, req_idx_MR; 551 u16 req_idx, req_idx_MR;
552 VirtDevice *vdev;
553 VirtTarget *vtarget;
523 554
524 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; 555 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
525 556
@@ -538,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
538 } 569 }
539 570
540 sc = hd->ScsiLookup[req_idx]; 571 sc = hd->ScsiLookup[req_idx];
572 hd->ScsiLookup[req_idx] = NULL;
541 if (sc == NULL) { 573 if (sc == NULL) {
542 MPIHeader_t *hdr = (MPIHeader_t *)mf; 574 MPIHeader_t *hdr = (MPIHeader_t *)mf;
543 575
@@ -553,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
553 return 1; 585 return 1;
554 } 586 }
555 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;
556 sc->result = DID_OK << 16; /* Set default reply as OK */ 594 sc->result = DID_OK << 16; /* Set default reply as OK */
557 pScsiReq = (SCSIIORequest_t *) mf; 595 pScsiReq = (SCSIIORequest_t *) mf;
558 pScsiReply = (SCSIIOReply_t *) mr; 596 pScsiReply = (SCSIIOReply_t *) mr;
@@ -640,10 +678,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
640 678
641 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) 679 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
642 hd->sel_timeout[pScsiReq->TargetID]++; 680 hd->sel_timeout[pScsiReq->TargetID]++;
681
682 vdev = sc->device->hostdata;
683 if (!vdev)
684 break;
685 vtarget = vdev->vtarget;
686 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
687 mptscsih_issue_sep_command(ioc, vtarget,
688 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
689 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
690 }
643 break; 691 break;
644 692
645 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
646 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 693 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
694 if ( ioc->bus_type == SAS ) {
695 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
696 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
697 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
698 log_info &=SAS_LOGINFO_MASK;
699 if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
700 sc->result = (DID_BUS_BUSY << 16);
701 break;
702 }
703 }
704 }
705
706 /*
707 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
708 */
709
710 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
647 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 711 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
648 /* Linux handles an unsolicited DID_RESET better 712 /* Linux handles an unsolicited DID_RESET better
649 * than an unsolicited DID_ABORT. 713 * than an unsolicited DID_ABORT.
@@ -658,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
658 sc->result=DID_SOFT_ERROR << 16; 722 sc->result=DID_SOFT_ERROR << 16;
659 else /* Sufficient data transfer occurred */ 723 else /* Sufficient data transfer occurred */
660 sc->result = (DID_OK << 16) | scsi_status; 724 sc->result = (DID_OK << 16) | scsi_status;
661 dreplyprintk((KERN_NOTICE 725 dreplyprintk((KERN_NOTICE
662 "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));
663 break; 727 break;
664 728
@@ -784,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
784 sc->request_bufflen, sc->sc_data_direction); 848 sc->request_bufflen, sc->sc_data_direction);
785 } 849 }
786 850
787 hd->ScsiLookup[req_idx] = NULL;
788
789 sc->scsi_done(sc); /* Issue the command callback */ 851 sc->scsi_done(sc); /* Issue the command callback */
790 852
791 /* Free Chain buffers */ 853 /* Free Chain buffers */
@@ -827,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
827 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", 889 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
828 mf, SCpnt)); 890 mf, SCpnt));
829 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
830 /* Set status, free OS resources (SG DMA buffers) 901 /* Set status, free OS resources (SG DMA buffers)
831 * Do OS callback 902 * Do OS callback
832 * Free driver resources (chain, msg buffers)
833 */ 903 */
834 if (SCpnt->use_sg) { 904 if (SCpnt->use_sg) {
835 pci_unmap_sg(ioc->pcidev, 905 pci_unmap_sg(ioc->pcidev,
@@ -845,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
845 SCpnt->result = DID_RESET << 16; 915 SCpnt->result = DID_RESET << 16;
846 SCpnt->host_scribble = NULL; 916 SCpnt->host_scribble = NULL;
847 917
848 /* Free Chain buffers */
849 mptscsih_freeChainBuffers(ioc, ii);
850
851 /* Free Message frames */
852 mpt_free_msg_frame(ioc, mf);
853
854 SCpnt->scsi_done(SCpnt); /* Issue the command callback */ 918 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
855 } 919 }
856 } 920 }
@@ -887,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
887 if ((sc = hd->ScsiLookup[ii]) != NULL) { 951 if ((sc = hd->ScsiLookup[ii]) != NULL) {
888 952
889 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); 953 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
890 954 if (mf == NULL)
955 continue;
891 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",
892 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); 957 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
893
894 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)))
895 continue; 959 continue;
896 960
@@ -899,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
899 hd->ScsiLookup[ii] = NULL; 963 hd->ScsiLookup[ii] = NULL;
900 mptscsih_freeChainBuffers(hd->ioc, ii); 964 mptscsih_freeChainBuffers(hd->ioc, ii);
901 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;
902 if (sc->use_sg) { 968 if (sc->use_sg) {
903 pci_unmap_sg(hd->ioc->pcidev, 969 pci_unmap_sg(hd->ioc->pcidev,
904 (struct scatterlist *) sc->request_buffer, 970 (struct scatterlist *) sc->request_buffer,
@@ -1341,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1341 goto fail; 1407 goto fail;
1342 } 1408 }
1343 1409
1410 SCpnt->host_scribble = (unsigned char *)mf;
1344 hd->ScsiLookup[my_idx] = SCpnt; 1411 hd->ScsiLookup[my_idx] = SCpnt;
1345 SCpnt->host_scribble = NULL;
1346 1412
1347 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); 1413 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1348 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",
@@ -1529,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
1529 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); 1595 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1530 } 1596 }
1531 1597
1598 /*
1599 * Check IOCStatus from TM reply message
1600 */
1601 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1602 rc = FAILED;
1603
1532 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));
1533 1605
1534 return rc; 1606 return rc;
@@ -1654,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1654 int scpnt_idx; 1726 int scpnt_idx;
1655 int retval; 1727 int retval;
1656 VirtDevice *vdev; 1728 VirtDevice *vdev;
1729 ulong sn = SCpnt->serial_number;
1657 1730
1658 /* 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.
1659 */ 1732 */
@@ -1707,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1707 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, 1780 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
1708 ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); 1781 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1709 1782
1783 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1784 SCpnt->serial_number == sn) {
1785 retval = FAILED;
1786 }
1787
1710 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", 1788 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1711 hd->ioc->name, 1789 hd->ioc->name,
1712 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1790 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2023,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
2023 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); 2101 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2024 2102
2025 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; 2103 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2104 hd->tm_iocstatus = iocstatus;
2026 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",
2027 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); 2106 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2028 /* Error? (anything non-zero?) */ 2107 /* Error? (anything non-zero?) */
@@ -2401,6 +2480,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
2401 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12]; 2480 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2402 2481
2403 ioc->eventContext++; 2482 ioc->eventContext++;
2483 if (hd->ioc->pcidev->vendor ==
2484 PCI_VENDOR_ID_IBM) {
2485 mptscsih_issue_sep_command(hd->ioc,
2486 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2487 vdev->vtarget->tflags |=
2488 MPT_TARGET_FLAGS_LED_ON;
2489 }
2404 } 2490 }
2405 } 2491 }
2406 } else { 2492 } else {
@@ -2409,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
2409 } 2495 }
2410} 2496}
2411 2497
2412static u32 2498static int
2413SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) 2499SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2414{ 2500{
2415 MPT_SCSI_HOST *hd; 2501 MPT_SCSI_HOST *hd;