summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001
diff options
context:
space:
mode:
authorPeter Chang <dpf@google.com>2020-03-16 08:49:04 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2020-03-17 18:57:16 +0100
commitb40f28820fbafbcb0e0ec555fc2bca76ac1d9612 (patch)
treead0a666d16ed3496d9268b08e87b4135edd665eb /drivers/scsi/pm8001
parentscsi: pm80xx: Free the tag when mpi_set_phy_profile_resp is received (diff)
downloadlinux-b40f28820fbafbcb0e0ec555fc2bca76ac1d9612.tar.xz
linux-b40f28820fbafbcb0e0ec555fc2bca76ac1d9612.zip
scsi: pm80xx: Cleanup initialization loading fail path
1) Move the instance tracking down after we think the instance is good to go. Avoids having a use-after free. 2) There are goto targets for trying to cleanup if the hw fails to initialize, but there's some overlap depending on who thinks they own the sub-structures. Link: https://lore.kernel.org/r/20200316074906.9119-5-deepak.ukey@microchip.com Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Peter Chang <dpf@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>
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index c964b124a005..8fa82bf1a454 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1019,6 +1019,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
struct pm8001_hba_info *pm8001_ha;
struct Scsi_Host *shost = NULL;
const struct pm8001_chip_info *chip;
+ struct sas_ha_struct *sha;
dev_printk(KERN_INFO, &pdev->dev,
"pm80xx: driver version %s\n", DRV_VERSION);
@@ -1047,12 +1048,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
goto err_out_regions;
}
chip = &pm8001_chips[ent->driver_data];
- SHOST_TO_SAS_HA(shost) =
- kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
- if (!SHOST_TO_SAS_HA(shost)) {
+ sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
+ if (!sha) {
rc = -ENOMEM;
goto err_out_free_host;
}
+ SHOST_TO_SAS_HA(shost) = sha;
rc = pm8001_prep_sas_ha_init(shost, chip);
if (rc) {
@@ -1073,7 +1074,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
"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);
if (rc) {
@@ -1108,8 +1109,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
pm8001_post_sas_ha_init(shost, chip);
rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
- if (rc)
+ if (rc) {
+ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+ "sas_register_ha failed [ret: %d]\n", rc));
goto err_out_shost;
+ }
+ list_add_tail(&pm8001_ha->list, &hba_list);
scsi_scan_host(pm8001_ha->shost);
pm8001_ha->flags = PM8001F_RUN_TIME;
return 0;
@@ -1119,7 +1124,7 @@ err_out_shost:
err_out_ha_free:
pm8001_free(pm8001_ha);
err_out_free:
- kfree(SHOST_TO_SAS_HA(shost));
+ kfree(sha);
err_out_free_host:
scsi_host_put(shost);
err_out_regions: