Commit cd2c6191 authored by Eric Moore's avatar Eric Moore Committed by James Bottomley

[SCSI] fusion - error handling bug fix's

misc error handling bug fix's
- properly interpret iocstatus returned after task management request
- clear tmState after a failed doorbell
- cleanup mptscsih_taskmgmt_complete
Signed-off-by: default avatarEric Moore <Eric.Moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2ecce492
...@@ -3219,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) ...@@ -3219,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
u32 diag1val = 0; u32 diag1val = 0;
#endif #endif
/* Clear any existing interrupts */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
"address=%p\n", ioc->name, __FUNCTION__, "address=%p\n", ioc->name, __FUNCTION__,
...@@ -3238,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) ...@@ -3238,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
" count=%d\n", " count=%d\n",
ioc->name, doorbell, count)); ioc->name, doorbell, count));
if (doorbell == MPI_IOC_STATE_READY) { if (doorbell == MPI_IOC_STATE_READY) {
return 0; return 1;
} }
/* wait 1 sec */ /* wait 1 sec */
...@@ -3250,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) ...@@ -3250,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
return -1; return -1;
} }
/* Clear any existing interrupts */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
/* Use "Diagnostic reset" method! (only thing available!) */ /* Use "Diagnostic reset" method! (only thing available!) */
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
...@@ -3968,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) ...@@ -3968,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
} }
} else { } else {
while (--cntdn) { while (--cntdn) {
mdelay (1); udelay (1000);
intstat = CHIPREG_READ32(&ioc->chip->IntStatus); intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break; break;
...@@ -4020,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) ...@@ -4020,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
intstat = CHIPREG_READ32(&ioc->chip->IntStatus); intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (intstat & MPI_HIS_DOORBELL_INTERRUPT) if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
break; break;
mdelay(1); udelay (1000);
count++; count++;
} }
} }
......
...@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) ...@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
*/ */
dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
ioctl->ioc->name)); ioctl->ioc->name));
mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
} }
return; return;
......
...@@ -1536,7 +1536,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) ...@@ -1536,7 +1536,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
*/ */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /**
* mptscsih_TMHandler - Generic handler for SCSI Task Management. * mptscsih_TMHandler - Generic handler for SCSI Task Management.
* Fall through to mpt_HardResetHandler if: not operational, too many * Fall through to mpt_HardResetHandler if: not operational, too many
* failed TM requests or handshake failure. * failed TM requests or handshake failure.
...@@ -1552,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) ...@@ -1552,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
* will be active. * will be active.
* *
* Returns 0 for SUCCESS or -1 if FAILED. * Returns 0 for SUCCESS, or FAILED.
*/ **/
int int
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{ {
MPT_ADAPTER *ioc; MPT_ADAPTER *ioc;
int rc = -1; int rc = -1;
int doTask = 1;
u32 ioc_raw_state; u32 ioc_raw_state;
unsigned long flags; unsigned long flags;
/* If FW is being reloaded currently, return success to
* the calling function.
*/
if (hd == NULL)
return 0;
ioc = hd->ioc; ioc = hd->ioc;
if (ioc == NULL) {
printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
return FAILED;
}
dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
// SJR - CHECKME - Can we avoid this here? // SJR - CHECKME - Can we avoid this here?
...@@ -1586,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ...@@ -1586,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
spin_unlock_irqrestore(&ioc->diagLock, flags); spin_unlock_irqrestore(&ioc->diagLock, flags);
/* Wait a fixed amount of time for the TM pending flag to be cleared. /* Wait a fixed amount of time for the TM pending flag to be cleared.
* If we time out and not bus reset, then we return a FAILED status to the caller. * If we time out and not bus reset, then we return a FAILED status
* The call to mptscsih_tm_pending_wait() will set the pending flag if we are * to the caller.
* The call to mptscsih_tm_pending_wait() will set the pending flag
* if we are
* successful. Otherwise, reload the FW. * successful. Otherwise, reload the FW.
*/ */
if (mptscsih_tm_pending_wait(hd) == FAILED) { if (mptscsih_tm_pending_wait(hd) == FAILED) {
...@@ -1597,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ...@@ -1597,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
hd->ioc->name, hd->tmPending)); hd->ioc->name, hd->tmPending));
return FAILED; return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
"Timed out waiting for last TM (%d) to complete! \n", "reset: Timed out waiting for last TM (%d) "
hd->ioc->name, hd->tmPending)); "to complete! \n", hd->ioc->name,
hd->tmPending));
return FAILED; return FAILED;
} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
"Timed out waiting for last TM (%d) to complete! \n", "Timed out waiting for last TM (%d) to complete! \n",
hd->ioc->name, hd->tmPending)); hd->ioc->name, hd->tmPending));
if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
return FAILED; return FAILED;
doTask = 0;
} }
} else { } else {
spin_lock_irqsave(&hd->ioc->FreeQlock, flags); spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
...@@ -1616,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ...@@ -1616,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
} }
/* Is operational?
*/
ioc_raw_state = mpt_GetIocState(hd->ioc, 0); ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
#ifdef MPT_DEBUG_RESET
if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
printk(MYIOC_s_WARN_FMT printk(MYIOC_s_WARN_FMT
"TM Handler: IOC Not operational(0x%x)!\n", "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
hd->ioc->name, ioc_raw_state); ioc->name, type, ioc_raw_state);
printk(KERN_WARNING " Issuing HardReset!!\n");
if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
printk((KERN_WARNING "TMHandler: HardReset "
"FAILED!!\n"));
return FAILED;
} }
#endif
if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { printk(MYIOC_s_WARN_FMT
"TM Handler for type=%x: ioc_state: "
"DOORBELL_ACTIVE (0x%x)!\n",
ioc->name, type, ioc_raw_state);
return FAILED;
}
/* Isse the Task Mgmt request. /* Isse the Task Mgmt request.
*/ */
if (hd->hard_resets < -1) if (hd->hard_resets < -1)
hd->hard_resets++; hd->hard_resets++;
rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout);
if (rc) {
printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
} else {
dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
}
}
/* Only fall through to the HRH if this is a bus reset rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
*/ ctx2abort, timeout);
if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || if (rc)
ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name);
else
dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
hd->ioc->name)); hd->ioc->name));
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));
...@@ -1665,7 +1647,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ...@@ -1665,7 +1647,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* /**
* mptscsih_IssueTaskMgmt - Generic send Task Management function. * mptscsih_IssueTaskMgmt - Generic send Task Management function.
* @hd: Pointer to MPT_SCSI_HOST structure * @hd: Pointer to MPT_SCSI_HOST structure
* @type: Task Management type * @type: Task Management type
...@@ -1678,9 +1660,9 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ...@@ -1678,9 +1660,9 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
* *
* Not all fields are meaningfull for all task types. * Not all fields are meaningfull for all task types.
* *
* Returns 0 for SUCCESS, -999 for "no msg frames", * Returns 0 for SUCCESS, or FAILED.
* else other non-zero value returned. *
*/ **/
static int static int
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{ {
...@@ -1720,32 +1702,52 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i ...@@ -1720,32 +1702,52 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
pScsiTm->TaskMsgContext = ctx2abort; pScsiTm->TaskMsgContext = ctx2abort;
dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
hd->ioc->name, ctx2abort, type)); "type=%d\n", hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
CAN_SLEEP)) != 0) { dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf, retval));
hd->ioc, mf)); goto fail_out;
mpt_free_msg_frame(hd->ioc, mf);
return retval;
} }
if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
hd->ioc, mf)); hd->ioc, mf));
mpt_free_msg_frame(hd->ioc, mf);
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
hd->ioc->name)); hd->ioc->name));
retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
hd->ioc->name, retval));
goto fail_out;
} }
/*
* Handle success case, see if theres a non-zero ioc_status.
*/
if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
retval = 0;
else
retval = FAILED;
return retval; return retval;
fail_out:
/*
* Free task managment mf, and corresponding tm flags
*/
mpt_free_msg_frame(hd->ioc, mf);
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
return FAILED;
} }
static int static int
...@@ -1770,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) ...@@ -1770,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
* (linux scsi_host_template.eh_abort_handler routine) * (linux scsi_host_template.eh_abort_handler routine)
* *
* Returns SUCCESS or FAILED. * Returns SUCCESS or FAILED.
*/ **/
int int
mptscsih_abort(struct scsi_cmnd * SCpnt) mptscsih_abort(struct scsi_cmnd * SCpnt)
{ {
...@@ -1806,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1806,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
return SUCCESS; return SUCCESS;
} }
if (hd->resetPending) { if (hd->resetPending)
return FAILED; return FAILED;
}
if (hd->timeouts < -1) if (hd->timeouts < -1)
hd->timeouts++; hd->timeouts++;
...@@ -1835,9 +1836,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1835,9 +1836,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
SCpnt->serial_number == sn) { SCpnt->serial_number == sn)
retval = FAILED; 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,
...@@ -1845,11 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1845,11 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
if (retval == 0) if (retval == 0)
return SUCCESS; return SUCCESS;
else
if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
}
return FAILED; return FAILED;
} }
...@@ -1861,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ...@@ -1861,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
* (linux scsi_host_template.eh_dev_reset_handler routine) * (linux scsi_host_template.eh_dev_reset_handler routine)
* *
* Returns SUCCESS or FAILED. * Returns SUCCESS or FAILED.
*/ **/
int int
mptscsih_dev_reset(struct scsi_cmnd * SCpnt) mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{ {
...@@ -1896,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) ...@@ -1896,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
if (retval == 0) if (retval == 0)
return SUCCESS; return SUCCESS;
else
if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
}
return FAILED; return FAILED;
} }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/** /**
* mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
...@@ -1912,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) ...@@ -1912,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
* (linux scsi_host_template.eh_bus_reset_handler routine) * (linux scsi_host_template.eh_bus_reset_handler routine)
* *
* Returns SUCCESS or FAILED. * Returns SUCCESS or FAILED.
*/ **/
int int
mptscsih_bus_reset(struct scsi_cmnd * SCpnt) mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{ {
...@@ -1946,11 +1939,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) ...@@ -1946,11 +1939,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
if (retval == 0) if (retval == 0)
return SUCCESS; return SUCCESS;
else
if(retval != FAILED ) {
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
}
return FAILED; return FAILED;
} }
...@@ -2034,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) ...@@ -2034,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
/** /**
* mptscsih_tm_wait_for_completion - wait for completion of TM task * mptscsih_tm_wait_for_completion - wait for completion of TM task
* @hd: Pointer to MPT host structure. * @hd: Pointer to MPT host structure.
* @timeout: timeout in seconds
* *
* Returns {SUCCESS,FAILED}. * Returns {SUCCESS,FAILED}.
*/ */
...@@ -2108,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) ...@@ -2108,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
* load/init time via the mpt_register() API call. * load/init time via the mpt_register() API call.
* *
* Returns 1 indicating alloc'd request frame ptr should be freed. * Returns 1 indicating alloc'd request frame ptr should be freed.
*/ **/
int int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{ {
...@@ -2118,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m ...@@ -2118,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
unsigned long flags; unsigned long flags;
u16 iocstatus; u16 iocstatus;
u8 tmType; u8 tmType;
u32 termination_count;
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
ioc->name, mf, mr)); ioc->name, mf, mr));
if (ioc->sh) { if (!ioc->sh) {
/* Depending on the thread, a timer is activated for dtmprintk((MYIOC_s_WARN_FMT
* the TM request. Delete this timer on completion of TM. "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
* Decrement count of outstanding TM requests.
*/
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
} else {
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
ioc->name));
return 1; return 1;
} }
if (mr == NULL) { if (mr == NULL) {
dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", dtmprintk((MYIOC_s_WARN_FMT
ioc->name, mf)); "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
return 1; return 1;
} else { }
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
pScsiTmReply = (SCSITaskMgmtReply_t*)mr; pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
pScsiTmReq = (SCSITaskMgmt_t*)mf; pScsiTmReq = (SCSITaskMgmt_t*)mf;
/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
tmType = pScsiTmReq->TaskType; tmType = pScsiTmReq->TaskType;
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
pScsiTmReply->ResponseCode) pScsiTmReply->ResponseCode)
mptscsih_taskmgmt_response_code(ioc, mptscsih_taskmgmt_response_code(ioc,
pScsiTmReply->ResponseCode); pScsiTmReply->ResponseCode);
dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
hd->tm_iocstatus = iocstatus; printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
pScsiTmReply->TargetID, pScsiTmReq->TaskType,
le16_to_cpu(pScsiTmReply->IOCStatus),
le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
le32_to_cpu(pScsiTmReply->TerminationCount));
#endif
if (!iocstatus) {
dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
hd->abortSCpnt = NULL;
goto out;
}
/* Error? (anything non-zero?) */ /* Error? (anything non-zero?) */
if (iocstatus) {
/* clear flags and continue. /* clear flags and continue.
*/ */
if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) switch (tmType) {
case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
if (termination_count == 1)
iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
hd->abortSCpnt = NULL; hd->abortSCpnt = NULL;
break;
case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
/* If an internal command is present /* If an internal command is present
* or the TM failed - reload the FW. * or the TM failed - reload the FW.
* FC FW may respond FAILED to an ABORT * FC FW may respond FAILED to an ABORT
*/ */
if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
if ((hd->cmdPtr) || hd->cmdPtr)
(iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
printk((KERN_WARNING break;
" Firmware Reload FAILED!!\n"));
}
}
}
} else {
dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
hd->abortSCpnt = NULL;
} case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
default:
break;
} }
out:
spin_lock_irqsave(&ioc->FreeQlock, flags); spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0; hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd->tmState = TM_STATE_NONE; hd->tmState = TM_STATE_NONE;
hd->tm_iocstatus = iocstatus;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
return 1; return 1;
} }
......
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