diff options
Diffstat (limited to 'drivers/acpi/container.c')
-rw-r--r-- | drivers/acpi/container.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index e23151667655..0b6ae6eb5c4a 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -27,8 +27,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include <linux/acpi.h> - -#include "internal.h" +#include <linux/container.h> #include "internal.h" @@ -44,19 +43,65 @@ static const struct acpi_device_id container_device_ids[] = { {"", 0}, }; -static int container_device_attach(struct acpi_device *device, +static int acpi_container_offline(struct container_dev *cdev) +{ + struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); + struct acpi_device *child; + + /* Check all of the dependent devices' physical companions. */ + list_for_each_entry(child, &adev->children, node) + if (!acpi_scan_is_offline(child, false)) + return -EBUSY; + + return 0; +} + +static void acpi_container_release(struct device *dev) +{ + kfree(to_container_dev(dev)); +} + +static int container_device_attach(struct acpi_device *adev, const struct acpi_device_id *not_used) { - /* This is necessary for container hotplug to work. */ + struct container_dev *cdev; + struct device *dev; + int ret; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + cdev->offline = acpi_container_offline; + dev = &cdev->dev; + dev->bus = &container_subsys; + dev_set_name(dev, "%s", dev_name(&adev->dev)); + ACPI_COMPANION_SET(dev, adev); + dev->release = acpi_container_release; + ret = device_register(dev); + if (ret) + return ret; + + adev->driver_data = dev; return 1; } +static void container_device_detach(struct acpi_device *adev) +{ + struct device *dev = acpi_driver_data(adev); + + adev->driver_data = NULL; + if (dev) + device_unregister(dev); +} + static struct acpi_scan_handler container_handler = { .ids = container_device_ids, .attach = container_device_attach, + .detach = container_device_detach, .hotplug = { .enabled = true, - .mode = AHM_CONTAINER, + .demand_offline = true, }, }; |