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.c212
1 files changed, 135 insertions, 77 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b1f68caf9a1d..dc5e996a8944 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -80,6 +80,10 @@ MODULE_VERSION(my_VERSION);
80/* 80/*
81 * Other private/forward protos... 81 * Other private/forward protos...
82 */ 82 */
83static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
84static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
85static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
86static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
83int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 87int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
84static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); 88static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
85int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 89int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
@@ -90,7 +94,6 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
90static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); 94static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
91static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); 95static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
92static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); 96static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
93static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
94 97
95static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); 98static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
96 99
@@ -658,12 +661,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
658 printk (MYIOC_s_ERR_FMT 661 printk (MYIOC_s_ERR_FMT
659 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n", 662 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
660 ioc->name, req_idx, req_idx_MR, mf, mr, 663 ioc->name, req_idx, req_idx_MR, mf, mr,
661 hd->ScsiLookup[req_idx_MR]); 664 mptscsih_get_scsi_lookup(ioc, req_idx_MR));
662 return 0; 665 return 0;
663 } 666 }
664 667
665 sc = hd->ScsiLookup[req_idx]; 668 sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
666 hd->ScsiLookup[req_idx] = NULL;
667 if (sc == NULL) { 669 if (sc == NULL) {
668 MPIHeader_t *hdr = (MPIHeader_t *)mf; 670 MPIHeader_t *hdr = (MPIHeader_t *)mf;
669 671
@@ -969,48 +971,32 @@ static void
969mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) 971mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
970{ 972{
971 MPT_ADAPTER *ioc = hd->ioc; 973 MPT_ADAPTER *ioc = hd->ioc;
972 struct scsi_cmnd *SCpnt; 974 struct scsi_cmnd *sc;
973 MPT_FRAME_HDR *mf; 975 SCSIIORequest_t *mf = NULL;
974 int ii; 976 int ii;
975 int max = ioc->req_depth; 977 int channel, id;
976
977 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush_ScsiLookup called\n", ioc->name));
978 for (ii= 0; ii < max; ii++) {
979 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
980
981 /* Command found.
982 */
983
984 /* Null ScsiLookup index
985 */
986 hd->ScsiLookup[ii] = NULL;
987 978
988 mf = MPT_INDEX_2_MFPTR(ioc, ii); 979 for (ii= 0; ii < ioc->req_depth; ii++) {
989 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush: ScsiDone (mf=%p,sc=%p)\n", 980 sc = mptscsih_getclear_scsi_lookup(ioc, ii);
990 ioc->name, mf, SCpnt)); 981 if (!sc)
991 982 continue;
992 /* Free Chain buffers */ 983 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
993 mptscsih_freeChainBuffers(ioc, ii); 984 if (!mf)
994 985 continue;
995 /* Free Message frames */ 986 channel = mf->Bus;
996 mpt_free_msg_frame(ioc, mf); 987 id = mf->TargetID;
997 988 mptscsih_freeChainBuffers(ioc, ii);
998 if ((unsigned char *)mf != SCpnt->host_scribble) 989 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
999 continue; 990 if ((unsigned char *)mf != sc->host_scribble)
1000 991 continue;
1001 /* Set status, free OS resources (SG DMA buffers) 992 scsi_dma_unmap(sc);
1002 * Do OS callback 993 sc->result = DID_RESET << 16;
1003 */ 994 sc->host_scribble = NULL;
1004 scsi_dma_unmap(SCpnt); 995 sdev_printk(MYIOC_s_INFO_FMT, sc->device,
1005 996 "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
1006 SCpnt->result = DID_RESET << 16; 997 " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
1007 SCpnt->host_scribble = NULL; 998 sc->scsi_done(sc);
1008
1009 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1010 }
1011 } 999 }
1012
1013 return;
1014} 1000}
1015 1001
1016/* 1002/*
@@ -1032,16 +1018,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1032{ 1018{
1033 SCSIIORequest_t *mf = NULL; 1019 SCSIIORequest_t *mf = NULL;
1034 int ii; 1020 int ii;
1035 int max = hd->ioc->req_depth;
1036 struct scsi_cmnd *sc; 1021 struct scsi_cmnd *sc;
1037 struct scsi_lun lun; 1022 struct scsi_lun lun;
1038 MPT_ADAPTER *ioc = hd->ioc; 1023 MPT_ADAPTER *ioc = hd->ioc;
1024 unsigned long flags;
1039 1025
1040 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": search_running channel %d id %d lun %d max %d\n", 1026 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1041 ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); 1027 for (ii = 0; ii < ioc->req_depth; ii++) {
1042 1028 if ((sc = ioc->ScsiLookup[ii]) != NULL) {
1043 for (ii=0; ii < max; ii++) {
1044 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1045 1029
1046 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); 1030 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
1047 if (mf == NULL) 1031 if (mf == NULL)
@@ -1060,13 +1044,12 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1060 memcmp(lun.scsi_lun, mf->LUN, 8)) 1044 memcmp(lun.scsi_lun, mf->LUN, 8))
1061 continue; 1045 continue;
1062 1046
1063 /* Cleanup
1064 */
1065 hd->ScsiLookup[ii] = NULL;
1066 mptscsih_freeChainBuffers(ioc, ii);
1067 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1068 if ((unsigned char *)mf != sc->host_scribble) 1047 if ((unsigned char *)mf != sc->host_scribble)
1069 continue; 1048 continue;
1049 ioc->ScsiLookup[ii] = NULL;
1050 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1051 mptscsih_freeChainBuffers(ioc, ii);
1052 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1070 scsi_dma_unmap(sc); 1053 scsi_dma_unmap(sc);
1071 sc->host_scribble = NULL; 1054 sc->host_scribble = NULL;
1072 sc->result = DID_NO_CONNECT << 16; 1055 sc->result = DID_NO_CONNECT << 16;
@@ -1074,8 +1057,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1074 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, 1057 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
1075 vdevice->vtarget->id, sc, mf, ii); 1058 vdevice->vtarget->id, sc, mf, ii);
1076 sc->scsi_done(sc); 1059 sc->scsi_done(sc);
1060 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1077 } 1061 }
1078 } 1062 }
1063 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1079 return; 1064 return;
1080} 1065}
1081 1066
@@ -1143,10 +1128,10 @@ mptscsih_remove(struct pci_dev *pdev)
1143 1128
1144 sz1=0; 1129 sz1=0;
1145 1130
1146 if (hd->ScsiLookup != NULL) { 1131 if (ioc->ScsiLookup != NULL) {
1147 sz1 = ioc->req_depth * sizeof(void *); 1132 sz1 = ioc->req_depth * sizeof(void *);
1148 kfree(hd->ScsiLookup); 1133 kfree(ioc->ScsiLookup);
1149 hd->ScsiLookup = NULL; 1134 ioc->ScsiLookup = NULL;
1150 } 1135 }
1151 1136
1152 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 1137 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
@@ -1463,7 +1448,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1463 } 1448 }
1464 1449
1465 SCpnt->host_scribble = (unsigned char *)mf; 1450 SCpnt->host_scribble = (unsigned char *)mf;
1466 hd->ScsiLookup[my_idx] = SCpnt; 1451 mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1467 1452
1468 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); 1453 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1469 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", 1454 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
@@ -1472,7 +1457,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1472 return 0; 1457 return 0;
1473 1458
1474 fail: 1459 fail:
1475 hd->ScsiLookup[my_idx] = NULL;
1476 mptscsih_freeChainBuffers(ioc, my_idx); 1460 mptscsih_freeChainBuffers(ioc, my_idx);
1477 mpt_free_msg_frame(ioc, mf); 1461 mpt_free_msg_frame(ioc, mf);
1478 return SCSI_MLQUEUE_HOST_BUSY; 1462 return SCSI_MLQUEUE_HOST_BUSY;
@@ -1834,7 +1818,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1834 1818
1835 /* Find this command 1819 /* Find this command
1836 */ 1820 */
1837 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { 1821 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
1838 /* Cmd not found in ScsiLookup. 1822 /* Cmd not found in ScsiLookup.
1839 * Do OS callback. 1823 * Do OS callback.
1840 */ 1824 */
@@ -1870,7 +1854,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
1870 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, 1854 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1871 ctx2abort, mptscsih_get_tm_timeout(ioc)); 1855 ctx2abort, mptscsih_get_tm_timeout(ioc));
1872 1856
1873 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && 1857 if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
1874 SCpnt->serial_number == sn) 1858 SCpnt->serial_number == sn)
1875 retval = FAILED; 1859 retval = FAILED;
1876 1860
@@ -2551,21 +2535,101 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
2551 } 2535 }
2552} 2536}
2553 2537
2554static int 2538/**
2555SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) 2539 * mptscsih_get_scsi_lookup
2540 *
2541 * retrieves scmd entry from ScsiLookup[] array list
2542 *
2543 * @ioc: Pointer to MPT_ADAPTER structure
2544 * @i: index into the array
2545 *
2546 * Returns the scsi_cmd pointer
2547 *
2548 **/
2549static struct scsi_cmnd *
2550mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2556{ 2551{
2557 MPT_SCSI_HOST *hd; 2552 unsigned long flags;
2558 int i; 2553 struct scsi_cmnd *scmd;
2554
2555 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2556 scmd = ioc->ScsiLookup[i];
2557 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2558
2559 return scmd;
2560}
2561
2562/**
2563 * mptscsih_getclear_scsi_lookup
2564 *
2565 * retrieves and clears scmd entry from ScsiLookup[] array list
2566 *
2567 * @ioc: Pointer to MPT_ADAPTER structure
2568 * @i: index into the array
2569 *
2570 * Returns the scsi_cmd pointer
2571 *
2572 **/
2573static struct scsi_cmnd *
2574mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2575{
2576 unsigned long flags;
2577 struct scsi_cmnd *scmd;
2578
2579 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2580 scmd = ioc->ScsiLookup[i];
2581 ioc->ScsiLookup[i] = NULL;
2582 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2583
2584 return scmd;
2585}
2586
2587/**
2588 * mptscsih_set_scsi_lookup
2589 *
2590 * writes a scmd entry into the ScsiLookup[] array list
2591 *
2592 * @ioc: Pointer to MPT_ADAPTER structure
2593 * @i: index into the array
2594 * @scmd: scsi_cmnd pointer
2595 *
2596 **/
2597static void
2598mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2599{
2600 unsigned long flags;
2559 2601
2560 hd = shost_priv(sc->device->host); 2602 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2603 ioc->ScsiLookup[i] = scmd;
2604 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2605}
2606
2607/**
2608 * SCPNT_TO_LOOKUP_IDX
2609 *
2610 * search's for a given scmd in the ScsiLookup[] array list
2611 *
2612 * @ioc: Pointer to MPT_ADAPTER structure
2613 * @scmd: scsi_cmnd pointer
2614 *
2615 **/
2616static int
2617SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2618{
2619 unsigned long flags;
2620 int i, index=-1;
2561 2621
2562 for (i = 0; i < hd->ioc->req_depth; i++) { 2622 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2563 if (hd->ScsiLookup[i] == sc) { 2623 for (i = 0; i < ioc->req_depth; i++) {
2564 return i; 2624 if (ioc->ScsiLookup[i] == sc) {
2625 index = i;
2626 goto out;
2565 } 2627 }
2566 } 2628 }
2567 2629
2568 return -1; 2630 out:
2631 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2632 return index;
2569} 2633}
2570 2634
2571/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 2635/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2574,7 +2638,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2574{ 2638{
2575 MPT_SCSI_HOST *hd; 2639 MPT_SCSI_HOST *hd;
2576 unsigned long flags; 2640 unsigned long flags;
2577 int ii;
2578 2641
2579 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2642 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2580 ": IOC %s_reset routed to SCSI host driver!\n", 2643 ": IOC %s_reset routed to SCSI host driver!\n",
@@ -2630,11 +2693,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2630 * Init all control structures. 2693 * Init all control structures.
2631 */ 2694 */
2632 2695
2633 /* ScsiLookup initialization
2634 */
2635 for (ii=0; ii < ioc->req_depth; ii++)
2636 hd->ScsiLookup[ii] = NULL;
2637
2638 /* 2. Chain Buffer initialization 2696 /* 2. Chain Buffer initialization
2639 */ 2697 */
2640 2698
@@ -2772,7 +2830,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2772 2830
2773 del_timer(&hd->timer); 2831 del_timer(&hd->timer);
2774 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 2832 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2775 hd->ScsiLookup[req_idx] = NULL; 2833 mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
2776 pReq = (SCSIIORequest_t *) mf; 2834 pReq = (SCSIIORequest_t *) mf;
2777 2835
2778 if (mf != hd->cmdPtr) { 2836 if (mf != hd->cmdPtr) {