diff options
Diffstat (limited to 'drivers/acpi/container.c')
| -rw-r--r-- | drivers/acpi/container.c | 76 | 
1 files changed, 69 insertions, 7 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index e2315166765..76f7cff6459 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -27,13 +27,10 @@   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   */  #include <linux/acpi.h> +#include <linux/container.h>  #include "internal.h" -#include "internal.h" - -#define PREFIX "ACPI: " -  #define _COMPONENT			ACPI_CONTAINER_COMPONENT  ACPI_MODULE_NAME("container"); @@ -44,23 +41,88 @@ static const struct acpi_device_id container_device_ids[] = {  	{"", 0},  }; -static int container_device_attach(struct acpi_device *device, +#ifdef CONFIG_ACPI_CONTAINER + +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; + +	if (adev->flags.is_dock_station) +		return 0; + +	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) { +		put_device(dev); +		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,  	},  };  void __init acpi_container_init(void)  { +	acpi_scan_add_handler(&container_handler); +} + +#else + +static struct acpi_scan_handler container_handler = { +	.ids = container_device_ids, +}; + +void __init acpi_container_init(void) +{  	acpi_scan_add_handler_with_hotplug(&container_handler, "container");  } + +#endif /* CONFIG_ACPI_CONTAINER */  | 
