aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptscsih.c
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2007-09-29 12:16:53 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:52:15 -0400
commite8206381f5842269691f3164ec0d79b7059bd710 (patch)
tree4d3db0df57f86b34425dcfe929c940d8d06fe614 /drivers/message/fusion/mptscsih.c
parentbc6e089a13a5c0ac36247616baecd6fc77405e7f (diff)
[SCSI] mpt fusion: lock down ScsiLookup
ScsiLookup is an array of pending scmd pointers that the scsi lld maintains. This array is touched from queuecommand, eh threads, and interrupt context. This array should put under locks, hence this patch to synchronize its access. I've added some nice little function wrappers for this, and moved the ScsiLookup array over to MPT_ADAPTER struct. Signed-off-by: Eric Moore <Eric.Moore@lsi.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.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) {