Commit 3dc0b03f authored by Eric Moore's avatar Eric Moore Committed by James Bottomley

[SCSI] mptfusion: task abort fix's

Fix's to insure proper status is returned to midlayer
when a task abort failed to be aborted by controller
firmware.

Also sanity checks to prevent scsi cmd from being
double completed during error recovery.
Signed-off-by: default avatarEric Moore <Eric.Moore@lsil.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent bf451522
...@@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS ...@@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS
u32 HostIndex; /* 50 Host Index register */ u32 HostIndex; /* 50 Host Index register */
u32 Reserved4[15]; /* 54-8F */ u32 Reserved4[15]; /* 54-8F */
u32 Fubar; /* 90 For Fubar usage */ u32 Fubar; /* 90 For Fubar usage */
u32 Reserved5[1050];/* 94-10F8 */ u32 Reserved5[1050];/* 94-10F8 */
u32 Reset_1078; /* 10FC Reset 1078 */ u32 Reset_1078; /* 10FC Reset 1078 */
} SYSIF_REGS; } SYSIF_REGS;
/* /*
...@@ -981,7 +981,8 @@ typedef struct _MPT_SCSI_HOST { ...@@ -981,7 +981,8 @@ typedef struct _MPT_SCSI_HOST {
wait_queue_head_t scandv_waitq; wait_queue_head_t scandv_waitq;
int scandv_wait_done; int scandv_wait_done;
long last_queue_full; long last_queue_full;
u8 mpt_pq_filter; u8 mpt_pq_filter;
u16 tm_iocstatus;
} MPT_SCSI_HOST; } MPT_SCSI_HOST;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
...@@ -128,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); ...@@ -128,7 +128,7 @@ 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 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_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); static int 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); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
...@@ -569,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ...@@ -569,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
} }
sc = hd->ScsiLookup[req_idx]; sc = hd->ScsiLookup[req_idx];
hd->ScsiLookup[req_idx] = NULL;
if (sc == NULL) { if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf; MPIHeader_t *hdr = (MPIHeader_t *)mf;
...@@ -584,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ...@@ -584,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1; 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 */ sc->result = DID_OK << 16; /* Set default reply as OK */
pScsiReq = (SCSIIORequest_t *) mf; pScsiReq = (SCSIIORequest_t *) mf;
pScsiReply = (SCSIIOReply_t *) mr; pScsiReply = (SCSIIOReply_t *) mr;
...@@ -715,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ...@@ -715,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->result=DID_SOFT_ERROR << 16; sc->result=DID_SOFT_ERROR << 16;
else /* Sufficient data transfer occurred */ else /* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status; 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)); "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
break; break;
...@@ -841,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ...@@ -841,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->request_bufflen, sc->sc_data_direction); sc->request_bufflen, sc->sc_data_direction);
} }
hd->ScsiLookup[req_idx] = NULL;
sc->scsi_done(sc); /* Issue the command callback */ sc->scsi_done(sc); /* Issue the command callback */
/* Free Chain buffers */ /* Free Chain buffers */
...@@ -884,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) ...@@ -884,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
mf, SCpnt)); 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) /* Set status, free OS resources (SG DMA buffers)
* Do OS callback * Do OS callback
* Free driver resources (chain, msg buffers)
*/ */
if (SCpnt->use_sg) { if (SCpnt->use_sg) {
pci_unmap_sg(ioc->pcidev, pci_unmap_sg(ioc->pcidev,
...@@ -902,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) ...@@ -902,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
SCpnt->result = DID_RESET << 16; SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL; 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 */ SCpnt->scsi_done(SCpnt); /* Issue the command callback */
} }
} }
...@@ -944,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) ...@@ -944,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
if ((sc = hd->ScsiLookup[ii]) != NULL) { if ((sc = hd->ScsiLookup[ii]) != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); 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", dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
continue; continue;
...@@ -956,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) ...@@ -956,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
hd->ScsiLookup[ii] = NULL; hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd->ioc, ii); mptscsih_freeChainBuffers(hd->ioc, ii);
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
if ((unsigned char *)mf != sc->host_scribble)
continue;
if (sc->use_sg) { if (sc->use_sg) {
pci_unmap_sg(hd->ioc->pcidev, pci_unmap_sg(hd->ioc->pcidev,
(struct scatterlist *) sc->request_buffer, (struct scatterlist *) sc->request_buffer,
...@@ -1398,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ...@@ -1398,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
goto fail; goto fail;
} }
SCpnt->host_scribble = (unsigned char *)mf;
hd->ScsiLookup[my_idx] = SCpnt; hd->ScsiLookup[my_idx] = SCpnt;
SCpnt->host_scribble = NULL;
mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
...@@ -1586,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in ...@@ -1586,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); 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)); dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
return rc; return rc;
...@@ -1711,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1711,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
int scpnt_idx; int scpnt_idx;
int retval; int retval;
VirtDevice *vdev; VirtDevice *vdev;
ulong sn = SCpnt->serial_number;
/* If we can't locate our host adapter structure, return FAILED status. /* If we can't locate our host adapter structure, return FAILED status.
*/ */
...@@ -1764,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1764,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); 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", printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name, hd->ioc->name,
((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
...@@ -2080,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m ...@@ -2080,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; 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", dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
/* Error? (anything non-zero?) */ /* Error? (anything non-zero?) */
...@@ -2473,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR ...@@ -2473,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
} }
} }
static u32 static int
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
{ {
MPT_SCSI_HOST *hd; MPT_SCSI_HOST *hd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment