diff options
Diffstat (limited to 'drivers/acpi/container.c')
| -rw-r--r-- | drivers/acpi/container.c | 277 | 
1 files changed, 61 insertions, 216 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 45cd03b4630..76f7cff6459 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -1,12 +1,12 @@  /* - * acpi_container.c  - ACPI Generic Container Driver - * ($Revision: ) + * container.c  - ACPI Generic Container Driver   *   * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)   * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)   * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com) - * Copyright (C) 2004 Intel Corp.   * Copyright (C) 2004 FUJITSU LIMITED + * Copyright (C) 2004, 2013 Intel Corp. + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>   *   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   * @@ -26,258 +26,103 @@   *   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/types.h>  #include <linux/acpi.h> -#include <acpi/acpi_bus.h> -#include <acpi/acpi_drivers.h> -#include <acpi/container.h> +#include <linux/container.h> -#define PREFIX "ACPI: " - -#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device" -#define ACPI_CONTAINER_CLASS		"container" - -#define INSTALL_NOTIFY_HANDLER		1 -#define UNINSTALL_NOTIFY_HANDLER	2 +#include "internal.h"  #define _COMPONENT			ACPI_CONTAINER_COMPONENT  ACPI_MODULE_NAME("container"); -MODULE_AUTHOR("Anil S Keshavamurthy"); -MODULE_DESCRIPTION("ACPI container driver"); -MODULE_LICENSE("GPL"); - -static int acpi_container_add(struct acpi_device *device); -static int acpi_container_remove(struct acpi_device *device, int type); -  static const struct acpi_device_id container_device_ids[] = {  	{"ACPI0004", 0},  	{"PNP0A05", 0},  	{"PNP0A06", 0},  	{"", 0},  }; -MODULE_DEVICE_TABLE(acpi, container_device_ids); - -static struct acpi_driver acpi_container_driver = { -	.name = "container", -	.class = ACPI_CONTAINER_CLASS, -	.ids = container_device_ids, -	.ops = { -		.add = acpi_container_add, -		.remove = acpi_container_remove, -		}, -}; -/*******************************************************************/ - -static int is_device_present(acpi_handle handle) -{ -	acpi_handle temp; -	acpi_status status; -	unsigned long long sta; - - -	status = acpi_get_handle(handle, "_STA", &temp); -	if (ACPI_FAILURE(status)) -		return 1;	/* _STA not found, assume device present */ - -	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); -	if (ACPI_FAILURE(status)) -		return 0;	/* Firmware error */ - -	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); -} +#ifdef CONFIG_ACPI_CONTAINER -/*******************************************************************/ -static int acpi_container_add(struct acpi_device *device) +static int acpi_container_offline(struct container_dev *cdev)  { -	struct acpi_container *container; +	struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); +	struct acpi_device *child; - -	if (!device) { -		printk(KERN_ERR PREFIX "device is NULL\n"); -		return -EINVAL; -	} - -	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); -	if (!container) -		return -ENOMEM; - -	container->handle = device->handle; -	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); -	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); -	device->driver_data = container; - -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", -			  acpi_device_name(device), acpi_device_bid(device))); +	/* 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 int acpi_container_remove(struct acpi_device *device, int type) +static void acpi_container_release(struct device *dev)  { -	acpi_status status = AE_OK; -	struct acpi_container *pc = NULL; - -	pc = acpi_driver_data(device); -	kfree(pc); -	return status; +	kfree(to_container_dev(dev));  } -static int container_device_add(struct acpi_device **device, acpi_handle handle) +static int container_device_attach(struct acpi_device *adev, +				   const struct acpi_device_id *not_used)  { -	acpi_handle phandle; -	struct acpi_device *pdev; -	int result; +	struct container_dev *cdev; +	struct device *dev; +	int ret; +	if (adev->flags.is_dock_station) +		return 0; -	if (acpi_get_parent(handle, &phandle)) { -		return -ENODEV; -	} - -	if (acpi_bus_get_device(phandle, &pdev)) { -		return -ENODEV; -	} +	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); +	if (!cdev) +		return -ENOMEM; -	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { -		return -ENODEV; +	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;  	} - -	result = acpi_bus_start(*device); - -	return result; +	adev->driver_data = dev; +	return 1;  } -static void container_notify_cb(acpi_handle handle, u32 type, void *context) +static void container_device_detach(struct acpi_device *adev)  { -	struct acpi_device *device = NULL; -	int result; -	int present; -	acpi_status status; - +	struct device *dev = acpi_driver_data(adev); -	present = is_device_present(handle); - -	switch (type) { -	case ACPI_NOTIFY_BUS_CHECK: -		/* Fall through */ -	case ACPI_NOTIFY_DEVICE_CHECK: -		printk(KERN_WARNING "Container driver received %s event\n", -		       (type == ACPI_NOTIFY_BUS_CHECK) ? -		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); -		status = acpi_bus_get_device(handle, &device); -		if (present) { -			if (ACPI_FAILURE(status) || !device) { -				result = container_device_add(&device, handle); -				if (!result) -					kobject_uevent(&device->dev.kobj, -						       KOBJ_ONLINE); -				else -					printk(KERN_WARNING -					       "Failed to add container\n"); -			} -		} else { -			if (ACPI_SUCCESS(status)) { -				/* device exist and this is a remove request */ -				kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); -			} -		} -		break; -	case ACPI_NOTIFY_EJECT_REQUEST: -		if (!acpi_bus_get_device(handle, &device) && device) { -			kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); -		} -		break; -	default: -		break; -	} -	return; +	adev->driver_data = NULL; +	if (dev) +		device_unregister(dev);  } -static acpi_status -container_walk_namespace_cb(acpi_handle handle, -			    u32 lvl, void *context, void **rv) -{ -	char *hid = NULL; -	struct acpi_device_info *info; -	acpi_status status; -	int *action = context; - -	status = acpi_get_object_info(handle, &info); -	if (ACPI_FAILURE(status)) { -		return AE_OK; -	} - -	if (info->valid & ACPI_VALID_HID) -		hid = info->hardware_id.string; - -	if (hid == NULL) { -		goto end; -	} - -	if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") && -	    strcmp(hid, "PNP0A06")) { -		goto end; -	} - -	switch (*action) { -	case INSTALL_NOTIFY_HANDLER: -		acpi_install_notify_handler(handle, -					    ACPI_SYSTEM_NOTIFY, -					    container_notify_cb, NULL); -		break; -	case UNINSTALL_NOTIFY_HANDLER: -		acpi_remove_notify_handler(handle, -					   ACPI_SYSTEM_NOTIFY, -					   container_notify_cb); -		break; -	default: -		break; -	} - -      end: -	kfree(info); - -	return AE_OK; -} +static struct acpi_scan_handler container_handler = { +	.ids = container_device_ids, +	.attach = container_device_attach, +	.detach = container_device_detach, +	.hotplug = { +		.enabled = true, +		.demand_offline = true, +	}, +}; -static int __init acpi_container_init(void) +void __init acpi_container_init(void)  { -	int result = 0; -	int action = INSTALL_NOTIFY_HANDLER; - -	result = acpi_bus_register_driver(&acpi_container_driver); -	if (result < 0) { -		return (result); -	} - -	/* register notify handler to every container device */ -	acpi_walk_namespace(ACPI_TYPE_DEVICE, -			    ACPI_ROOT_OBJECT, -			    ACPI_UINT32_MAX, -			    container_walk_namespace_cb, NULL, &action, NULL); - -	return (0); +	acpi_scan_add_handler(&container_handler);  } -static void __exit acpi_container_exit(void) -{ -	int action = UNINSTALL_NOTIFY_HANDLER; - - -	acpi_walk_namespace(ACPI_TYPE_DEVICE, -			    ACPI_ROOT_OBJECT, -			    ACPI_UINT32_MAX, -			    container_walk_namespace_cb, NULL, &action, NULL); +#else -	acpi_bus_unregister_driver(&acpi_container_driver); +static struct acpi_scan_handler container_handler = { +	.ids = container_device_ids, +}; -	return; +void __init acpi_container_init(void) +{ +	acpi_scan_add_handler_with_hotplug(&container_handler, "container");  } -module_init(acpi_container_init); -module_exit(acpi_container_exit); +#endif /* CONFIG_ACPI_CONTAINER */  | 
