[PATCH v8 13/17] PCI/pwrctl: reuse the OF node for power controlled devices

Bartosz Golaszewski posted 17 patches 1 year, 6 months ago
[PATCH v8 13/17] PCI/pwrctl: reuse the OF node for power controlled devices
Posted by Bartosz Golaszewski 1 year, 6 months ago
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

With PCI power control we deal with two struct device objects bound to
two different drivers but consuming the same OF node. We must not bind
the pinctrl twice. To that end: before setting the OF node of the newly
instantiated PCI device, check if a platform device consuming the same
OF node doesn't already exist on the platform bus and - if so - mark the
PCI device as reusing the OF node.

Tested-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/pci/of.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 51e3dd0ea5ab..b908fe1ae951 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -6,6 +6,7 @@
  */
 #define pr_fmt(fmt)	"PCI: OF: " fmt
 
+#include <linux/cleanup.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -13,6 +14,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/platform_device.h>
 #include "pci.h"
 
 #ifdef CONFIG_PCI
@@ -25,16 +27,20 @@
  */
 int pci_set_of_node(struct pci_dev *dev)
 {
-	struct device_node *node;
-
 	if (!dev->bus->dev.of_node)
 		return 0;
 
-	node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
+	struct device_node *node __free(device_node) =
+		of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
 	if (!node)
 		return 0;
 
-	device_set_node(&dev->dev, of_fwnode_handle(node));
+	struct device *pdev __free(put_device) =
+		bus_find_device_by_of_node(&platform_bus_type, node);
+	if (pdev)
+		dev->bus->dev.of_node_reused = true;
+
+	device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
 	return 0;
 }
 

-- 
2.43.0
Re: [PATCH v8 13/17] PCI/pwrctl: reuse the OF node for power controlled devices
Posted by Bjorn Helgaas 1 year, 6 months ago
On Tue, May 28, 2024 at 09:03:21PM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> 
> With PCI power control we deal with two struct device objects bound to
> two different drivers but consuming the same OF node. We must not bind
> the pinctrl twice. To that end: before setting the OF node of the newly
> instantiated PCI device, check if a platform device consuming the same
> OF node doesn't already exist on the platform bus and - if so - mark the
> PCI device as reusing the OF node.
> 
> Tested-by: Amit Pundir <amit.pundir@linaro.org>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

With s/reuse/Reuse/ in subject to match history,

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Would be good to get Rob's ack as well.

> ---
>  drivers/pci/of.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
> index 51e3dd0ea5ab..b908fe1ae951 100644
> --- a/drivers/pci/of.c
> +++ b/drivers/pci/of.c
> @@ -6,6 +6,7 @@
>   */
>  #define pr_fmt(fmt)	"PCI: OF: " fmt
>  
> +#include <linux/cleanup.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
>  #include <linux/pci.h>
> @@ -13,6 +14,7 @@
>  #include <linux/of_irq.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
> +#include <linux/platform_device.h>
>  #include "pci.h"
>  
>  #ifdef CONFIG_PCI
> @@ -25,16 +27,20 @@
>   */
>  int pci_set_of_node(struct pci_dev *dev)
>  {
> -	struct device_node *node;
> -
>  	if (!dev->bus->dev.of_node)
>  		return 0;
>  
> -	node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
> +	struct device_node *node __free(device_node) =
> +		of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
>  	if (!node)
>  		return 0;
>  
> -	device_set_node(&dev->dev, of_fwnode_handle(node));
> +	struct device *pdev __free(put_device) =
> +		bus_find_device_by_of_node(&platform_bus_type, node);
> +	if (pdev)
> +		dev->bus->dev.of_node_reused = true;
> +
> +	device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
>  	return 0;
>  }
>  
> 
> -- 
> 2.43.0
>