Skip to content

Commit 487ee43

Browse files
committed
Merge tag 'pci-v6.11-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
Pull pci fixes from Bjorn Helgaas: - Unregister platform devices for child nodes when stopping a PCI device, even if the PCI core has already cleared the OF_POPULATED bit and of_platform_depopulate() doesn't do anything (Bartosz Golaszewski) - Rescan the bus from a separate thread so we don't deadlock when triggering rescan from sysfs (Bartosz Golaszewski) * tag 'pci-v6.11-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: PCI/pwrctl: Rescan bus on a separate thread PCI: Don't rely on of_platform_depopulate() for reused OF-nodes
2 parents a86b83f + 8f62819 commit 487ee43

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

drivers/pci/pwrctl/core.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action,
4848
return NOTIFY_DONE;
4949
}
5050

51+
static void rescan_work_func(struct work_struct *work)
52+
{
53+
struct pci_pwrctl *pwrctl = container_of(work, struct pci_pwrctl, work);
54+
55+
pci_lock_rescan_remove();
56+
pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
57+
pci_unlock_rescan_remove();
58+
}
59+
60+
/**
61+
* pci_pwrctl_init() - Initialize the PCI power control context struct
62+
*
63+
* @pwrctl: PCI power control data
64+
* @dev: Parent device
65+
*/
66+
void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev)
67+
{
68+
pwrctl->dev = dev;
69+
INIT_WORK(&pwrctl->work, rescan_work_func);
70+
}
71+
EXPORT_SYMBOL_GPL(pci_pwrctl_init);
72+
5173
/**
5274
* pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI
5375
* device is powered-up and ready to be detected.
@@ -74,9 +96,7 @@ int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl)
7496
if (ret)
7597
return ret;
7698

77-
pci_lock_rescan_remove();
78-
pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
79-
pci_unlock_rescan_remove();
99+
schedule_work(&pwrctl->work);
80100

81101
return 0;
82102
}

drivers/pci/pwrctl/pci-pwrctl-pwrseq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
5050
if (ret)
5151
return ret;
5252

53-
data->ctx.dev = dev;
53+
pci_pwrctl_init(&data->ctx, dev);
5454

5555
ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
5656
if (ret)

drivers/pci/remove.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/pci.h>
33
#include <linux/module.h>
4+
#include <linux/of.h>
45
#include <linux/of_platform.h>
6+
#include <linux/platform_device.h>
7+
58
#include "pci.h"
69

710
static void pci_free_resources(struct pci_dev *dev)
@@ -14,12 +17,25 @@ static void pci_free_resources(struct pci_dev *dev)
1417
}
1518
}
1619

20+
static int pci_pwrctl_unregister(struct device *dev, void *data)
21+
{
22+
struct device_node *pci_node = data, *plat_node = dev_of_node(dev);
23+
24+
if (dev_is_platform(dev) && plat_node && plat_node == pci_node) {
25+
of_device_unregister(to_platform_device(dev));
26+
of_node_clear_flag(plat_node, OF_POPULATED);
27+
}
28+
29+
return 0;
30+
}
31+
1732
static void pci_stop_dev(struct pci_dev *dev)
1833
{
1934
pci_pme_active(dev, false);
2035

2136
if (pci_dev_is_added(dev)) {
22-
of_platform_depopulate(&dev->dev);
37+
device_for_each_child(dev->dev.parent, dev_of_node(&dev->dev),
38+
pci_pwrctl_unregister);
2339
device_release_driver(&dev->dev);
2440
pci_proc_detach_device(dev);
2541
pci_remove_sysfs_dev_files(dev);

include/linux/pci-pwrctl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define __PCI_PWRCTL_H__
88

99
#include <linux/notifier.h>
10+
#include <linux/workqueue.h>
1011

1112
struct device;
1213
struct device_link;
@@ -41,8 +42,10 @@ struct pci_pwrctl {
4142
/* Private: don't use. */
4243
struct notifier_block nb;
4344
struct device_link *link;
45+
struct work_struct work;
4446
};
4547

48+
void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev);
4649
int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl);
4750
void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl);
4851
int devm_pci_pwrctl_device_set_ready(struct device *dev,

0 commit comments

Comments
 (0)