]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: mpi3mr: Add retry mechanism for IOC shutdown with timeout reset
authorRanjan Kumar <ranjan.kumar@broadcom.com>
Fri, 20 Mar 2026 09:03:26 +0000 (14:33 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 27 Mar 2026 21:09:01 +0000 (17:09 -0400)
Enhance the IOC shutdown process to handle transient failures during
controller cleanup. Add retry logic with configurable maximum retry
count (MPI3MR_MAX_SHUTDOWN_RETRY_COUNT) and proper timeout management
that resets on each retry attempt. This ensures shutdown can recover
from temporary issues without failing completely.

Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Link: https://patch.msgid.link/20260320090326.47544-4-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpi3mr/mpi3mr.h
drivers/scsi/mpi3mr/mpi3mr_fw.c

index 631a48f7425d937335a2bc0d9edc5a5ba696e92e..c25525fe0671a824943d69db69f3f132495998d1 100644 (file)
@@ -159,6 +159,7 @@ extern atomic64_t event_counter;
 /* Controller Reset related definitions */
 #define MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT     5
 #define MPI3MR_MAX_RESET_RETRY_COUNT           3
+#define MPI3MR_MAX_SHUTDOWN_RETRY_COUNT                2
 
 /* ResponseCode definitions */
 #define MPI3MR_RI_MASK_RESPCODE                (0x000000FF)
index 54debf16c2e6736cbe13b7d27949b79b3c4f44c8..01042eaf0dff4720c65f72b617cbb63d645f0c23 100644 (file)
@@ -5058,9 +5058,9 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
  */
 static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
 {
-       u32 ioc_config, ioc_status;
-       u8 retval = 1;
-       u32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10;
+       u32 ioc_config, ioc_status, shutdown_action;
+       u8 retval = 1, retry = 0;
+       u32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10, timeout_remaining = 0;
 
        ioc_info(mrioc, "Issuing shutdown Notification\n");
        if (mrioc->unrecoverable) {
@@ -5075,14 +5075,16 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
                return;
        }
 
+       shutdown_action = MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL |
+           MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
        ioc_config = readl(&mrioc->sysif_regs->ioc_configuration);
-       ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
-       ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
+       ioc_config |= shutdown_action;
 
        writel(ioc_config, &mrioc->sysif_regs->ioc_configuration);
 
        if (mrioc->facts.shutdown_timeout)
                timeout = mrioc->facts.shutdown_timeout * 10;
+       timeout_remaining = timeout;
 
        do {
                ioc_status = readl(&mrioc->sysif_regs->ioc_status);
@@ -5091,8 +5093,26 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
                        retval = 0;
                        break;
                }
+               if (mrioc->unrecoverable)
+                       break;
+               if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
+                       mpi3mr_print_fault_info(mrioc);
+                       if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT)
+                               break;
+                       if (mpi3mr_issue_reset(mrioc,
+                           MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
+                           MPI3MR_RESET_FROM_CTLR_CLEANUP))
+                               break;
+                       ioc_config =
+                           readl(&mrioc->sysif_regs->ioc_configuration);
+                       ioc_config |= shutdown_action;
+                       writel(ioc_config,
+                           &mrioc->sysif_regs->ioc_configuration);
+                       timeout_remaining = timeout;
+                       retry++;
+               }
                msleep(100);
-       } while (--timeout);
+       } while (--timeout_remaining);
 
        ioc_status = readl(&mrioc->sysif_regs->ioc_status);
        ioc_config = readl(&mrioc->sysif_regs->ioc_configuration);