diff options
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 118 |
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); | |||
127 | 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); |
128 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); | 129 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); |
129 | 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 ); |
130 | static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); | 131 | static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); |
131 | 132 | ||
132 | 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); |
133 | 134 | ||
@@ -497,6 +498,34 @@ nextSGEset: | |||
497 | return SUCCESS; | 498 | return SUCCESS; |
498 | } /* mptscsih_AddSGE() */ | 499 | } /* mptscsih_AddSGE() */ |
499 | 500 | ||
501 | static void | ||
502 | mptscsih_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 | ||
2412 | static u32 | 2498 | static int |
2413 | SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) | 2499 | SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) |
2414 | { | 2500 | { |
2415 | MPT_SCSI_HOST *hd; | 2501 | MPT_SCSI_HOST *hd; |