ACPI: platform: Unregister stale platform devices
When commit68bdb67732
("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:68bdb67732
("ACPI: add support for ACPI reconfiguration notifiers") Depends-on:00500147cb
("drivers: Introduce device lookup variants by ACPI_COMPANION device") Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> [ rjw: Changelog & function rename ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
ac36d37e94
commit
cb0701acfa
@ -31,6 +31,44 @@ static const struct acpi_device_id forbidden_id_list[] = {
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = bus_find_device_by_acpi_dev(&platform_bus_type, adev);
|
||||
return dev ? to_platform_device(dev) : NULL;
|
||||
}
|
||||
|
||||
static int acpi_platform_device_remove_notify(struct notifier_block *nb,
|
||||
unsigned long value, void *arg)
|
||||
{
|
||||
struct acpi_device *adev = arg;
|
||||
struct platform_device *pdev;
|
||||
|
||||
switch (value) {
|
||||
case ACPI_RECONFIG_DEVICE_ADD:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
case ACPI_RECONFIG_DEVICE_REMOVE:
|
||||
if (!acpi_device_enumerated(adev))
|
||||
break;
|
||||
|
||||
pdev = acpi_platform_device_find_by_companion(adev);
|
||||
if (!pdev)
|
||||
break;
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
put_device(&pdev->dev);
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block acpi_platform_notifier = {
|
||||
.notifier_call = acpi_platform_device_remove_notify,
|
||||
};
|
||||
|
||||
static void acpi_platform_fill_resource(struct acpi_device *adev,
|
||||
const struct resource *src, struct resource *dest)
|
||||
{
|
||||
@ -130,3 +168,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
|
||||
return pdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_create_platform_device);
|
||||
|
||||
void __init acpi_platform_init(void)
|
||||
{
|
||||
acpi_reconfig_notifier_register(&acpi_platform_notifier);
|
||||
}
|
||||
|
@ -2174,6 +2174,7 @@ int __init acpi_scan_init(void)
|
||||
acpi_pci_root_init();
|
||||
acpi_pci_link_init();
|
||||
acpi_processor_init();
|
||||
acpi_platform_init();
|
||||
acpi_lpss_init();
|
||||
acpi_apd_init();
|
||||
acpi_cmos_rtc_init();
|
||||
|
Loading…
Reference in New Issue
Block a user