From 7582fe07f4ca4c560eb47800b640997f06a8baa2 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 25 Oct 2024 13:24:51 +0530 Subject: [PATCH 1/6] PCI/pwrctl: Use of_platform_device_create() to create pwrctl devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The of_platform_populate() API creates platform devices by descending through the children of the parent node. But it provides no control over the child nodes, which makes it difficult to add checks for the child nodes in the future. Use of_platform_device_create() and for_each_child_of_node_scoped() to make it possible to add checks for each node before creating the platform device. Link: https://lore.kernel.org/r/20241025-pci-pwrctl-rework-v2-1-568756156cbe@linaro.org Tested-by: Bartosz Golaszewski Tested-by: Krishna chaitanya chundru Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Reviewed-by: Bartosz Golaszewski --- drivers/pci/bus.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 55c853686051..9d278d3a19ff 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -329,6 +330,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { } void pci_bus_add_device(struct pci_dev *dev) { struct device_node *dn = dev->dev.of_node; + struct platform_device *pdev; int retval; /* @@ -351,11 +353,11 @@ void pci_bus_add_device(struct pci_dev *dev) pci_dev_assign_added(dev, true); if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) { - retval = of_platform_populate(dev_of_node(&dev->dev), NULL, NULL, - &dev->dev); - if (retval) - pci_err(dev, "failed to populate child OF nodes (%d)\n", - retval); + for_each_available_child_of_node_scoped(dn, child) { + pdev = of_platform_device_create(child, NULL, &dev->dev); + if (!pdev) + pci_err(dev, "failed to create OF node: %s\n", child->name); + } } } EXPORT_SYMBOL_GPL(pci_bus_add_device); From 278dd091e95d428eea0a2c3c517d895b052de5ff Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 25 Oct 2024 13:24:52 +0530 Subject: [PATCH 2/6] PCI/pwrctl: Create pwrctl device only if at least one power supply is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, pwrctl devices are created if the corresponding PCI nodes are defined in devicetree. But this is not correct, because not all PCI nodes require pwrctl support. Pwrctl comes into the picture only when the device requires kernel to manage its power state. This can be determined using the power supply properties present in the devicetree node of the device. Add of_pci_supply_present() to check whether the devicetree contains at least one power supply property for a device. If one is present, create a pwrctl device for that PCI node. Suggested-by: Dmitry Baryshkov Fixes: 8fb18619d910 ("PCI/pwrctl: Create platform devices for child OF nodes of the port node") Link: https://lore.kernel.org/r/20241025-pci-pwrctl-rework-v2-2-568756156cbe@linaro.org Tested-by: Bartosz Golaszewski Tested-by: Krishna chaitanya chundru Signed-off-by: Manivannan Sadhasivam [bhelgaas: rename of_pci_is_supply_present() to of_pci_supply_present() for readability] Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Reviewed-by: Bartosz Golaszewski Cc: stable+noautosel@kernel.org # Depends on of_platform_device_create() rework --- drivers/pci/bus.c | 11 +++++++++++ drivers/pci/of.c | 27 +++++++++++++++++++++++++++ drivers/pci/pci.h | 5 +++++ 3 files changed, 43 insertions(+) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 9d278d3a19ff..93bc42170122 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -354,6 +354,17 @@ void pci_bus_add_device(struct pci_dev *dev) if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) { for_each_available_child_of_node_scoped(dn, child) { + /* + * First check whether the pwrctl device needs to be + * created or not. This is decided based on at least + * one of the power supplies being defined in the + * devicetree node of the device. + */ + if (!of_pci_supply_present(child)) { + pci_dbg(dev, "skipping OF node: %s\n", child->name); + continue; + } + pdev = of_platform_device_create(child, NULL, &dev->dev); if (!pdev) pci_err(dev, "failed to create OF node: %s\n", child->name); diff --git a/drivers/pci/of.c b/drivers/pci/of.c index dacea3fc5128..52f770bcc481 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -728,6 +728,33 @@ out_free_name: } #endif +/** + * of_pci_supply_present() - Check if the power supply is present for the PCI + * device + * @np: Device tree node + * + * Check if the power supply for the PCI device is present in the device tree + * node or not. + * + * Return: true if at least one power supply exists; false otherwise. + */ +bool of_pci_supply_present(struct device_node *np) +{ + struct property *prop; + char *supply; + + if (!np) + return false; + + for_each_property_of_node(np, prop) { + supply = strrchr(prop->name, '-'); + if (supply && !strcmp(supply, "-supply")) + return true; + } + + return false; +} + #endif /* CONFIG_PCI */ /** diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 14d00ce45bfa..64c6ca6de802 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -746,6 +746,7 @@ void pci_set_bus_of_node(struct pci_bus *bus); void pci_release_bus_of_node(struct pci_bus *bus); int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge); +bool of_pci_supply_present(struct device_node *np); #else static inline int @@ -793,6 +794,10 @@ static inline int devm_of_pci_bridge_init(struct device *dev, struct pci_host_br return 0; } +static inline bool of_pci_supply_present(struct device_node *np) +{ + return false; +} #endif /* CONFIG_OF */ struct of_changeset; From b458ff7e8176523b9d5a8d33f2487f29d7096eb1 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 25 Oct 2024 13:24:53 +0530 Subject: [PATCH 3/6] PCI/pwrctl: Ensure that pwrctl drivers are probed before PCI client drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the kernel device driver model, a pwrctl device is the supplier for the PCI device, but the device link that enforces the supplier-consumer relationship was previously created by the pwrctl driver. Therefore, the driver model didn't prevent probing PCI client drivers before probing the corresponding pwrctl drivers. This may lead to a race condition if the PCI device was already powered on by the bootloader (before the pwrctl driver). If the bootloader did not power on the PCI device, this wouldn't create any problem as the pwrctl driver will be the one powering on the device, so the PCI client driver always gets probed afterward. But if the device was already powered on, then the device will be seen by the PCI core and the PCI client driver may get probed before its pwrctl driver. This creates a race condition as the pwrctl driver may change the device power state while the device is being accessed by the client driver. One such issue was already reported on the Qcom X13s platform with the WLAN device and fixed with a hack in the WCN pwrseq driver by a9aaf1ff88a8 ("power: sequencing: request the WLAN enable GPIO as-is"). A cleaner way to fix the above mentioned race condition is to ensure that the pwrctl drivers are always probed before the client drivers. If the PCI device is associated with a pwrctl platform device with a power supply, add a device link between the PCI device and the pwrctl device before device_attach() in pci_bus_add_device(). Note that there is no need to explicitly remove the device link as that will be taken care of by the driver core when the PCI device gets removed. Fixes: 4565d2652a37 ("PCI/pwrctl: Add PCI power control core code") Fixes: 8fb18619d910 ("PCI/pwrctl: Create platform devices for child OF nodes of the port node") Link: https://lore.kernel.org/r/20241025-pci-pwrctl-rework-v2-3-568756156cbe@linaro.org Tested-by: Bartosz Golaszewski Tested-by: Krishna chaitanya chundru Signed-off-by: Manivannan Sadhasivam [bhelgaas: squash fix from https://lore.kernel.org/r/20241120062459.6371-1-manivannan.sadhasivam@linaro.org for SPARCv9 issue reported by Jonathan Currier ] Signed-off-by: Bjorn Helgaas [kwilczynski: wrap code to 80 columns] Signed-off-by: Krzysztof Wilczyński Reviewed-by: Bartosz Golaszewski Cc: stable+noautosel@kernel.org # Depends on power supply check --- drivers/pci/bus.c | 75 +++++++++++++++++++++++++++++---------- drivers/pci/pwrctl/core.c | 10 ------ 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 93bc42170122..90d775601789 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -321,6 +321,46 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } void __weak pcibios_bus_add_device(struct pci_dev *pdev) { } +/* + * Create pwrctl devices (if required) for the PCI devices to handle the power + * state. + */ +static void pci_pwrctl_create_devices(struct pci_dev *dev) +{ + struct device_node *np = dev_of_node(&dev->dev); + struct device *parent = &dev->dev; + struct platform_device *pdev; + + /* + * First ensure that we are starting from a PCI bridge and it has a + * corresponding devicetree node. + */ + if (np && pci_is_bridge(dev)) { + /* + * Now look for the child PCI device nodes and create pwrctl + * devices for them. The pwrctl device drivers will manage the + * power state of the devices. + */ + for_each_available_child_of_node_scoped(np, child) { + /* + * First check whether the pwrctl device really needs to + * be created or not. This is decided based on at least + * one of the power supplies being defined in the + * devicetree node of the device. + */ + if (!of_pci_supply_present(child)) { + pci_dbg(dev, "skipping OF node: %s\n", child->name); + return; + } + + /* Now create the pwrctl device */ + pdev = of_platform_device_create(child, NULL, parent); + if (!pdev) + pci_err(dev, "failed to create OF node: %s\n", child->name); + } + } +} + /** * pci_bus_add_device - start driver for a single device * @dev: device to add @@ -345,31 +385,28 @@ void pci_bus_add_device(struct pci_dev *dev) pci_proc_attach_device(dev); pci_bridge_d3_update(dev); + pci_pwrctl_create_devices(dev); + + /* + * If the PCI device is associated with a pwrctl device with a + * power supply, create a device link between the PCI device and + * pwrctl device. This ensures that pwrctl drivers are probed + * before PCI client drivers. + */ + pdev = of_find_device_by_node(dn); + if (pdev && of_pci_supply_present(dn)) { + if (!device_link_add(&dev->dev, &pdev->dev, + DL_FLAG_AUTOREMOVE_CONSUMER)) + pci_err(dev, "failed to add device link to power control device %s\n", + pdev->name); + } + dev->match_driver = !dn || of_device_is_available(dn); retval = device_attach(&dev->dev); if (retval < 0 && retval != -EPROBE_DEFER) pci_warn(dev, "device attach failed (%d)\n", retval); pci_dev_assign_added(dev, true); - - if (dev_of_node(&dev->dev) && pci_is_bridge(dev)) { - for_each_available_child_of_node_scoped(dn, child) { - /* - * First check whether the pwrctl device needs to be - * created or not. This is decided based on at least - * one of the power supplies being defined in the - * devicetree node of the device. - */ - if (!of_pci_supply_present(child)) { - pci_dbg(dev, "skipping OF node: %s\n", child->name); - continue; - } - - pdev = of_platform_device_create(child, NULL, &dev->dev); - if (!pdev) - pci_err(dev, "failed to create OF node: %s\n", child->name); - } - } } EXPORT_SYMBOL_GPL(pci_bus_add_device); diff --git a/drivers/pci/pwrctl/core.c b/drivers/pci/pwrctl/core.c index 01d913b60316..bb5a23712434 100644 --- a/drivers/pci/pwrctl/core.c +++ b/drivers/pci/pwrctl/core.c @@ -33,16 +33,6 @@ static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action, */ dev->of_node_reused = true; break; - case BUS_NOTIFY_BOUND_DRIVER: - pwrctl->link = device_link_add(dev, pwrctl->dev, - DL_FLAG_AUTOREMOVE_CONSUMER); - if (!pwrctl->link) - dev_err(pwrctl->dev, "Failed to add device link\n"); - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - if (pwrctl->link) - device_link_remove(dev, pwrctl->dev); - break; } return NOTIFY_DONE; From 681725afb6b91dfa581f4eba5f256ac5e953b463 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Fri, 25 Oct 2024 13:24:55 +0530 Subject: [PATCH 4/6] PCI/pwrctl: Remove pwrctl device without iterating over all children of pwrctl parent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to iterate over all children of the pwrctl device parent to remove the pwrctl device. Since the pwrctl device associated with the PCI device can be found using of_find_device_by_node() API, use it directly instead. Any pwrctl devices lying around without getting associated with the PCI devices will be removed once their parent device gets removed. Link: https://lore.kernel.org/r/20241025-pci-pwrctl-rework-v2-5-568756156cbe@linaro.org Tested-by: Bartosz Golaszewski Tested-by: Krishna chaitanya chundru Signed-off-by: Manivannan Sadhasivam [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Reviewed-by: Bartosz Golaszewski --- drivers/pci/remove.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index e4ce1145aa3e..3dd9b3024956 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -17,16 +17,16 @@ static void pci_free_resources(struct pci_dev *dev) } } -static int pci_pwrctl_unregister(struct device *dev, void *data) +static void pci_pwrctl_unregister(struct device *dev) { - struct device_node *pci_node = data, *plat_node = dev_of_node(dev); + struct platform_device *pdev; - if (dev_is_platform(dev) && plat_node && plat_node == pci_node) { - of_device_unregister(to_platform_device(dev)); - of_node_clear_flag(plat_node, OF_POPULATED); - } + pdev = of_find_device_by_node(dev_of_node(dev)); + if (!pdev) + return; - return 0; + of_device_unregister(pdev); + of_node_clear_flag(dev_of_node(dev), OF_POPULATED); } static void pci_stop_dev(struct pci_dev *dev) @@ -34,8 +34,7 @@ static void pci_stop_dev(struct pci_dev *dev) pci_pme_active(dev, false); if (pci_dev_is_added(dev)) { - device_for_each_child(dev->dev.parent, dev_of_node(&dev->dev), - pci_pwrctl_unregister); + pci_pwrctl_unregister(&dev->dev); device_release_driver(&dev->dev); pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); From b88cbaaa6fa109c2eb455d8fe2a318de0d197ea2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 15 Nov 2024 15:44:27 -0600 Subject: [PATCH 5/6] PCI/pwrctrl: Rename pwrctl files to pwrctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To slightly reduce confusion between "pwrctl" (the power controller and power sequencing framework) and "bwctrl" (the bandwidth controller), rename "pwrctl" to "pwrctrl" so they use the same "ctrl" suffix. Rename drivers/pci/pwrctl/ to drivers/pci/pwrctrl/, including the related MAINTAINERS, include file (include/linux/pci-pwrctl.h), Makefile, and Kconfig changes. This is the minimal rename of files only. A subsequent commit will rename functions and data structures. Link: https://lore.kernel.org/r/20241115214428.2061153-2-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Acked-by: Krzysztof Wilczyński --- MAINTAINERS | 4 ++-- drivers/pci/Kconfig | 2 +- drivers/pci/Makefile | 2 +- drivers/pci/pwrctl/Makefile | 6 ------ drivers/pci/{pwrctl => pwrctrl}/Kconfig | 0 drivers/pci/pwrctrl/Makefile | 6 ++++++ drivers/pci/{pwrctl => pwrctrl}/core.c | 2 +- .../pci-pwrctl-pwrseq.c => pwrctrl/pci-pwrctrl-pwrseq.c} | 2 +- include/linux/{pci-pwrctl.h => pci-pwrctrl.h} | 0 9 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 drivers/pci/pwrctl/Makefile rename drivers/pci/{pwrctl => pwrctrl}/Kconfig (100%) create mode 100644 drivers/pci/pwrctrl/Makefile rename drivers/pci/{pwrctl => pwrctrl}/core.c (99%) rename drivers/pci/{pwrctl/pci-pwrctl-pwrseq.c => pwrctrl/pci-pwrctrl-pwrseq.c} (98%) rename include/linux/{pci-pwrctl.h => pci-pwrctrl.h} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f..1a6096135424 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17910,8 +17910,8 @@ M: Bartosz Golaszewski L: linux-pci@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git -F: drivers/pci/pwrctl/* -F: include/linux/pci-pwrctl.h +F: drivers/pci/pwrctrl/* +F: include/linux/pci-pwrctrl.h PCI SUBSYSTEM M: Bjorn Helgaas diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 0d94e4a967d8..e1c025698a28 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -305,6 +305,6 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pci/controller/Kconfig" source "drivers/pci/endpoint/Kconfig" source "drivers/pci/switch/Kconfig" -source "drivers/pci/pwrctl/Kconfig" +source "drivers/pci/pwrctrl/Kconfig" endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 374c5c06d92f..39a07890abd1 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \ obj-$(CONFIG_PCI) += msi/ obj-$(CONFIG_PCI) += pcie/ -obj-$(CONFIG_PCI) += pwrctl/ +obj-$(CONFIG_PCI) += pwrctrl/ ifdef CONFIG_PCI obj-$(CONFIG_PROC_FS) += proc.o diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile deleted file mode 100644 index d308aae4800c..000000000000 --- a/drivers/pci/pwrctl/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o -pci-pwrctl-core-y := core.o - -obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctrl/Kconfig similarity index 100% rename from drivers/pci/pwrctl/Kconfig rename to drivers/pci/pwrctrl/Kconfig diff --git a/drivers/pci/pwrctrl/Makefile b/drivers/pci/pwrctrl/Makefile new file mode 100644 index 000000000000..75c7ce531c7e --- /dev/null +++ b/drivers/pci/pwrctrl/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctrl-core.o +pci-pwrctrl-core-y := core.o + +obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctrl-pwrseq.o diff --git a/drivers/pci/pwrctl/core.c b/drivers/pci/pwrctrl/core.c similarity index 99% rename from drivers/pci/pwrctl/core.c rename to drivers/pci/pwrctrl/core.c index bb5a23712434..88f06e9271ba 100644 --- a/drivers/pci/pwrctl/core.c +++ b/drivers/pci/pwrctrl/core.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c similarity index 98% rename from drivers/pci/pwrctl/pci-pwrctl-pwrseq.c rename to drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c index a23a4312574b..cc19ad61dd6e 100644 --- a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c +++ b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/pci-pwrctl.h b/include/linux/pci-pwrctrl.h similarity index 100% rename from include/linux/pci-pwrctl.h rename to include/linux/pci-pwrctrl.h From 3f925cd6287401bbc9d568f56d796a69c8bd292a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 15 Nov 2024 15:44:28 -0600 Subject: [PATCH 6/6] PCI/pwrctrl: Rename pwrctrl functions and structures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename pwrctrl functions and structures from "pwrctl" to "pwrctrl" to match the similar file renames. Link: https://lore.kernel.org/r/20241115214428.2061153-3-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Acked-by: Krzysztof Wilczyński --- drivers/pci/bus.c | 25 ++++---- drivers/pci/pwrctrl/core.c | 77 ++++++++++++------------ drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c | 32 +++++----- drivers/pci/remove.c | 4 +- include/linux/pci-pwrctrl.h | 22 +++---- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 90d775601789..0d27809746df 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -322,10 +322,10 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } void __weak pcibios_bus_add_device(struct pci_dev *pdev) { } /* - * Create pwrctl devices (if required) for the PCI devices to handle the power + * Create pwrctrl devices (if required) for the PCI devices to handle the power * state. */ -static void pci_pwrctl_create_devices(struct pci_dev *dev) +static void pci_pwrctrl_create_devices(struct pci_dev *dev) { struct device_node *np = dev_of_node(&dev->dev); struct device *parent = &dev->dev; @@ -337,23 +337,24 @@ static void pci_pwrctl_create_devices(struct pci_dev *dev) */ if (np && pci_is_bridge(dev)) { /* - * Now look for the child PCI device nodes and create pwrctl - * devices for them. The pwrctl device drivers will manage the + * Now look for the child PCI device nodes and create pwrctrl + * devices for them. The pwrctrl device drivers will manage the * power state of the devices. */ for_each_available_child_of_node_scoped(np, child) { /* - * First check whether the pwrctl device really needs to - * be created or not. This is decided based on at least - * one of the power supplies being defined in the - * devicetree node of the device. + * First check whether the pwrctrl device really + * needs to be created or not. This is decided + * based on at least one of the power supplies + * being defined in the devicetree node of the + * device. */ if (!of_pci_supply_present(child)) { pci_dbg(dev, "skipping OF node: %s\n", child->name); return; } - /* Now create the pwrctl device */ + /* Now create the pwrctrl device */ pdev = of_platform_device_create(child, NULL, parent); if (!pdev) pci_err(dev, "failed to create OF node: %s\n", child->name); @@ -385,12 +386,12 @@ void pci_bus_add_device(struct pci_dev *dev) pci_proc_attach_device(dev); pci_bridge_d3_update(dev); - pci_pwrctl_create_devices(dev); + pci_pwrctrl_create_devices(dev); /* - * If the PCI device is associated with a pwrctl device with a + * If the PCI device is associated with a pwrctrl device with a * power supply, create a device link between the PCI device and - * pwrctl device. This ensures that pwrctl drivers are probed + * pwrctrl device. This ensures that pwrctrl drivers are probed * before PCI client drivers. */ pdev = of_find_device_by_node(dn); diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c index 88f06e9271ba..2fb174db91e5 100644 --- a/drivers/pci/pwrctrl/core.c +++ b/drivers/pci/pwrctrl/core.c @@ -11,13 +11,13 @@ #include #include -static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action, - void *data) +static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action, + void *data) { - struct pci_pwrctl *pwrctl = container_of(nb, struct pci_pwrctl, nb); + struct pci_pwrctrl *pwrctrl = container_of(nb, struct pci_pwrctrl, nb); struct device *dev = data; - if (dev_fwnode(dev) != dev_fwnode(pwrctl->dev)) + if (dev_fwnode(dev) != dev_fwnode(pwrctrl->dev)) return NOTIFY_DONE; switch (action) { @@ -40,31 +40,32 @@ static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action, static void rescan_work_func(struct work_struct *work) { - struct pci_pwrctl *pwrctl = container_of(work, struct pci_pwrctl, work); + struct pci_pwrctrl *pwrctrl = container_of(work, + struct pci_pwrctrl, work); pci_lock_rescan_remove(); - pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus); + pci_rescan_bus(to_pci_dev(pwrctrl->dev->parent)->bus); pci_unlock_rescan_remove(); } /** - * pci_pwrctl_init() - Initialize the PCI power control context struct + * pci_pwrctrl_init() - Initialize the PCI power control context struct * - * @pwrctl: PCI power control data + * @pwrctrl: PCI power control data * @dev: Parent device */ -void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev) +void pci_pwrctrl_init(struct pci_pwrctrl *pwrctrl, struct device *dev) { - pwrctl->dev = dev; - INIT_WORK(&pwrctl->work, rescan_work_func); + pwrctrl->dev = dev; + INIT_WORK(&pwrctrl->work, rescan_work_func); } -EXPORT_SYMBOL_GPL(pci_pwrctl_init); +EXPORT_SYMBOL_GPL(pci_pwrctrl_init); /** - * pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI + * pci_pwrctrl_device_set_ready() - Notify the pwrctrl subsystem that the PCI * device is powered-up and ready to be detected. * - * @pwrctl: PCI power control data. + * @pwrctrl: PCI power control data. * * Returns: * 0 on success, negative error number on error. @@ -74,31 +75,31 @@ EXPORT_SYMBOL_GPL(pci_pwrctl_init); * that the bus rescan was successfully started. The device will get bound to * its PCI driver asynchronously. */ -int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl) +int pci_pwrctrl_device_set_ready(struct pci_pwrctrl *pwrctrl) { int ret; - if (!pwrctl->dev) + if (!pwrctrl->dev) return -ENODEV; - pwrctl->nb.notifier_call = pci_pwrctl_notify; - ret = bus_register_notifier(&pci_bus_type, &pwrctl->nb); + pwrctrl->nb.notifier_call = pci_pwrctrl_notify; + ret = bus_register_notifier(&pci_bus_type, &pwrctrl->nb); if (ret) return ret; - schedule_work(&pwrctl->work); + schedule_work(&pwrctrl->work); return 0; } -EXPORT_SYMBOL_GPL(pci_pwrctl_device_set_ready); +EXPORT_SYMBOL_GPL(pci_pwrctrl_device_set_ready); /** - * pci_pwrctl_device_unset_ready() - Notify the pwrctl subsystem that the PCI + * pci_pwrctrl_device_unset_ready() - Notify the pwrctrl subsystem that the PCI * device is about to be powered-down. * - * @pwrctl: PCI power control data. + * @pwrctrl: PCI power control data. */ -void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl) +void pci_pwrctrl_device_unset_ready(struct pci_pwrctrl *pwrctrl) { /* * We don't have to delete the link here. Typically, this function @@ -106,41 +107,41 @@ void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl) * it is being detached then the child PCI device must have already * been unbound too or the device core wouldn't let us unbind. */ - bus_unregister_notifier(&pci_bus_type, &pwrctl->nb); + bus_unregister_notifier(&pci_bus_type, &pwrctrl->nb); } -EXPORT_SYMBOL_GPL(pci_pwrctl_device_unset_ready); +EXPORT_SYMBOL_GPL(pci_pwrctrl_device_unset_ready); -static void devm_pci_pwrctl_device_unset_ready(void *data) +static void devm_pci_pwrctrl_device_unset_ready(void *data) { - struct pci_pwrctl *pwrctl = data; + struct pci_pwrctrl *pwrctrl = data; - pci_pwrctl_device_unset_ready(pwrctl); + pci_pwrctrl_device_unset_ready(pwrctrl); } /** - * devm_pci_pwrctl_device_set_ready - Managed variant of - * pci_pwrctl_device_set_ready(). + * devm_pci_pwrctrl_device_set_ready - Managed variant of + * pci_pwrctrl_device_set_ready(). * - * @dev: Device managing this pwrctl provider. - * @pwrctl: PCI power control data. + * @dev: Device managing this pwrctrl provider. + * @pwrctrl: PCI power control data. * * Returns: * 0 on success, negative error number on error. */ -int devm_pci_pwrctl_device_set_ready(struct device *dev, - struct pci_pwrctl *pwrctl) +int devm_pci_pwrctrl_device_set_ready(struct device *dev, + struct pci_pwrctrl *pwrctrl) { int ret; - ret = pci_pwrctl_device_set_ready(pwrctl); + ret = pci_pwrctrl_device_set_ready(pwrctrl); if (ret) return ret; return devm_add_action_or_reset(dev, - devm_pci_pwrctl_device_unset_ready, - pwrctl); + devm_pci_pwrctrl_device_unset_ready, + pwrctrl); } -EXPORT_SYMBOL_GPL(devm_pci_pwrctl_device_set_ready); +EXPORT_SYMBOL_GPL(devm_pci_pwrctrl_device_set_ready); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_DESCRIPTION("PCI Device Power Control core driver"); diff --git a/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c index cc19ad61dd6e..e9f89866b7c2 100644 --- a/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c +++ b/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c @@ -13,21 +13,21 @@ #include #include -struct pci_pwrctl_pwrseq_data { - struct pci_pwrctl ctx; +struct pci_pwrctrl_pwrseq_data { + struct pci_pwrctrl ctx; struct pwrseq_desc *pwrseq; }; -static void devm_pci_pwrctl_pwrseq_power_off(void *data) +static void devm_pci_pwrctrl_pwrseq_power_off(void *data) { struct pwrseq_desc *pwrseq = data; pwrseq_power_off(pwrseq); } -static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev) +static int pci_pwrctrl_pwrseq_probe(struct platform_device *pdev) { - struct pci_pwrctl_pwrseq_data *data; + struct pci_pwrctrl_pwrseq_data *data; struct device *dev = &pdev->dev; int ret; @@ -45,22 +45,22 @@ static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to power-on the device\n"); - ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off, + ret = devm_add_action_or_reset(dev, devm_pci_pwrctrl_pwrseq_power_off, data->pwrseq); if (ret) return ret; - pci_pwrctl_init(&data->ctx, dev); + pci_pwrctrl_init(&data->ctx, dev); - ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx); + ret = devm_pci_pwrctrl_device_set_ready(dev, &data->ctx); if (ret) return dev_err_probe(dev, ret, - "Failed to register the pwrctl wrapper\n"); + "Failed to register the pwrctrl wrapper\n"); return 0; } -static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = { +static const struct of_device_id pci_pwrctrl_pwrseq_of_match[] = { { /* ATH11K in QCA6390 package. */ .compatible = "pci17cb,1101", @@ -78,16 +78,16 @@ static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = { }, { } }; -MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match); +MODULE_DEVICE_TABLE(of, pci_pwrctrl_pwrseq_of_match); -static struct platform_driver pci_pwrctl_pwrseq_driver = { +static struct platform_driver pci_pwrctrl_pwrseq_driver = { .driver = { - .name = "pci-pwrctl-pwrseq", - .of_match_table = pci_pwrctl_pwrseq_of_match, + .name = "pci-pwrctrl-pwrseq", + .of_match_table = pci_pwrctrl_pwrseq_of_match, }, - .probe = pci_pwrctl_pwrseq_probe, + .probe = pci_pwrctrl_pwrseq_probe, }; -module_platform_driver(pci_pwrctl_pwrseq_driver); +module_platform_driver(pci_pwrctrl_pwrseq_driver); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices"); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 3dd9b3024956..27ef371a8443 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -17,7 +17,7 @@ static void pci_free_resources(struct pci_dev *dev) } } -static void pci_pwrctl_unregister(struct device *dev) +static void pci_pwrctrl_unregister(struct device *dev) { struct platform_device *pdev; @@ -34,7 +34,7 @@ static void pci_stop_dev(struct pci_dev *dev) pci_pme_active(dev, false); if (pci_dev_is_added(dev)) { - pci_pwrctl_unregister(&dev->dev); + pci_pwrctrl_unregister(&dev->dev); device_release_driver(&dev->dev); pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); diff --git a/include/linux/pci-pwrctrl.h b/include/linux/pci-pwrctrl.h index 0d23dddf59ec..7d439b0675e9 100644 --- a/include/linux/pci-pwrctrl.h +++ b/include/linux/pci-pwrctrl.h @@ -3,8 +3,8 @@ * Copyright (C) 2024 Linaro Ltd. */ -#ifndef __PCI_PWRCTL_H__ -#define __PCI_PWRCTL_H__ +#ifndef __PCI_PWRCTRL_H__ +#define __PCI_PWRCTRL_H__ #include #include @@ -29,14 +29,14 @@ struct device_link; */ /** - * struct pci_pwrctl - PCI device power control context. + * struct pci_pwrctrl - PCI device power control context. * @dev: Address of the power controlling device. * * An object of this type must be allocated by the PCI power control device and - * passed to the pwrctl subsystem to trigger a bus rescan and setup a device + * passed to the pwrctrl subsystem to trigger a bus rescan and setup a device * link with the device once it's up. */ -struct pci_pwrctl { +struct pci_pwrctrl { struct device *dev; /* Private: don't use. */ @@ -45,10 +45,10 @@ struct pci_pwrctl { struct work_struct work; }; -void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev); -int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl); -void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl); -int devm_pci_pwrctl_device_set_ready(struct device *dev, - struct pci_pwrctl *pwrctl); +void pci_pwrctrl_init(struct pci_pwrctrl *pwrctrl, struct device *dev); +int pci_pwrctrl_device_set_ready(struct pci_pwrctrl *pwrctrl); +void pci_pwrctrl_device_unset_ready(struct pci_pwrctrl *pwrctrl); +int devm_pci_pwrctrl_device_set_ready(struct device *dev, + struct pci_pwrctrl *pwrctrl); -#endif /* __PCI_PWRCTL_H__ */ +#endif /* __PCI_PWRCTRL_H__ */