Skip to content

Commit ce1deca

Browse files
committed
Merge branch 'pci/pwrctl'
- Use of_platform_device_create() instead of of_platform_populate() to create pwrctl platform devices so we can control it based on the child nodes (Manivannan Sadhasivam) - Create pwrctrl platform devices only if there's a relevant power supply property (Manivannan Sadhasivam) - Add device link from the pwrctl supplier to the PCI dev to ensure pwrctl drivers are probed before the PCI dev driver; this avoids a race where pwrctl could change device power state while the PCI driver was active (Manivannan Sadhasivam) - Find pwrctl device for removal with of_find_device_by_node() instead of searching all children of the parent (Manivannan Sadhasivam) - Rename 'pwrctl' to 'pwrctrl' to use the same 'ctrl' suffix as 'bwctrl' and other PCI files to reduce confusion (Bjorn Helgaas) * pci/pwrctl: PCI/pwrctrl: Rename pwrctrl functions and structures PCI/pwrctrl: Rename pwrctl files to pwrctrl PCI/pwrctl: Remove pwrctl device without iterating over all children of pwrctl parent PCI/pwrctl: Ensure that pwrctl drivers are probed before PCI client drivers PCI/pwrctl: Create pwrctl device only if at least one power supply is present PCI/pwrctl: Use of_platform_device_create() to create pwrctl devices # Conflicts: # drivers/pci/bus.c # drivers/pci/remove.c
2 parents 95e9303 + 3f925cd commit ce1deca

File tree

14 files changed

+285
-212
lines changed

14 files changed

+285
-212
lines changed

MAINTAINERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17916,8 +17916,8 @@ M: Bartosz Golaszewski <brgl@bgdev.pl>
1791617916
L: linux-pci@vger.kernel.org
1791717917
S: Maintained
1791817918
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
17919-
F: drivers/pci/pwrctl/*
17920-
F: include/linux/pci-pwrctl.h
17919+
F: drivers/pci/pwrctrl/*
17920+
F: include/linux/pci-pwrctrl.h
1792117921

1792217922
PCI SUBSYSTEM
1792317923
M: Bjorn Helgaas <bhelgaas@google.com>

drivers/pci/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,6 @@ source "drivers/pci/hotplug/Kconfig"
305305
source "drivers/pci/controller/Kconfig"
306306
source "drivers/pci/endpoint/Kconfig"
307307
source "drivers/pci/switch/Kconfig"
308-
source "drivers/pci/pwrctl/Kconfig"
308+
source "drivers/pci/pwrctrl/Kconfig"
309309

310310
endif

drivers/pci/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \
99

1010
obj-$(CONFIG_PCI) += msi/
1111
obj-$(CONFIG_PCI) += pcie/
12-
obj-$(CONFIG_PCI) += pwrctl/
12+
obj-$(CONFIG_PCI) += pwrctrl/
1313

1414
ifdef CONFIG_PCI
1515
obj-$(CONFIG_PROC_FS) += proc.o

drivers/pci/bus.c

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/ioport.h>
1414
#include <linux/of.h>
1515
#include <linux/of_platform.h>
16+
#include <linux/platform_device.h>
1617
#include <linux/proc_fs.h>
1718
#include <linux/slab.h>
1819

@@ -330,6 +331,47 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
330331

331332
void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
332333

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+
333375
/**
334376
* pci_bus_add_device - start driver for a single device
335377
* @dev: device to add
@@ -339,6 +381,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
339381
void pci_bus_add_device(struct pci_dev *dev)
340382
{
341383
struct device_node *dn = dev->dev.of_node;
384+
struct platform_device *pdev;
342385
int retval;
343386

344387
/*
@@ -353,20 +396,28 @@ void pci_bus_add_device(struct pci_dev *dev)
353396
pci_proc_attach_device(dev);
354397
pci_bridge_d3_update(dev);
355398

399+
pci_pwrctrl_create_devices(dev);
400+
401+
/*
402+
* If the PCI device is associated with a pwrctrl device with a
403+
* power supply, create a device link between the PCI device and
404+
* pwrctrl device. This ensures that pwrctrl drivers are probed
405+
* before PCI client drivers.
406+
*/
407+
pdev = of_find_device_by_node(dn);
408+
if (pdev && of_pci_supply_present(dn)) {
409+
if (!device_link_add(&dev->dev, &pdev->dev,
410+
DL_FLAG_AUTOREMOVE_CONSUMER))
411+
pci_err(dev, "failed to add device link to power control device %s\n",
412+
pdev->name);
413+
}
414+
356415
dev->match_driver = !dn || of_device_is_available(dn);
357416
retval = device_attach(&dev->dev);
358417
if (retval < 0 && retval != -EPROBE_DEFER)
359418
pci_warn(dev, "device attach failed (%d)\n", retval);
360419

361420
pci_dev_assign_added(dev);
362-
363-
if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) {
364-
retval = of_platform_populate(dev_of_node(&dev->dev), NULL, NULL,
365-
&dev->dev);
366-
if (retval)
367-
pci_err(dev, "failed to populate child OF nodes (%d)\n",
368-
retval);
369-
}
370421
}
371422
EXPORT_SYMBOL_GPL(pci_bus_add_device);
372423

drivers/pci/of.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,33 @@ void of_pci_make_dev_node(struct pci_dev *pdev)
728728
}
729729
#endif
730730

731+
/**
732+
* of_pci_supply_present() - Check if the power supply is present for the PCI
733+
* device
734+
* @np: Device tree node
735+
*
736+
* Check if the power supply for the PCI device is present in the device tree
737+
* node or not.
738+
*
739+
* Return: true if at least one power supply exists; false otherwise.
740+
*/
741+
bool of_pci_supply_present(struct device_node *np)
742+
{
743+
struct property *prop;
744+
char *supply;
745+
746+
if (!np)
747+
return false;
748+
749+
for_each_property_of_node(np, prop) {
750+
supply = strrchr(prop->name, '-');
751+
if (supply && !strcmp(supply, "-supply"))
752+
return true;
753+
}
754+
755+
return false;
756+
}
757+
731758
#endif /* CONFIG_PCI */
732759

733760
/**

drivers/pci/pci.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,7 @@ void pci_set_bus_of_node(struct pci_bus *bus);
797797
void pci_release_bus_of_node(struct pci_bus *bus);
798798

799799
int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge);
800+
bool of_pci_supply_present(struct device_node *np);
800801

801802
#else
802803
static inline int
@@ -844,6 +845,10 @@ static inline int devm_of_pci_bridge_init(struct device *dev, struct pci_host_br
844845
return 0;
845846
}
846847

848+
static inline bool of_pci_supply_present(struct device_node *np)
849+
{
850+
return false;
851+
}
847852
#endif /* CONFIG_OF */
848853

849854
struct of_changeset;

drivers/pci/pwrctl/Makefile

Lines changed: 0 additions & 6 deletions
This file was deleted.

drivers/pci/pwrctl/core.c

Lines changed: 0 additions & 157 deletions
This file was deleted.
File renamed without changes.

drivers/pci/pwrctrl/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
3+
obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctrl-core.o
4+
pci-pwrctrl-core-y := core.o
5+
6+
obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctrl-pwrseq.o

0 commit comments

Comments
 (0)