]> www.infradead.org Git - linux-platform-drivers-x86.git/commitdiff
scsi: pm80xx: Fix drives missing during rmmod/insmod loop
authorAjish Koshy <ajish.koshy@microchip.com>
Wed, 5 May 2021 12:01:03 +0000 (17:31 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 15 May 2021 22:07:43 +0000 (18:07 -0400)
When driver is loaded after rmmod some drives are not showing up during
discovery.

SATA drives are directly attached to the controller connected phys.  During
device discovery, the IDENTIFY command (qc timeout (cmd 0xec)) is timing out
during revalidation. This will trigger abort from host side and controller
successfully aborts the command and returns success. Post this successful
abort response ATA library decides to mark the disk as NODEV.

To overcome this, inside pm8001_scan_start() after phy_start() call, add get
start response and wait for few milliseconds to trigger next phy start.
This millisecond delay will give sufficient time for the controller state
machine to accept next phy start.

Link: https://lore.kernel.org/r/20210505120103.24497-1-ajish.koshy@microchip.com
Signed-off-by: Ajish Koshy <ajish.koshy@microchip.com>
Signed-off-by: Viswas G <viswas.g@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm80xx_hwi.c

index ecd06d2d7e81624553b67f4da111d7603dca6341..71aa6af08340612e28454018d98d274b1bf31e69 100644 (file)
@@ -3765,11 +3765,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case HW_EVENT_PHY_START_STATUS:
                pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS status = %x\n",
                           status);
-               if (status == 0) {
+               if (status == 0)
                        phy->phy_state = 1;
-                       if (pm8001_ha->flags == PM8001F_RUN_TIME &&
-                                       phy->enable_completion != NULL)
-                               complete(phy->enable_completion);
+
+               if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+                               phy->enable_completion != NULL) {
+                       complete(phy->enable_completion);
+                       phy->enable_completion = NULL;
                }
                break;
        case HW_EVENT_SAS_PHY_UP:
index 390c33df03578e7bc876e266ef9d3ad98a4ab57d..af09bd282cb94d80861c37a297d7b1ac2c38767a 100644 (file)
@@ -1151,8 +1151,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                goto err_out_shost;
        }
        list_add_tail(&pm8001_ha->list, &hba_list);
-       scsi_scan_host(pm8001_ha->shost);
        pm8001_ha->flags = PM8001F_RUN_TIME;
+       scsi_scan_host(pm8001_ha->shost);
        return 0;
 
 err_out_shost:
index d28af413b93a227014e529addec26d2ff54ee68b..335cf37e6cb94053f6cade51993afebb1ded3e22 100644 (file)
@@ -264,12 +264,17 @@ void pm8001_scan_start(struct Scsi_Host *shost)
        int i;
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+       DECLARE_COMPLETION_ONSTACK(completion);
        pm8001_ha = sha->lldd_ha;
        /* SAS_RE_INITIALIZATION not available in SPCv/ve */
        if (pm8001_ha->chip_id == chip_8001)
                PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
-       for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
+       for (i = 0; i < pm8001_ha->chip->n_phy; ++i) {
+               pm8001_ha->phy[i].enable_completion = &completion;
                PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
+               wait_for_completion(&completion);
+               msleep(300);
+       }
 }
 
 int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time)
index 4e980830f9f59f137f1a80cefaba49199ee6894c..700530e969ac0d125170a3a038b692d8928cdcd0 100644 (file)
@@ -3487,13 +3487,13 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        pm8001_dbg(pm8001_ha, INIT,
                   "phy start resp status:0x%x, phyid:0x%x\n",
                   status, phy_id);
-       if (status == 0) {
+       if (status == 0)
                phy->phy_state = PHY_LINK_DOWN;
-               if (pm8001_ha->flags == PM8001F_RUN_TIME &&
-                               phy->enable_completion != NULL) {
-                       complete(phy->enable_completion);
-                       phy->enable_completion = NULL;
-               }
+
+       if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+                       phy->enable_completion != NULL) {
+               complete(phy->enable_completion);
+               phy->enable_completion = NULL;
        }
        return 0;