gpu: nvgpu: fix memory leaks in error path

Error path is not implemented in nvgpu_pci_probe(), and that could lead to
memory leaks if any of the step in nvgpu_pci_probe() fails

Fix this by implementing error path and freeing all allocated buffers

Bug 200291879
Coverify defect id : 2845621

Change-Id: Iee1abb041089e47a517a6698f0a4067c9c4fa289
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1681028
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Deepak Nibade
2018-03-23 05:44:19 -07:00
committed by mobile promotions
parent cb8d8337a6
commit b1ac66d418

View File

@@ -549,7 +549,8 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
sizeof(struct gk20a_platform)); sizeof(struct gk20a_platform));
if (!platform) { if (!platform) {
dev_err(&pdev->dev, "couldn't allocate platform data"); dev_err(&pdev->dev, "couldn't allocate platform data");
return -ENOMEM; err = -ENOMEM;
goto err_free_l;
} }
/* copy detected device data to allocated platform space*/ /* copy detected device data to allocated platform space*/
@@ -559,10 +560,8 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, platform); pci_set_drvdata(pdev, platform);
err = nvgpu_init_enabled_flags(g); err = nvgpu_init_enabled_flags(g);
if (err) { if (err)
kfree(g); goto err_free_platform;
return err;
}
platform->g = g; platform->g = g;
l->dev = &pdev->dev; l->dev = &pdev->dev;
@@ -575,7 +574,7 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
return err; goto err_free_platform;
pci_set_master(pdev); pci_set_master(pdev);
g->pci_vendor_id = pdev->vendor; g->pci_vendor_id = pdev->vendor;
@@ -597,8 +596,10 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
g->irq_stall = pdev->irq; g->irq_stall = pdev->irq;
g->irq_nonstall = pdev->irq; g->irq_nonstall = pdev->irq;
if (g->irq_stall < 0) if (g->irq_stall < 0) {
return -ENXIO; err = -ENXIO;
goto err_disable_msi;
}
err = devm_request_threaded_irq(&pdev->dev, err = devm_request_threaded_irq(&pdev->dev,
g->irq_stall, g->irq_stall,
@@ -611,17 +612,18 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
if (err) { if (err) {
nvgpu_err(g, nvgpu_err(g,
"failed to request irq @ %d", g->irq_stall); "failed to request irq @ %d", g->irq_stall);
return err; goto err_disable_msi;
} }
disable_irq(g->irq_stall); disable_irq(g->irq_stall);
err = nvgpu_pci_init_support(pdev); err = nvgpu_pci_init_support(pdev);
if (err) if (err)
return err; goto err_free_irq;
if (strchr(dev_name(&pdev->dev), '%')) { if (strchr(dev_name(&pdev->dev), '%')) {
nvgpu_err(g, "illegal character in device name"); nvgpu_err(g, "illegal character in device name");
return -EINVAL; err = -EINVAL;
goto err_free_irq;
} }
snprintf(nodefmt, sizeof(nodefmt), snprintf(nodefmt, sizeof(nodefmt),
@@ -629,12 +631,12 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
err = nvgpu_probe(g, "gpu_pci", nodefmt, &nvgpu_pci_class); err = nvgpu_probe(g, "gpu_pci", nodefmt, &nvgpu_pci_class);
if (err) if (err)
return err; goto err_free_irq;
err = nvgpu_pci_pm_init(&pdev->dev); err = nvgpu_pci_pm_init(&pdev->dev);
if (err) { if (err) {
nvgpu_err(g, "pm init failed"); nvgpu_err(g, "pm init failed");
return err; goto err_free_irq;
} }
err = nvgpu_nvlink_probe(g); err = nvgpu_nvlink_probe(g);
@@ -645,13 +647,26 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
if (err) { if (err) {
if (err != -ENODEV) { if (err != -ENODEV) {
nvgpu_err(g, "fatal error probing nvlink, bailing out"); nvgpu_err(g, "fatal error probing nvlink, bailing out");
return err; goto err_free_irq;
} }
} }
g->mm.has_physical_mode = false; g->mm.has_physical_mode = false;
return 0; return 0;
err_free_irq:
nvgpu_free_irq(g);
err_disable_msi:
#if defined(CONFIG_PCI_MSI)
if (g->msi_enabled)
pci_disable_msi(pdev);
#endif
err_free_platform:
nvgpu_kfree(g, platform);
err_free_l:
kfree(l);
return err;
} }
static void nvgpu_pci_remove(struct pci_dev *pdev) static void nvgpu_pci_remove(struct pci_dev *pdev)