* [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11
@ 2024-08-19 8:24 Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 1/2] PCI: don't rely on of_platform_depopulate() for reused OF-nodes Bartosz Golaszewski
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Bartosz Golaszewski @ 2024-08-19 8:24 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-pci, linux-kernel, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Here are two fixes addressing issues with PCI pwrctl detected in some
corner-cases.
v1 -> v2:
- use the scoped variant of for_each_child_of_node() to fix a memory
leak in patch 1/2
Bartosz Golaszewski (2):
PCI: don't rely on of_platform_depopulate() for reused OF-nodes
PCI/pwrctl: put the bus rescan on a different thread
drivers/pci/pwrctl/core.c | 26 +++++++++++++++++++++++---
drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 2 +-
drivers/pci/remove.c | 16 +++++++++++++++-
include/linux/pci-pwrctl.h | 3 +++
4 files changed, 42 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/2] PCI: don't rely on of_platform_depopulate() for reused OF-nodes
2024-08-19 8:24 [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
@ 2024-08-19 8:24 ` Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 2/2] PCI/pwrctl: put the bus rescan on a different thread Bartosz Golaszewski
2024-08-22 10:23 ` [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
2 siblings, 0 replies; 4+ messages in thread
From: Bartosz Golaszewski @ 2024-08-19 8:24 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-pci, linux-kernel, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
of_platform_depopulate() doesn't play nice with reused OF nodes - it
ignores the ones that are not marked explicitly as populated and it may
happen that the PCI device goes away before the platform device in which
case the PCI core clears the OF_POPULATED bit. We need to
unconditionally unregister the platform devices for child nodes when
stopping the PCI device.
Fixes: 8fb18619d910 ("PCI/pwrctl: Create platform devices for child OF nodes of the port node")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/remove.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 910387e5bdbf..c7092a34a5f6 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
#include "pci.h"
@@ -16,13 +17,26 @@ static void pci_free_resources(struct pci_dev *dev)
static void pci_stop_dev(struct pci_dev *dev)
{
+ struct platform_device *pdev;
+
pci_pme_active(dev, false);
if (pci_dev_is_added(dev)) {
- of_platform_depopulate(&dev->dev);
device_release_driver(&dev->dev);
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
+
+ if (dev_of_node(&dev->dev)) {
+ for_each_child_of_node_scoped(dev_of_node(&dev->dev),
+ child) {
+ pdev = of_find_device_by_node(child);
+ if (pdev) {
+ of_device_unregister(pdev);
+ of_node_clear_flag(child, OF_POPULATED);
+ }
+ }
+ }
+
of_pci_remove_node(dev);
pci_dev_assign_added(dev, false);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] PCI/pwrctl: put the bus rescan on a different thread
2024-08-19 8:24 [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 1/2] PCI: don't rely on of_platform_depopulate() for reused OF-nodes Bartosz Golaszewski
@ 2024-08-19 8:24 ` Bartosz Golaszewski
2024-08-22 10:23 ` [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
2 siblings, 0 replies; 4+ messages in thread
From: Bartosz Golaszewski @ 2024-08-19 8:24 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-pci, linux-kernel, Bartosz Golaszewski, Konrad Dybcio
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
If we trigger the bus rescan from sysfs, we'll try to lock the PCI
rescan mutex recursively and deadlock - the platform device will be
populated and probed on the same thread that handles the sysfs write.
Add a workqueue to the pwrctl code on which we schedule the rescan for
controlled PCI devices. While at it: add a new interface for
initializing the pwrctl context where we'd now assign the parent device
address and initialize the workqueue.
Fixes: 4565d2652a37 ("PCI/pwrctl: Add PCI power control core code")
Reported-by: Konrad Dybcio <konradybcio@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/pwrctl/core.c | 26 +++++++++++++++++++++++---
drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 2 +-
include/linux/pci-pwrctl.h | 3 +++
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/pwrctl/core.c b/drivers/pci/pwrctl/core.c
index feca26ad2f6a..01d913b60316 100644
--- a/drivers/pci/pwrctl/core.c
+++ b/drivers/pci/pwrctl/core.c
@@ -48,6 +48,28 @@ static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE;
}
+static void rescan_work_func(struct work_struct *work)
+{
+ struct pci_pwrctl *pwrctl = container_of(work, struct pci_pwrctl, work);
+
+ pci_lock_rescan_remove();
+ pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
+ pci_unlock_rescan_remove();
+}
+
+/**
+ * pci_pwrctl_init() - Initialize the PCI power control context struct
+ *
+ * @pwrctl: PCI power control data
+ * @dev: Parent device
+ */
+void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev)
+{
+ pwrctl->dev = dev;
+ INIT_WORK(&pwrctl->work, rescan_work_func);
+}
+EXPORT_SYMBOL_GPL(pci_pwrctl_init);
+
/**
* pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI
* device is powered-up and ready to be detected.
@@ -74,9 +96,7 @@ int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl)
if (ret)
return ret;
- pci_lock_rescan_remove();
- pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
- pci_unlock_rescan_remove();
+ schedule_work(&pwrctl->work);
return 0;
}
diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
index c7a113a76c0c..f07758c9edad 100644
--- a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
+++ b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
@@ -50,7 +50,7 @@ static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
if (ret)
return ret;
- data->ctx.dev = dev;
+ pci_pwrctl_init(&data->ctx, dev);
ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
if (ret)
diff --git a/include/linux/pci-pwrctl.h b/include/linux/pci-pwrctl.h
index 45e9cfe740e4..0d23dddf59ec 100644
--- a/include/linux/pci-pwrctl.h
+++ b/include/linux/pci-pwrctl.h
@@ -7,6 +7,7 @@
#define __PCI_PWRCTL_H__
#include <linux/notifier.h>
+#include <linux/workqueue.h>
struct device;
struct device_link;
@@ -41,8 +42,10 @@ struct pci_pwrctl {
/* Private: don't use. */
struct notifier_block nb;
struct device_link *link;
+ 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,
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11
2024-08-19 8:24 [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 1/2] PCI: don't rely on of_platform_depopulate() for reused OF-nodes Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 2/2] PCI/pwrctl: put the bus rescan on a different thread Bartosz Golaszewski
@ 2024-08-22 10:23 ` Bartosz Golaszewski
2 siblings, 0 replies; 4+ messages in thread
From: Bartosz Golaszewski @ 2024-08-22 10:23 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-pci, linux-kernel, Bartosz Golaszewski
On Mon, Aug 19, 2024 at 10:24 AM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Here are two fixes addressing issues with PCI pwrctl detected in some
> corner-cases.
>
> v1 -> v2:
> - use the scoped variant of for_each_child_of_node() to fix a memory
> leak in patch 1/2
>
> Bartosz Golaszewski (2):
> PCI: don't rely on of_platform_depopulate() for reused OF-nodes
> PCI/pwrctl: put the bus rescan on a different thread
>
> drivers/pci/pwrctl/core.c | 26 +++++++++++++++++++++++---
> drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 2 +-
> drivers/pci/remove.c | 16 +++++++++++++++-
> include/linux/pci-pwrctl.h | 3 +++
> 4 files changed, 42 insertions(+), 5 deletions(-)
>
> --
> 2.43.0
>
Bjorn,
We found another issue that will require extending and modifying of
this series. Please disregard this iteration and I'll send a new
version shortly.
Bart
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-08-22 10:23 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-19 8:24 [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 1/2] PCI: don't rely on of_platform_depopulate() for reused OF-nodes Bartosz Golaszewski
2024-08-19 8:24 ` [PATCH v2 2/2] PCI/pwrctl: put the bus rescan on a different thread Bartosz Golaszewski
2024-08-22 10:23 ` [PATCH v2 0/2] PCI/pwrctl: fixes for v6.11 Bartosz Golaszewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox