diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 517621fa8bca..e9c6a6047a00 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6474,8 +6474,19 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) pReq->Action, ioc->mptbase_cmds.status, timeleft)); if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) goto out; - if (!timeleft) + if (!timeleft) { + spin_lock_irqsave(&ioc->taskmgmt_lock, flags); + if (ioc->ioc_reset_in_progress) { + spin_unlock_irqrestore(&ioc->taskmgmt_lock, + flags); + printk(MYIOC_s_INFO_FMT "%s: host reset in" + " progress mpt_config timed out.!!\n", + __func__, ioc->name); + return -EFAULT; + } + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); issue_hard_reset = 1; + } goto out; } @@ -7189,7 +7200,18 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) spin_lock_irqsave(&ioc->taskmgmt_lock, flags); if (ioc->ioc_reset_in_progress) { spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); - return 0; + ioc->wait_on_reset_completion = 1; + do { + ssleep(1); + } while (ioc->ioc_reset_in_progress == 1); + ioc->wait_on_reset_completion = 0; + return ioc->reset_status; + } + if (ioc->wait_on_reset_completion) { + spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + rc = 0; + time_count = jiffies; + goto exit; } ioc->ioc_reset_in_progress = 1; if (ioc->alt_ioc) @@ -7226,6 +7248,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) ioc->ioc_reset_in_progress = 0; ioc->taskmgmt_quiesce_io = 0; ioc->taskmgmt_in_progress = 0; + ioc->reset_status = rc; if (ioc->alt_ioc) { ioc->alt_ioc->ioc_reset_in_progress = 0; ioc->alt_ioc->taskmgmt_quiesce_io = 0; @@ -7241,7 +7264,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) ioc->alt_ioc, MPT_IOC_POST_RESET); } } - +exit: dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler: completed (%d seconds): %s\n", ioc->name, diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index a4048ea45c92..b4d24dc081ae 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -753,6 +753,8 @@ typedef struct _MPT_ADAPTER int taskmgmt_in_progress; u8 taskmgmt_quiesce_io; u8 ioc_reset_in_progress; + u8 reset_status; + u8 wait_on_reset_completion; MPT_SCHEDULE_TARGET_RESET schedule_target_reset; MPT_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; struct work_struct sas_persist_task; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 074e52254fcd..9d9504298549 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1950,6 +1950,15 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc) goto done; } + /* In case if IOC is in reset from internal context. + * Do not execute EEH for the same IOC. SML should to reset timer. + */ + if (ioc->ioc_reset_in_progress) { + dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset," + "SML need to reset the timer (sc=%p)\n", + ioc->name, __func__, sc)); + rc = BLK_EH_RESET_TIMER; + } vdevice = sc->device->hostdata; if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD || vdevice->vtarget->deleted)) { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index de8cf92d8614..ced6e4dc0847 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1630,7 +1630,13 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, return 0; } - if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { + /* DOORBELL ACTIVE check is not required if + * MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported. + */ + + if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) + && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) && + (ioc_raw_state & MPI_DOORBELL_ACTIVE)) { printk(MYIOC_s_WARN_FMT "TaskMgmt type=%x: ioc_state: " "DOORBELL_ACTIVE (0x%x)!\n", @@ -1729,7 +1735,9 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!! doorbell=0x%08x\n", ioc->name, __func__, mpt_GetIocState(ioc, 0)); - retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); + retval = (ioc->bus_type == SAS) ? + mpt_HardResetHandler(ioc, CAN_SLEEP) : + mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); mpt_free_msg_frame(ioc, mf); }