diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-06 17:31:37 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-06 17:31:37 +0100 |
commit | 3c2cc7ff9e2522e42468f8e81a7277be386c5ec4 (patch) | |
tree | e8a8405373896d0ff02a7d41a244fa81547c6f73 /include/acpi | |
parent | e525506fcb67a9bbd94f01eac84af802139004eb (diff) | |
download | linux-next-3c2cc7ff9e2522e42468f8e81a7277be386c5ec4.tar.gz |
ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices. However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to the theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).
In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn(). For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler. At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices or use the generic
ACPI device hotplug code for device objects with matching scan
handlers.
This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'include/acpi')
-rw-r--r-- | include/acpi/acpi_bus.h | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0c82708ff08a..53ce357f6335 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -137,6 +137,16 @@ struct acpi_scan_handler { }; /* + * ACPI Hotplug Context + * -------------------- + */ + +struct acpi_hotplug_context { + struct acpi_device *self; + int (*event)(struct acpi_device *, u32); +}; + +/* * ACPI Driver * ----------- */ @@ -190,7 +200,8 @@ struct acpi_device_flags { u32 initialized:1; u32 visited:1; u32 no_hotplug:1; - u32 reserved:24; + u32 hotplug_notify:1; + u32 reserved:23; }; /* File System */ @@ -329,6 +340,7 @@ struct acpi_device { struct acpi_device_perf performance; struct acpi_device_dir dir; struct acpi_scan_handler *handler; + struct acpi_hotplug_context *hp; struct acpi_driver *driver; void *driver_data; struct device dev; @@ -351,6 +363,15 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) *((u32 *)&adev->status) = sta; } +static inline void acpi_set_hp_context(struct acpi_device *adev, + struct acpi_hotplug_context *hp, + int (*event)(struct acpi_device *, u32)) +{ + hp->self = adev; + hp->event = event; + adev->hp = hp; +} + /* acpi_device.dev.bus == &acpi_bus_type */ extern struct bus_type acpi_bus_type; @@ -425,6 +446,8 @@ static inline bool acpi_device_enumerated(struct acpi_device *adev) typedef void (*acpi_hp_callback)(void *data, u32 src); acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); +void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data); +void acpi_remove_hotplug_notify_handler(acpi_handle handle); /** * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver |