Message ID | 20210419110156.1786882-19-kashyap.desai@broadcom.com |
---|---|
State | Superseded |
Headers | show |
Series | Introducing mpi3mr driver | expand |
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Unlock the host diagnostic registers and write the specific > reset type to that, wait for reset acknowledgment from the > controller, if the reset is not successful retry for the > predefined number of times > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 3 + > drivers/scsi/mpi3mr/mpi3mr_fw.c | 245 +++++++++++++++++++++++++++++++- > 2 files changed, 246 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 3ac7b0f119bb..ff3e68a6d0b5 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -189,6 +189,9 @@ enum mpi3mr_reset_reason { > MPI3MR_RESET_FROM_EVTACK_TIMEOUT = 19, > MPI3MR_RESET_FROM_CIACTVRST_TIMER = 20, > MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT = 21, > + MPI3MR_RESET_FROM_PELABORT_TIMEOUT = 22, > + MPI3MR_RESET_FROM_SYSFS = 23, > + MPI3MR_RESET_FROM_SYSFS_TIMEOUT = 24 > }; > > /** > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c > index 76e4c87c0426..bb1d2c45e903 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c > @@ -643,6 +643,100 @@ static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state) > return name; > } > > +/* Reset reason to name mapper structure*/ > +static const struct { > + enum mpi3mr_reset_reason value; > + char *name; > +} mpi3mr_reset_reason_codes[] = { > + { MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" }, > + { MPI3MR_RESET_FROM_FAULT_WATCH, "fault" }, > + { MPI3MR_RESET_FROM_IOCTL, "application invocation" }, > + { MPI3MR_RESET_FROM_EH_HOS, "error handling" }, > + { MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" }, > + { MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" }, > + { MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" }, > + { MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" }, > + { MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" }, > + { MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" }, > + { MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" }, > + { MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" }, > + { MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" }, > + { > + MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT, > + "create request queue timeout" > + }, > + { > + MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT, > + "create reply queue timeout" > + }, Don’t understand the change in formatting above ?? > + { MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" }, > + { MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" }, > + { MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" }, > + { MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" }, > + { > + MPI3MR_RESET_FROM_CIACTVRST_TIMER, > + "component image activation timeout" > + }, > + { > + MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT, > + "get package version timeout" > + }, And here ?? > + { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, > + { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, > +}; > + > +/** > + * mpi3mr_reset_rc_name - get reset reason code name > + * @reason_code: reset reason code value > + * > + * Map reset reason to an NULL terminated ASCII string > + * > + * Return: Name corresponding to reset reason value or NULL. > + */ > +static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code) > +{ > + int i; > + char *name = NULL; > + > + for (i = 0; i < ARRAY_SIZE(mpi3mr_reset_reason_codes); i++) { > + if (mpi3mr_reset_reason_codes[i].value == reason_code) { > + name = mpi3mr_reset_reason_codes[i].name; > + break; > + } > + } > + return name; > +} > + > +/* Reset type to name mapper structure*/ > +static const struct { > + u16 reset_type; > + char *name; > +} mpi3mr_reset_types[] = { > + { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" }, > + { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" }, > +}; > + > +/** > + * mpi3mr_reset_type_name - get reset type name > + * @reset_type: reset type value > + * > + * Map reset type to an NULL terminated ASCII string > + * > + * Return: Name corresponding to reset type value or NULL. > + */ > +static const char *mpi3mr_reset_type_name(u16 reset_type) > +{ > + int i; > + char *name = NULL; > + > + for (i = 0; i < ARRAY_SIZE(mpi3mr_reset_types); i++) { > + if (mpi3mr_reset_types[i].reset_type == reset_type) { > + name = mpi3mr_reset_types[i].name; > + break; > + } > + } > + return name; > +} > > /** > * mpi3mr_print_fault_info - Display fault information > @@ -806,6 +900,48 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc) > return -1; > } > > +/** > + * mpi3mr_soft_reset_success - Check softreset is success or not > + * @ioc_status: IOC status register value > + * @ioc_config: IOC config register value > + * > + * Check whether the soft reset is successful or not based on > + * IOC status and IOC config register values. > + * > + * Return: True when the soft reset is success, false otherwise. > + */ > +static inline bool > +mpi3mr_soft_reset_success(u32 ioc_status, u32 ioc_config) > +{ > + if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || > + (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || > + (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) > + return true; > + return false; > +} > + > +/** > + * mpi3mr_diagfault_success - Check diag fault is success or not > + * @mrioc: Adapter reference > + * @ioc_status: IOC status register value > + * > + * Check whether the controller hit diag reset fault code. > + * > + * Return: True when there is diag fault, false otherwise. > + */ > +static inline bool mpi3mr_diagfault_success(struct mpi3mr_ioc *mrioc, > + u32 ioc_status) > +{ > + u32 fault; > + > + if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) > + return false; > + fault = readl(&mrioc->sysif_regs->Fault) & MPI3_SYSIF_FAULT_CODE_MASK; > + if (fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) > + return true; > + return false; > +} > + > /** > * mpi3mr_set_diagsave - Set diag save bit for snapdump > * @mrioc: Adapter reference > @@ -830,14 +966,117 @@ static inline void mpi3mr_set_diagsave(struct mpi3mr_ioc *mrioc) > * @reset_type: Reset type > * @reset_reason: Reset reason code > * > - * TBD > + * Unlock the host diagnostic registers and write the specific > + * reset type to that, wait for reset acknowledgment from the > + * controller, if the reset is not successful retry for the > + * predefined number of times. > * > * Return: 0 on success, non-zero on failure. > */ > static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, > u32 reset_reason) > { > - return 0; > + int retval = -1; > + u8 unlock_retry_count, reset_retry_count = 0; > + u32 host_diagnostic, timeout, ioc_status, ioc_config; > + > + pci_cfg_access_lock(mrioc->pdev); > + if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && > + (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)) > + goto out; > + if (mrioc->unrecoverable) > + goto out; > +retry_reset: > + unlock_retry_count = 0; > + mpi3mr_clear_reset_history(mrioc); > + do { > + ioc_info(mrioc, > + "Write magic sequence to unlock host diag register (retry=%d)\n", > + ++unlock_retry_count); > + if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) { > + writel(reset_reason, &mrioc->sysif_regs->Scratchpad[0]); > + mrioc->unrecoverable = 1; > + goto out; > + } > + > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH, > + &mrioc->sysif_regs->WriteSequence); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH, > + &mrioc->sysif_regs->WriteSequence); > + usleep_range(1000, 1100); > + host_diagnostic = readl(&mrioc->sysif_regs->HostDiagnostic); > + ioc_info(mrioc, > + "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n", > + unlock_retry_count, host_diagnostic); > + } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE)); > + > + writel(reset_reason, &mrioc->sysif_regs->Scratchpad[0]); > + ioc_info(mrioc, "%s reset due to %s(0x%x)\n", > + mpi3mr_reset_type_name(reset_type), > + mpi3mr_reset_rc_name(reset_reason), reset_reason); > + writel(host_diagnostic | reset_type, > + &mrioc->sysif_regs->HostDiagnostic); > + timeout = mrioc->ready_timeout * 10; > + if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) { > + do { > + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); > + if (ioc_status & > + MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { > + mpi3mr_clear_reset_history(mrioc); > + ioc_config = > + readl(&mrioc->sysif_regs->IOCConfiguration); > + if (mpi3mr_soft_reset_success(ioc_status, > + ioc_config)) { > + retval = 0; > + break; > + } > + } > + msleep(100); > + } while (--timeout); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, > + &mrioc->sysif_regs->WriteSequence); > + } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) { > + do { > + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); > + if (mpi3mr_diagfault_success(mrioc, ioc_status)) { > + retval = 0; > + break; > + } > + msleep(100); > + } while (--timeout); > + mpi3mr_clear_reset_history(mrioc); > + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, > + &mrioc->sysif_regs->WriteSequence); > + } > + if (retval && ((++reset_retry_count) < MPI3MR_MAX_RESET_RETRY_COUNT)) { > + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); > + ioc_config = readl(&mrioc->sysif_regs->IOCConfiguration); > + ioc_info(mrioc, > + "Base IOC Sts/Config after reset try %d is (0x%x)/(0x%x)\n", > + reset_retry_count, ioc_status, ioc_config); > + goto retry_reset; > + } > + > +out: > + pci_cfg_access_unlock(mrioc->pdev); > + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); > + ioc_config = readl(&mrioc->sysif_regs->IOCConfiguration); > + > + ioc_info(mrioc, > + "Base IOC Sts/Config after %s reset is (0x%x)/(0x%x)\n", > + (!retval)?"successful":"failed", ioc_status, > + ioc_config); > + return retval; > } > > /** > @@ -3462,6 +3701,8 @@ int mpi3mr_diagfault_reset_handler(struct mpi3mr_ioc *mrioc, > { > int retval = 0; > > + ioc_info(mrioc, "Entry: reason code: %s\n", > + mpi3mr_reset_rc_name(reset_reason)); > mrioc->reset_in_progress = 1; > > mpi3mr_ioc_disable_intr(mrioc); > -- > 2.18.1 > Patch looks fine. Once you fix formatting, Please add Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 3ac7b0f119bb..ff3e68a6d0b5 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -189,6 +189,9 @@ enum mpi3mr_reset_reason { MPI3MR_RESET_FROM_EVTACK_TIMEOUT = 19, MPI3MR_RESET_FROM_CIACTVRST_TIMER = 20, MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT = 21, + MPI3MR_RESET_FROM_PELABORT_TIMEOUT = 22, + MPI3MR_RESET_FROM_SYSFS = 23, + MPI3MR_RESET_FROM_SYSFS_TIMEOUT = 24 }; /** diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 76e4c87c0426..bb1d2c45e903 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -643,6 +643,100 @@ static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state) return name; } +/* Reset reason to name mapper structure*/ +static const struct { + enum mpi3mr_reset_reason value; + char *name; +} mpi3mr_reset_reason_codes[] = { + { MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" }, + { MPI3MR_RESET_FROM_FAULT_WATCH, "fault" }, + { MPI3MR_RESET_FROM_IOCTL, "application invocation" }, + { MPI3MR_RESET_FROM_EH_HOS, "error handling" }, + { MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" }, + { MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" }, + { MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" }, + { MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" }, + { MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" }, + { MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" }, + { MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" }, + { MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" }, + { MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" }, + { + MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT, + "create request queue timeout" + }, + { + MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT, + "create reply queue timeout" + }, + { MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" }, + { MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" }, + { MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" }, + { MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" }, + { + MPI3MR_RESET_FROM_CIACTVRST_TIMER, + "component image activation timeout" + }, + { + MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT, + "get package version timeout" + }, + { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, + { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, +}; + +/** + * mpi3mr_reset_rc_name - get reset reason code name + * @reason_code: reset reason code value + * + * Map reset reason to an NULL terminated ASCII string + * + * Return: Name corresponding to reset reason value or NULL. + */ +static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code) +{ + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(mpi3mr_reset_reason_codes); i++) { + if (mpi3mr_reset_reason_codes[i].value == reason_code) { + name = mpi3mr_reset_reason_codes[i].name; + break; + } + } + return name; +} + +/* Reset type to name mapper structure*/ +static const struct { + u16 reset_type; + char *name; +} mpi3mr_reset_types[] = { + { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" }, + { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" }, +}; + +/** + * mpi3mr_reset_type_name - get reset type name + * @reset_type: reset type value + * + * Map reset type to an NULL terminated ASCII string + * + * Return: Name corresponding to reset type value or NULL. + */ +static const char *mpi3mr_reset_type_name(u16 reset_type) +{ + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(mpi3mr_reset_types); i++) { + if (mpi3mr_reset_types[i].reset_type == reset_type) { + name = mpi3mr_reset_types[i].name; + break; + } + } + return name; +} /** * mpi3mr_print_fault_info - Display fault information @@ -806,6 +900,48 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc) return -1; } +/** + * mpi3mr_soft_reset_success - Check softreset is success or not + * @ioc_status: IOC status register value + * @ioc_config: IOC config register value + * + * Check whether the soft reset is successful or not based on + * IOC status and IOC config register values. + * + * Return: True when the soft reset is success, false otherwise. + */ +static inline bool +mpi3mr_soft_reset_success(u32 ioc_status, u32 ioc_config) +{ + if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || + (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || + (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) + return true; + return false; +} + +/** + * mpi3mr_diagfault_success - Check diag fault is success or not + * @mrioc: Adapter reference + * @ioc_status: IOC status register value + * + * Check whether the controller hit diag reset fault code. + * + * Return: True when there is diag fault, false otherwise. + */ +static inline bool mpi3mr_diagfault_success(struct mpi3mr_ioc *mrioc, + u32 ioc_status) +{ + u32 fault; + + if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) + return false; + fault = readl(&mrioc->sysif_regs->Fault) & MPI3_SYSIF_FAULT_CODE_MASK; + if (fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) + return true; + return false; +} + /** * mpi3mr_set_diagsave - Set diag save bit for snapdump * @mrioc: Adapter reference @@ -830,14 +966,117 @@ static inline void mpi3mr_set_diagsave(struct mpi3mr_ioc *mrioc) * @reset_type: Reset type * @reset_reason: Reset reason code * - * TBD + * Unlock the host diagnostic registers and write the specific + * reset type to that, wait for reset acknowledgment from the + * controller, if the reset is not successful retry for the + * predefined number of times. * * Return: 0 on success, non-zero on failure. */ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, u32 reset_reason) { - return 0; + int retval = -1; + u8 unlock_retry_count, reset_retry_count = 0; + u32 host_diagnostic, timeout, ioc_status, ioc_config; + + pci_cfg_access_lock(mrioc->pdev); + if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && + (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)) + goto out; + if (mrioc->unrecoverable) + goto out; +retry_reset: + unlock_retry_count = 0; + mpi3mr_clear_reset_history(mrioc); + do { + ioc_info(mrioc, + "Write magic sequence to unlock host diag register (retry=%d)\n", + ++unlock_retry_count); + if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) { + writel(reset_reason, &mrioc->sysif_regs->Scratchpad[0]); + mrioc->unrecoverable = 1; + goto out; + } + + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH, + &mrioc->sysif_regs->WriteSequence); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH, + &mrioc->sysif_regs->WriteSequence); + usleep_range(1000, 1100); + host_diagnostic = readl(&mrioc->sysif_regs->HostDiagnostic); + ioc_info(mrioc, + "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n", + unlock_retry_count, host_diagnostic); + } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE)); + + writel(reset_reason, &mrioc->sysif_regs->Scratchpad[0]); + ioc_info(mrioc, "%s reset due to %s(0x%x)\n", + mpi3mr_reset_type_name(reset_type), + mpi3mr_reset_rc_name(reset_reason), reset_reason); + writel(host_diagnostic | reset_type, + &mrioc->sysif_regs->HostDiagnostic); + timeout = mrioc->ready_timeout * 10; + if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) { + do { + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); + if (ioc_status & + MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { + mpi3mr_clear_reset_history(mrioc); + ioc_config = + readl(&mrioc->sysif_regs->IOCConfiguration); + if (mpi3mr_soft_reset_success(ioc_status, + ioc_config)) { + retval = 0; + break; + } + } + msleep(100); + } while (--timeout); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, + &mrioc->sysif_regs->WriteSequence); + } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) { + do { + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); + if (mpi3mr_diagfault_success(mrioc, ioc_status)) { + retval = 0; + break; + } + msleep(100); + } while (--timeout); + mpi3mr_clear_reset_history(mrioc); + writel(MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND, + &mrioc->sysif_regs->WriteSequence); + } + if (retval && ((++reset_retry_count) < MPI3MR_MAX_RESET_RETRY_COUNT)) { + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); + ioc_config = readl(&mrioc->sysif_regs->IOCConfiguration); + ioc_info(mrioc, + "Base IOC Sts/Config after reset try %d is (0x%x)/(0x%x)\n", + reset_retry_count, ioc_status, ioc_config); + goto retry_reset; + } + +out: + pci_cfg_access_unlock(mrioc->pdev); + ioc_status = readl(&mrioc->sysif_regs->IOCStatus); + ioc_config = readl(&mrioc->sysif_regs->IOCConfiguration); + + ioc_info(mrioc, + "Base IOC Sts/Config after %s reset is (0x%x)/(0x%x)\n", + (!retval)?"successful":"failed", ioc_status, + ioc_config); + return retval; } /** @@ -3462,6 +3701,8 @@ int mpi3mr_diagfault_reset_handler(struct mpi3mr_ioc *mrioc, { int retval = 0; + ioc_info(mrioc, "Entry: reason code: %s\n", + mpi3mr_reset_rc_name(reset_reason)); mrioc->reset_in_progress = 1; mpi3mr_ioc_disable_intr(mrioc);