scsi: pm80xx: Add GET_NVMD timeout during probe
authorChangyuan Lyu <changyuanl@google.com>
Wed, 19 Apr 2023 17:55:02 +0000 (17:55 +0000)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 8 May 2023 11:15:38 +0000 (07:15 -0400)
Add a wait timeout to prevent the kernel from waiting for the GET_NVMD
response forever during probe. Add a check for the controller state before
issuing GET_NVMD request.

Signed-off-by: Changyuan Lyu <changyuanl@google.com>
Signed-off-by: Pranav Prasad <pranavpp@google.com>
Link: https://lore.kernel.org/r/20230419175502.919999-1-pranavpp@google.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/pm8001/pm8001_init.c

index c23250a..2e886c1 100644 (file)
@@ -667,7 +667,7 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
  * Currently we just set the fixed SAS address to our HBA, for manufacture,
  * it should read from the EEPROM
  */
-static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
        u8 i, j;
        u8 sas_add[8];
@@ -680,6 +680,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        struct pm8001_ioctl_payload payload;
        u16 deviceid;
        int rc;
+       unsigned long time_remaining;
+
+       if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) {
+               pm8001_dbg(pm8001_ha, FAIL, "controller is in fatal error state\n");
+               return -EIO;
+       }
 
        pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
        pm8001_ha->nvmd_completion = &completion;
@@ -704,16 +710,23 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        payload.offset = 0;
        payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
        if (!payload.func_specific) {
-               pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n");
-               return;
+               pm8001_dbg(pm8001_ha, FAIL, "mem alloc fail\n");
+               return -ENOMEM;
        }
        rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
        if (rc) {
                kfree(payload.func_specific);
-               pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
-               return;
+               pm8001_dbg(pm8001_ha, FAIL, "nvmd failed\n");
+               return -EIO;
+       }
+       time_remaining = wait_for_completion_timeout(&completion,
+                               msecs_to_jiffies(60*1000)); // 1 min
+       if (!time_remaining) {
+               kfree(payload.func_specific);
+               pm8001_dbg(pm8001_ha, FAIL, "get_nvmd_req timeout\n");
+               return -EIO;
        }
-       wait_for_completion(&completion);
+
 
        for (i = 0, j = 0; i <= 7; i++, j++) {
                if (pm8001_ha->chip_id == chip_8001) {
@@ -752,6 +765,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
        memcpy(pm8001_ha->sas_addr, &pm8001_ha->phy[0].dev_sas_addr,
                SAS_ADDR_SIZE);
 #endif
+       return 0;
 }
 
 /*
@@ -1167,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                pm80xx_set_thermal_config(pm8001_ha);
        }
 
-       pm8001_init_sas_add(pm8001_ha);
+       if (pm8001_init_sas_add(pm8001_ha))
+               goto err_out_shost;
        /* phy setting support for motherboard controller */
        rc = pm8001_configure_phy_settings(pm8001_ha);
        if (rc)