scsi: pm80xx: Deal with kexec reboots
authorVikram Auradkar <auradkar@google.com>
Mon, 16 Mar 2020 07:49:02 +0000 (13:19 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 17 Mar 2020 17:57:15 +0000 (13:57 -0400)
A kexec reboot causes the controller fw to assert. This assertion shows up
in two ways, the controller doesn't show up as ready and an interrupt is
waiting as soon as the handler is registered. To resolve this added below
fix:

 - Split the interrupt handling setup into two parts, setup and request.

 - If the controller ready register indicates not-ready, but that the not
   readiness is only on the IOC units we can still try a reset to bring the
   system back to the pre-reboot state.

Link: https://lore.kernel.org/r/20200316074906.9119-3-deepak.ukey@microchip.com
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Signed-off-by: Vikram Auradkar <auradkar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm80xx_hwi.c

index de9e6b2dc533e0f6d26bba60508aa96ecb27aa47..c964b124a00595f5c108f86ed146abb512c3188e 100644 (file)
@@ -251,6 +251,9 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
        return ret;
 }
 
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
+static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
+
 /**
  * pm8001_alloc - initiate our hba structure and 6 DMAs area.
  * @pm8001_ha:our hba structure.
@@ -893,9 +896,7 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
  */
 static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 {
-       u32 i = 0, j = 0;
        u32 number_of_intr;
-       int flag = 0;
        int rc;
 
        /* SPCv controllers supports 64 msi-x */
@@ -903,11 +904,11 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
                number_of_intr = 1;
        } else {
                number_of_intr = PM8001_MAX_MSIX_VEC;
-               flag &= ~IRQF_SHARED;
        }
 
        rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
                        number_of_intr, PCI_IRQ_MSIX);
+       number_of_intr = rc;
        if (rc < 0)
                return rc;
        pm8001_ha->number_of_intr = number_of_intr;
@@ -915,8 +916,22 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
        PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
                "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
                                rc, pm8001_ha->number_of_intr));
+       return 0;
+}
+
+static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 i = 0, j = 0;
+       int flag = 0, rc = 0;
 
-       for (i = 0; i < number_of_intr; i++) {
+       if (pm8001_ha->chip_id != chip_8001)
+               flag &= ~IRQF_SHARED;
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("pci_enable_msix request number of intr %d\n",
+               pm8001_ha->number_of_intr));
+
+       for (i = 0; i < pm8001_ha->number_of_intr; i++) {
                snprintf(pm8001_ha->intr_drvname[i],
                        sizeof(pm8001_ha->intr_drvname[0]),
                        "%s-%d", pm8001_ha->name, i);
@@ -941,6 +956,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 }
 #endif
 
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
+{
+       struct pci_dev *pdev;
+
+       pdev = pm8001_ha->pdev;
+
+#ifdef PM8001_USE_MSIX
+       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
+               return pm8001_setup_msix(pm8001_ha);
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("MSIX not supported!!!\n"));
+#endif
+       return 0;
+}
+
 /**
  * pm8001_request_irq - register interrupt
  * @chip_info: our ha struct.
@@ -954,7 +984,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 
 #ifdef PM8001_USE_MSIX
        if (pdev->msix_cap && pci_msi_enabled())
-               return pm8001_setup_msix(pm8001_ha);
+               return pm8001_request_msix(pm8001_ha);
        else {
                PM8001_INIT_DBG(pm8001_ha,
                        pm8001_printk("MSIX not supported!!!\n"));
@@ -1036,6 +1066,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                rc = -ENOMEM;
                goto err_out_free;
        }
+       /* Setup Interrupt */
+       rc = pm8001_setup_irq(pm8001_ha);
+       if (rc) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "pm8001_setup_irq failed [ret: %d]\n", rc));
+               goto err_out_shost;
+       }
        list_add_tail(&pm8001_ha->list, &hba_list);
        PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
        rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
@@ -1048,6 +1085,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
        rc = scsi_add_host(shost, &pdev->dev);
        if (rc)
                goto err_out_ha_free;
+       /* Request Interrupt */
        rc = pm8001_request_irq(pm8001_ha);
        if (rc) {
                PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
index d1d95f1a2c6a1ab86c3a0e2df5c2ad9ce45417b8..a3989e544bbe968ffbe81216a46576478b438056 100644 (file)
@@ -1438,11 +1438,18 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
        if (!pm8001_ha->controller_fatal_error) {
                /* Check if MPI is in ready state to reset */
                if (mpi_uninit_check(pm8001_ha) != 0) {
-                       regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+                       u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
+                       u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+                       u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
+                       u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
                        PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
-                               "MPI state is not ready scratch1 :0x%x\n",
-                               regval));
-                       return -1;
+                               "MPI state is not ready scratch: %x:%x:%x:%x\n",
+                               r0, r1, r2, r3));
+                       /* if things aren't ready but the bootloader is ok then
+                        * try the reset anyway.
+                        */
+                       if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)
+                               return -1;
                }
        }
        /* checked for reset register normal state; 0x0 */