summaryrefslogtreecommitdiffstats
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 b1f68caf9a1..dc5e996a894 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -80,6 +80,10 @@ MODULE_VERSION(my_VERSION);
/*
* Other private/forward protos...
*/
+static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
+static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
+static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
+static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
int 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);
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
-static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
@@ -658,12 +661,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
printk (MYIOC_s_ERR_FMT
"req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
ioc->name, req_idx, req_idx_MR, mf, mr,
- hd->ScsiLookup[req_idx_MR]);
+ mptscsih_get_scsi_lookup(ioc, req_idx_MR));
return 0;
}
- sc = hd->ScsiLookup[req_idx];
- hd->ScsiLookup[req_idx] = NULL;
+ sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf;
@@ -969,48 +971,32 @@ static void
mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
{
MPT_ADAPTER *ioc = hd->ioc;
- struct scsi_cmnd *SCpnt;
- MPT_FRAME_HDR *mf;
+ struct scsi_cmnd *sc;
+ SCSIIORequest_t *mf = NULL;
int ii;
- int max = ioc->req_depth;
-
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush_ScsiLookup called\n", ioc->name));
- for (ii= 0; ii < max; ii++) {
- if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
-
- /* Command found.
- */
-
- /* Null ScsiLookup index
- */
- hd->ScsiLookup[ii] = NULL;
+ int channel, id;
- mf = MPT_INDEX_2_MFPTR(ioc, ii);
- dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush: ScsiDone (mf=%p,sc=%p)\n",
- ioc->name, mf, SCpnt));
-
- /* Free Chain buffers */
- mptscsih_freeChainBuffers(ioc, ii);
-
- /* Free Message frames */
- mpt_free_msg_frame(ioc, mf);
-
- if ((unsigned char *)mf != SCpnt->host_scribble)
- continue;
-
- /* Set status, free OS resources (SG DMA buffers)
- * Do OS callback
- */
- scsi_dma_unmap(SCpnt);
-
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
-
- SCpnt->scsi_done(SCpnt); /* Issue the command callback */
- }
+ for (ii= 0; ii < ioc->req_depth; ii++) {
+ sc = mptscsih_getclear_scsi_lookup(ioc, ii);
+ if (!sc)
+ continue;
+ mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
+ if (!mf)
+ continue;
+ channel = mf->Bus;
+ id = mf->TargetID;
+ mptscsih_freeChainBuffers(ioc, ii);
+ mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
+ if ((unsigned char *)mf != sc->host_scribble)
+ continue;
+ scsi_dma_unmap(sc);
+ sc->result = DID_RESET << 16;
+ sc->host_scribble = NULL;
+ sdev_printk(MYIOC_s_INFO_FMT, sc->device,
+ "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
+ " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
+ sc->scsi_done(sc);
}
-
- return;
}
/*
@@ -1032,16 +1018,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
{
SCSIIORequest_t *mf = NULL;
int ii;
- int max = hd->ioc->req_depth;
struct scsi_cmnd *sc;
struct scsi_lun lun;
MPT_ADAPTER *ioc = hd->ioc;
+ unsigned long flags;
- dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": search_running channel %d id %d lun %d max %d\n",
- ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
-
- for (ii=0; ii < max; ii++) {
- if ((sc = hd->ScsiLookup[ii]) != NULL) {
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ for (ii = 0; ii < ioc->req_depth; ii++) {
+ if ((sc = ioc->ScsiLookup[ii]) != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
if (mf == NULL)
@@ -1060,13 +1044,12 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
memcmp(lun.scsi_lun, mf->LUN, 8))
continue;
- /* Cleanup
- */
- hd->ScsiLookup[ii] = NULL;
- mptscsih_freeChainBuffers(ioc, ii);
- mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
if ((unsigned char *)mf != sc->host_scribble)
continue;
+ ioc->ScsiLookup[ii] = NULL;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ mptscsih_freeChainBuffers(ioc, ii);
+ mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
scsi_dma_unmap(sc);
sc->host_scribble = NULL;
sc->result = DID_NO_CONNECT << 16;
@@ -1074,8 +1057,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
"fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
vdevice->vtarget->id, sc, mf, ii);
sc->scsi_done(sc);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
}
}
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
return;
}
@@ -1143,10 +1128,10 @@ mptscsih_remove(struct pci_dev *pdev)
sz1=0;
- if (hd->ScsiLookup != NULL) {
+ if (ioc->ScsiLookup != NULL) {
sz1 = ioc->req_depth * sizeof(void *);
- kfree(hd->ScsiLookup);
- hd->ScsiLookup = NULL;
+ kfree(ioc->ScsiLookup);
+ ioc->ScsiLookup = NULL;
}
dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
@@ -1463,7 +1448,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
}
SCpnt->host_scribble = (unsigned char *)mf;
- hd->ScsiLookup[my_idx] = SCpnt;
+ mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
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 *))
return 0;
fail:
- hd->ScsiLookup[my_idx] = NULL;
mptscsih_freeChainBuffers(ioc, my_idx);
mpt_free_msg_frame(ioc, mf);
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1834,7 +1818,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
/* Find this command
*/
- if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
+ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
/* Cmd not found in ScsiLookup.
* Do OS callback.
*/
@@ -1870,7 +1854,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
ctx2abort, mptscsih_get_tm_timeout(ioc));
- if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+ if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
SCpnt->serial_number == sn)
retval = FAILED;
@@ -2551,21 +2535,101 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
}
}
-static int
-SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
+/**
+ * mptscsih_get_scsi_lookup
+ *
+ * retrieves scmd entry from ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ *
+ * Returns the scsi_cmd pointer
+ *
+ **/
+static struct scsi_cmnd *
+mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
{
- MPT_SCSI_HOST *hd;
- int i;
+ unsigned long flags;
+ struct scsi_cmnd *scmd;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ scmd = ioc->ScsiLookup[i];
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ return scmd;
+}
+
+/**
+ * mptscsih_getclear_scsi_lookup
+ *
+ * retrieves and clears scmd entry from ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ *
+ * Returns the scsi_cmd pointer
+ *
+ **/
+static struct scsi_cmnd *
+mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
+{
+ unsigned long flags;
+ struct scsi_cmnd *scmd;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ scmd = ioc->ScsiLookup[i];
+ ioc->ScsiLookup[i] = NULL;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ return scmd;
+}
+
+/**
+ * mptscsih_set_scsi_lookup
+ *
+ * writes a scmd entry into the ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @i: index into the array
+ * @scmd: scsi_cmnd pointer
+ *
+ **/
+static void
+mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
+{
+ unsigned long flags;
- hd = shost_priv(sc->device->host);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->ScsiLookup[i] = scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+}
+
+/**
+ * SCPNT_TO_LOOKUP_IDX
+ *
+ * search's for a given scmd in the ScsiLookup[] array list
+ *
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @scmd: scsi_cmnd pointer
+ *
+ **/
+static int
+SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
+{
+ unsigned long flags;
+ int i, index=-1;
- for (i = 0; i < hd->ioc->req_depth; i++) {
- if (hd->ScsiLookup[i] == sc) {
- return i;
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ for (i = 0; i < ioc->req_depth; i++) {
+ if (ioc->ScsiLookup[i] == sc) {
+ index = i;
+ goto out;
}
}
- return -1;
+ out:
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return index;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2574,7 +2638,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
MPT_SCSI_HOST *hd;
unsigned long flags;
- int ii;
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
": IOC %s_reset routed to SCSI host driver!\n",
@@ -2630,11 +2693,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
* Init all control structures.
*/
- /* ScsiLookup initialization
- */
- for (ii=0; ii < ioc->req_depth; ii++)
- hd->ScsiLookup[ii] = NULL;
-
/* 2. Chain Buffer initialization
*/
@@ -2772,7 +2830,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
del_timer(&hd->timer);
req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
- hd->ScsiLookup[req_idx] = NULL;
+ mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
pReq = (SCSIIORequest_t *) mf;
if (mf != hd->cmdPtr) {