Skip to content

Commit b365c0a

Browse files
committed
Merge branch 'pci/pwrctrl'
- Fix a double cleanup of regulators if devm_add_action_or_reset() fails (Geert Uytterhoeven) * pci/pwrctrl: PCI/pwrctrl: Fix device leak at device stop PCI/pwrctrl: Fix device and OF node leak at bus scan PCI/pwrctrl: Fix device leak at registration PCI/pwrctrl: Fix double cleanup on devm_add_action_or_reset() failure
2 parents 4c5cd8d + dc32e93 commit b365c0a

4 files changed

Lines changed: 30 additions & 17 deletions

File tree

drivers/pci/bus.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,15 @@ void pci_bus_add_device(struct pci_dev *dev)
361361
* before PCI client drivers.
362362
*/
363363
pdev = of_find_device_by_node(dn);
364-
if (pdev && of_pci_supply_present(dn)) {
365-
if (!device_link_add(&dev->dev, &pdev->dev,
366-
DL_FLAG_AUTOREMOVE_CONSUMER))
367-
pci_err(dev, "failed to add device link to power control device %s\n",
368-
pdev->name);
364+
if (pdev) {
365+
if (of_pci_supply_present(dn)) {
366+
if (!device_link_add(&dev->dev, &pdev->dev,
367+
DL_FLAG_AUTOREMOVE_CONSUMER)) {
368+
pci_err(dev, "failed to add device link to power control device %s\n",
369+
pdev->name);
370+
}
371+
}
372+
put_device(&pdev->dev);
369373
}
370374

371375
if (!dn || of_device_is_available(dn))

drivers/pci/probe.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,27 +2517,40 @@ static struct platform_device *pci_pwrctrl_create_device(struct pci_bus *bus, in
25172517
struct device_node *np;
25182518

25192519
np = of_pci_find_child_device(dev_of_node(&bus->dev), devfn);
2520-
if (!np || of_find_device_by_node(np))
2520+
if (!np)
25212521
return NULL;
25222522

2523+
pdev = of_find_device_by_node(np);
2524+
if (pdev) {
2525+
put_device(&pdev->dev);
2526+
goto err_put_of_node;
2527+
}
2528+
25232529
/*
25242530
* First check whether the pwrctrl device really needs to be created or
25252531
* not. This is decided based on at least one of the power supplies
25262532
* being defined in the devicetree node of the device.
25272533
*/
25282534
if (!of_pci_supply_present(np)) {
25292535
pr_debug("PCI/pwrctrl: Skipping OF node: %s\n", np->name);
2530-
return NULL;
2536+
goto err_put_of_node;
25312537
}
25322538

25332539
/* Now create the pwrctrl device */
25342540
pdev = of_platform_device_create(np, NULL, &host->dev);
25352541
if (!pdev) {
25362542
pr_err("PCI/pwrctrl: Failed to create pwrctrl device for node: %s\n", np->name);
2537-
return NULL;
2543+
goto err_put_of_node;
25382544
}
25392545

2546+
of_node_put(np);
2547+
25402548
return pdev;
2549+
2550+
err_put_of_node:
2551+
of_node_put(np);
2552+
2553+
return NULL;
25412554
}
25422555
#else
25432556
static struct platform_device *pci_pwrctrl_create_device(struct pci_bus *bus, int devfn)

drivers/pci/pwrctrl/slot.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,14 @@ static int pci_pwrctrl_slot_probe(struct platform_device *pdev)
4949
ret = regulator_bulk_enable(slot->num_supplies, slot->supplies);
5050
if (ret < 0) {
5151
dev_err_probe(dev, ret, "Failed to enable slot regulators\n");
52-
goto err_regulator_free;
52+
regulator_bulk_free(slot->num_supplies, slot->supplies);
53+
return ret;
5354
}
5455

5556
ret = devm_add_action_or_reset(dev, devm_pci_pwrctrl_slot_power_off,
5657
slot);
5758
if (ret)
58-
goto err_regulator_disable;
59+
return ret;
5960

6061
clk = devm_clk_get_optional_enabled(dev, NULL);
6162
if (IS_ERR(clk)) {
@@ -70,13 +71,6 @@ static int pci_pwrctrl_slot_probe(struct platform_device *pdev)
7071
return dev_err_probe(dev, ret, "Failed to register pwrctrl driver\n");
7172

7273
return 0;
73-
74-
err_regulator_disable:
75-
regulator_bulk_disable(slot->num_supplies, slot->supplies);
76-
err_regulator_free:
77-
regulator_bulk_free(slot->num_supplies, slot->supplies);
78-
79-
return ret;
8074
}
8175

8276
static const struct of_device_id pci_pwrctrl_slot_of_match[] = {

drivers/pci/remove.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static void pci_pwrctrl_unregister(struct device *dev)
3131
return;
3232

3333
of_device_unregister(pdev);
34+
put_device(&pdev->dev);
35+
3436
of_node_clear_flag(np, OF_POPULATED);
3537
}
3638

0 commit comments

Comments
 (0)