Skip to content

Commit cb0701a

Browse files
andy-shevrafaeljw
authored andcommitted
ACPI: platform: Unregister stale platform devices
When commit 68bdb67 ("ACPI: add support for ACPI reconfiguration notifiers") introduced reconfiguration notifiers, it missed the point that the ACPI table, which might be loaded and then unloaded via ConfigFS, could contain devices that were not enumerated by their parents. In such cases, the stale platform device is dangling in the system while the rest of the devices from the same table are already gone. Introduce acpi_platform_device_remove_notify() notifier that, in similar way to I²C or SPI buses, unregisters the platform devices on table removal event. Fixes: 68bdb67 ("ACPI: add support for ACPI reconfiguration notifiers") Depends-on: 0050014 ("drivers: Introduce device lookup variants by ACPI_COMPANION device") Signed-off-by: Andy Shevchenko <[email protected]> [ rjw: Changelog & function rename ] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent ac36d37 commit cb0701a

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

drivers/acpi/acpi_platform.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,44 @@ static const struct acpi_device_id forbidden_id_list[] = {
3131
{"", 0},
3232
};
3333

34+
static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev)
35+
{
36+
struct device *dev;
37+
38+
dev = bus_find_device_by_acpi_dev(&platform_bus_type, adev);
39+
return dev ? to_platform_device(dev) : NULL;
40+
}
41+
42+
static int acpi_platform_device_remove_notify(struct notifier_block *nb,
43+
unsigned long value, void *arg)
44+
{
45+
struct acpi_device *adev = arg;
46+
struct platform_device *pdev;
47+
48+
switch (value) {
49+
case ACPI_RECONFIG_DEVICE_ADD:
50+
/* Nothing to do here */
51+
break;
52+
case ACPI_RECONFIG_DEVICE_REMOVE:
53+
if (!acpi_device_enumerated(adev))
54+
break;
55+
56+
pdev = acpi_platform_device_find_by_companion(adev);
57+
if (!pdev)
58+
break;
59+
60+
platform_device_unregister(pdev);
61+
put_device(&pdev->dev);
62+
break;
63+
}
64+
65+
return NOTIFY_OK;
66+
}
67+
68+
static struct notifier_block acpi_platform_notifier = {
69+
.notifier_call = acpi_platform_device_remove_notify,
70+
};
71+
3472
static void acpi_platform_fill_resource(struct acpi_device *adev,
3573
const struct resource *src, struct resource *dest)
3674
{
@@ -130,3 +168,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
130168
return pdev;
131169
}
132170
EXPORT_SYMBOL_GPL(acpi_create_platform_device);
171+
172+
void __init acpi_platform_init(void)
173+
{
174+
acpi_reconfig_notifier_register(&acpi_platform_notifier);
175+
}

drivers/acpi/scan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,7 @@ int __init acpi_scan_init(void)
21742174
acpi_pci_root_init();
21752175
acpi_pci_link_init();
21762176
acpi_processor_init();
2177+
acpi_platform_init();
21772178
acpi_lpss_init();
21782179
acpi_apd_init();
21792180
acpi_cmos_rtc_init();

0 commit comments

Comments
 (0)