#include "mptbase.h"
#include "mptscsih.h"
-#include "lsi/mpi_log_sas.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define my_NAME "Fusion MPT SCSI Host driver"
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 u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
return SUCCESS;
} /* mptscsih_AddSGE() */
-static void
-mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
- U32 SlotStatus)
-{
- MPT_FRAME_HDR *mf;
- SEPRequest_t *SEPMsg;
-
- if (ioc->bus_type == FC)
- return;
-
- if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
- dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
- ioc->name,__FUNCTION__));
- return;
- }
-
- SEPMsg = (SEPRequest_t *)mf;
- SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
- SEPMsg->Bus = vtarget->bus_id;
- SEPMsg->TargetID = vtarget->target_id;
- SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
- SEPMsg->SlotStatus = SlotStatus;
- devtverboseprintk((MYIOC_s_WARN_FMT
- "Sending SEP cmd=%x id=%d bus=%d\n",
- ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
- mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_io_done - Main SCSI IO callback routine registered to
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
u16 req_idx, req_idx_MR;
- VirtDevice *vdev;
- VirtTarget *vtarget;
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
}
sc = hd->ScsiLookup[req_idx];
- hd->ScsiLookup[req_idx] = NULL;
if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf;
return 1;
}
- if ((unsigned char *)mf != sc->host_scribble) {
- mptscsih_freeChainBuffers(ioc, req_idx);
- return 1;
- }
-
- sc->host_scribble = NULL;
sc->result = DID_OK << 16; /* Set default reply as OK */
pScsiReq = (SCSIIORequest_t *) mf;
pScsiReply = (SCSIIOReply_t *) mr;
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
hd->sel_timeout[pScsiReq->TargetID]++;
-
- vdev = sc->device->hostdata;
- if (!vdev)
- break;
- vtarget = vdev->vtarget;
- if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
- mptscsih_issue_sep_command(ioc, vtarget,
- MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
- vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
- }
break;
- case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
- if ( ioc->bus_type == SAS ) {
- u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
- if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
- u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
- log_info &=SAS_LOGINFO_MASK;
- if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
- sc->result = (DID_BUS_BUSY << 16);
- break;
- }
- }
- }
-
- /*
- * Allow non-SAS & non-NEXUS_LOSS to drop into below code
- */
-
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
+ case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
/* Linux handles an unsolicited DID_RESET better
* than an unsolicited DID_ABORT.
sc->result=DID_SOFT_ERROR << 16;
else /* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status;
- dreplyprintk((KERN_NOTICE
+ dreplyprintk((KERN_NOTICE
"RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
break;
sc->request_bufflen, sc->sc_data_direction);
}
+ hd->ScsiLookup[req_idx] = NULL;
+
sc->scsi_done(sc); /* Issue the command callback */
/* Free Chain buffers */
dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
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
+ * Free driver resources (chain, msg buffers)
*/
if (SCpnt->use_sg) {
pci_unmap_sg(ioc->pcidev,
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
+ /* Free Chain buffers */
+ mptscsih_freeChainBuffers(ioc, ii);
+
+ /* Free Message frames */
+ mpt_free_msg_frame(ioc, mf);
+
SCpnt->scsi_done(SCpnt); /* Issue the command callback */
}
}
if ((sc = hd->ScsiLookup[ii]) != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
- if (mf == NULL)
- continue;
+
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
+
if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
continue;
hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd->ioc, ii);
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
- if ((unsigned char *)mf != sc->host_scribble)
- continue;
if (sc->use_sg) {
pci_unmap_sg(hd->ioc->pcidev,
(struct scatterlist *) sc->request_buffer,
goto fail;
}
- SCpnt->host_scribble = (unsigned char *)mf;
hd->ScsiLookup[my_idx] = SCpnt;
+ SCpnt->host_scribble = NULL;
mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
}
- /*
- * Check IOCStatus from TM reply message
- */
- if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
- rc = FAILED;
-
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
return rc;
int scpnt_idx;
int retval;
VirtDevice *vdev;
- ulong sn = SCpnt->serial_number;
/* If we can't locate our host adapter structure, return FAILED status.
*/
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
- if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
- SCpnt->serial_number == sn) {
- retval = FAILED;
- }
-
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name,
((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
- msleep(250);
+ msleep_interruptible(250);
} while (--loop_count);
return status;
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
- hd->tm_iocstatus = iocstatus;
dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
/* Error? (anything non-zero?) */
ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
ioc->eventContext++;
- if (hd->ioc->pcidev->vendor ==
- PCI_VENDOR_ID_IBM) {
- mptscsih_issue_sep_command(hd->ioc,
- vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
- vdev->vtarget->tflags |=
- MPT_TARGET_FLAGS_LED_ON;
- }
}
}
} else {
}
}
-static int
+static u32
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
{
MPT_SCSI_HOST *hd;
hd->cmdPtr = NULL;
}
+ /* 7. FC: Rescan for blocked rports which might have returned.
+ */
+ if (ioc->bus_type == FC) {
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_q) {
+ if (ioc->fc_rescan_work_count++ == 0) {
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ }
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
}
{
MPT_SCSI_HOST *hd;
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+ unsigned long flags;
devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
ioc->name, event));
break;
case MPI_EVENT_RESCAN: /* 06 */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_q) {
+ if (ioc->fc_rescan_work_count++ == 0) {
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
break;
/*