Skip to content

Commit 957f40d

Browse files
Mani-Sadhasivamkwilczynski
authored andcommitted
PCI/pwrctrl: Move creation of pwrctrl devices to pci_scan_device()
Current way of creating pwrctrl devices requires iterating through the child devicetree nodes of the PCI bridge in pci_pwrctrl_create_devices(). Even though it works, it creates confusion as there is no symmetry between this and pci_pwrctrl_unregister() function that removes the pwrctrl devices. So to make these two functions symmetric, move the creation of pwrctrl devices to pci_scan_device(). During the scan of each device in a slot, the devicetree node (if exists) for the PCI device will be checked. If it has the supplies populated, then the pwrctrl device will be created. Since the PCI device scan happens so early, there would be no "struct pci_dev" available for the device. So the host bridge is used as the parent of all pwrctrl devices. One nice side effect of this move is that, it is now possible to have pwrctrl devices for PCI bridges as well (to control the supplies of PCI slots). Suggested-by: Lukas Wunner <[email protected]> Tested-by: Bartosz Golaszewski <[email protected]> Signed-off-by: Manivannan Sadhasivam <[email protected]> Link: https://lore.kernel.org/r/[email protected] [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński <[email protected]>
1 parent 2014c95 commit 957f40d

File tree

3 files changed

+35
-44
lines changed

3 files changed

+35
-44
lines changed

drivers/pci/bus.c

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -331,47 +331,6 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
331331

332332
void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
333333

334-
/*
335-
* Create pwrctrl devices (if required) for the PCI devices to handle the power
336-
* state.
337-
*/
338-
static void pci_pwrctrl_create_devices(struct pci_dev *dev)
339-
{
340-
struct device_node *np = dev_of_node(&dev->dev);
341-
struct device *parent = &dev->dev;
342-
struct platform_device *pdev;
343-
344-
/*
345-
* First ensure that we are starting from a PCI bridge and it has a
346-
* corresponding devicetree node.
347-
*/
348-
if (np && pci_is_bridge(dev)) {
349-
/*
350-
* Now look for the child PCI device nodes and create pwrctrl
351-
* devices for them. The pwrctrl device drivers will manage the
352-
* power state of the devices.
353-
*/
354-
for_each_available_child_of_node_scoped(np, child) {
355-
/*
356-
* First check whether the pwrctrl device really
357-
* needs to be created or not. This is decided
358-
* based on at least one of the power supplies
359-
* being defined in the devicetree node of the
360-
* device.
361-
*/
362-
if (!of_pci_supply_present(child)) {
363-
pci_dbg(dev, "skipping OF node: %s\n", child->name);
364-
return;
365-
}
366-
367-
/* Now create the pwrctrl device */
368-
pdev = of_platform_device_create(child, NULL, parent);
369-
if (!pdev)
370-
pci_err(dev, "failed to create OF node: %s\n", child->name);
371-
}
372-
}
373-
}
374-
375334
/**
376335
* pci_bus_add_device - start driver for a single device
377336
* @dev: device to add
@@ -396,8 +355,6 @@ void pci_bus_add_device(struct pci_dev *dev)
396355
pci_proc_attach_device(dev);
397356
pci_bridge_d3_update(dev);
398357

399-
pci_pwrctrl_create_devices(dev);
400-
401358
/*
402359
* If the PCI device is associated with a pwrctrl device with a
403360
* power supply, create a device link between the PCI device and

drivers/pci/probe.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <linux/pci.h>
1010
#include <linux/msi.h>
1111
#include <linux/of_pci.h>
12+
#include <linux/of_platform.h>
13+
#include <linux/platform_device.h>
1214
#include <linux/pci_hotplug.h>
1315
#include <linux/slab.h>
1416
#include <linux/module.h>
@@ -2493,6 +2495,36 @@ bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
24932495
}
24942496
EXPORT_SYMBOL(pci_bus_read_dev_vendor_id);
24952497

2498+
/*
2499+
* Create pwrctrl device (if required) for the PCI device to handle the power
2500+
* state.
2501+
*/
2502+
static void pci_pwrctrl_create_device(struct pci_bus *bus, int devfn)
2503+
{
2504+
struct pci_host_bridge *host = pci_find_host_bridge(bus);
2505+
struct platform_device *pdev;
2506+
struct device_node *np;
2507+
2508+
np = of_pci_find_child_device(dev_of_node(&bus->dev), devfn);
2509+
if (!np || of_find_device_by_node(np))
2510+
return;
2511+
2512+
/*
2513+
* First check whether the pwrctrl device really needs to be created or
2514+
* not. This is decided based on at least one of the power supplies
2515+
* being defined in the devicetree node of the device.
2516+
*/
2517+
if (!of_pci_supply_present(np)) {
2518+
pr_debug("PCI/pwrctrl: Skipping OF node: %s\n", np->name);
2519+
return;
2520+
}
2521+
2522+
/* Now create the pwrctrl device */
2523+
pdev = of_platform_device_create(np, NULL, &host->dev);
2524+
if (!pdev)
2525+
pr_err("PCI/pwrctrl: Failed to create pwrctrl device for OF node: %s\n", np->name);
2526+
}
2527+
24962528
/*
24972529
* Read the config data for a PCI device, sanity-check it,
24982530
* and fill in the dev structure.
@@ -2502,6 +2534,8 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
25022534
struct pci_dev *dev;
25032535
u32 l;
25042536

2537+
pci_pwrctrl_create_device(bus, devfn);
2538+
25052539
if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
25062540
return NULL;
25072541

drivers/pci/pwrctrl/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static void rescan_work_func(struct work_struct *work)
4444
struct pci_pwrctrl, work);
4545

4646
pci_lock_rescan_remove();
47-
pci_rescan_bus(to_pci_dev(pwrctrl->dev->parent)->bus);
47+
pci_rescan_bus(to_pci_host_bridge(pwrctrl->dev->parent)->bus);
4848
pci_unlock_rescan_remove();
4949
}
5050

0 commit comments

Comments
 (0)