OSDN Git Service

scsi: megaraid_sas: Reset adapter if FW is not in READY state after device resume
authorAnand Lodnoor <anand.lodnoor@broadcom.com>
Tue, 14 Jan 2020 11:21:12 +0000 (16:51 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 16 Jan 2020 04:21:02 +0000 (23:21 -0500)
After device resume we expect the firmware to be in READY state.
Transition to READY might fail due to unhandled exceptions, such as an
internal error or a hardware failure. Retry initiating chip reset and wait
for the controller to come to ready state.

Link: https://lore.kernel.org/r/1579000882-20246-2-git-send-email-anand.lodnoor@broadcom.com
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: Anand Lodnoor <anand.lodnoor@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/megaraid/megaraid_sas_base.c

index a4bc814..6a01a60 100644 (file)
@@ -7593,6 +7593,7 @@ megasas_resume(struct pci_dev *pdev)
        struct Scsi_Host *host;
        struct megasas_instance *instance;
        int irq_flags = PCI_IRQ_LEGACY;
+       u32 status_reg;
 
        instance = pci_get_drvdata(pdev);
 
@@ -7620,9 +7621,35 @@ megasas_resume(struct pci_dev *pdev)
        /*
         * We expect the FW state to be READY
         */
-       if (megasas_transition_to_ready(instance, 0))
-               goto fail_ready_state;
 
+       if (megasas_transition_to_ready(instance, 0)) {
+               dev_info(&instance->pdev->dev,
+                        "Failed to transition controller to ready from %s!\n",
+                        __func__);
+               if (instance->adapter_type != MFI_SERIES) {
+                       status_reg =
+                               instance->instancet->read_fw_status_reg(instance);
+                       if (!(status_reg & MFI_RESET_ADAPTER) ||
+                               ((megasas_adp_reset_wait_for_ready
+                               (instance, true, 0)) == FAILED))
+                               goto fail_ready_state;
+               } else {
+                       atomic_set(&instance->fw_reset_no_pci_access, 1);
+                       instance->instancet->adp_reset
+                               (instance, instance->reg_set);
+                       atomic_set(&instance->fw_reset_no_pci_access, 0);
+
+                       /* waiting for about 30 seconds before retry */
+                       ssleep(30);
+
+                       if (megasas_transition_to_ready(instance, 0))
+                               goto fail_ready_state;
+               }
+
+               dev_info(&instance->pdev->dev,
+                        "FW restarted successfully from %s!\n",
+                        __func__);
+       }
        if (megasas_set_dma_mask(instance))
                goto fail_set_dma_mask;