diff options
Diffstat (limited to 'drivers/acpi/container.c')
| -rw-r--r-- | drivers/acpi/container.c | 210 | 
1 files changed, 52 insertions, 158 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 1f9f7d7d7bc..5523ba7d764 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -34,46 +34,34 @@  #include <linux/acpi.h>  #include <acpi/acpi_bus.h>  #include <acpi/acpi_drivers.h> -#include <acpi/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 -  #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, +static int container_device_attach(struct acpi_device *device, +				   const struct acpi_device_id *not_used) +{ +	/* +	 * FIXME: This is necessary, so that acpi_eject_store() doesn't return +	 * -ENODEV for containers. +	 */ +	return 1; +} + +static struct acpi_scan_handler container_device_handler = {  	.ids = container_device_ids, -	.ops = { -		.add = acpi_container_add, -		.remove = acpi_container_remove, -		}, +	.attach = container_device_attach,  }; -/*******************************************************************/ -  static int is_device_present(acpi_handle handle)  {  	acpi_handle temp; @@ -92,66 +80,6 @@ static int is_device_present(acpi_handle handle)  	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);  } -/*******************************************************************/ -static int acpi_container_add(struct acpi_device *device) -{ -	struct acpi_container *container; - - -	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))); - -	return 0; -} - -static int acpi_container_remove(struct acpi_device *device, int type) -{ -	acpi_status status = AE_OK; -	struct acpi_container *pc = NULL; - -	pc = acpi_driver_data(device); -	kfree(pc); -	return status; -} - -static int container_device_add(struct acpi_device **device, acpi_handle handle) -{ -	acpi_handle phandle; -	struct acpi_device *pdev; -	int result; - - -	if (acpi_get_parent(handle, &phandle)) { -		return -ENODEV; -	} - -	if (acpi_bus_get_device(phandle, &pdev)) { -		return -ENODEV; -	} - -	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { -		return -ENODEV; -	} - -	result = acpi_bus_start(*device); - -	return result; -} -  static void container_notify_cb(acpi_handle handle, u32 type, void *context)  {  	struct acpi_device *device = NULL; @@ -160,11 +88,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)  	acpi_status status;  	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ +	acpi_scan_lock_acquire(); +  	switch (type) {  	case ACPI_NOTIFY_BUS_CHECK:  		/* Fall through */  	case ACPI_NOTIFY_DEVICE_CHECK: -		printk(KERN_WARNING "Container driver received %s event\n", +		pr_debug("Container driver received %s event\n",  		       (type == ACPI_NOTIFY_BUS_CHECK) ?  		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); @@ -175,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)  				/* device exist and this is a remove request */  				device->flags.eject_pending = 1;  				kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); -				return; +				goto out;  			}  			break;  		} @@ -183,9 +113,14 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)  		if (!ACPI_FAILURE(status) || device)  			break; -		result = container_device_add(&device, handle); +		result = acpi_bus_scan(handle);  		if (result) { -			printk(KERN_WARNING "Failed to add container\n"); +			acpi_handle_warn(handle, "Failed to add container\n"); +			break; +		} +		result = acpi_bus_get_device(handle, &device); +		if (result) { +			acpi_handle_warn(handle, "Missing device object\n");  			break;  		} @@ -197,100 +132,59 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)  		if (!acpi_bus_get_device(handle, &device) && device) {  			device->flags.eject_pending = 1;  			kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); -			return; +			goto out;  		}  		break;  	default:  		/* non-hotplug event; possibly handled by other handler */ -		return; +		goto out;  	}  	/* Inform firmware that the hotplug operation has completed */  	(void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); -	return; + + out: +	acpi_scan_lock_release();  } -static acpi_status -container_walk_namespace_cb(acpi_handle handle, -			    u32 lvl, void *context, void **rv) +static bool is_container(acpi_handle handle)  { -	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; +	bool ret = false; -	if (hid == NULL) { -		goto end; -	} +	if (ACPI_FAILURE(acpi_get_object_info(handle, &info))) +		return false; -	if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") && -	    strcmp(hid, "PNP0A06")) { -		goto end; -	} +	if (info->valid & ACPI_VALID_HID) { +		const struct acpi_device_id *id; -	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; +		for (id = container_device_ids; id->id[0]; id++) { +			ret = !strcmp((char *)id->id, info->hardware_id.string); +			if (ret) +				break; +		}  	} - -      end:  	kfree(info); - -	return AE_OK; +	return ret;  } -static int __init acpi_container_init(void) +static acpi_status acpi_container_register_notify_handler(acpi_handle handle, +							  u32 lvl, void *ctxt, +							  void **retv)  { -	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); +	if (is_container(handle)) +		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, +					    container_notify_cb, NULL); -	return (0); +	return AE_OK;  } -static void __exit acpi_container_exit(void) +void __init acpi_container_init(void)  { -	int action = UNINSTALL_NOTIFY_HANDLER; +	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, +			    acpi_container_register_notify_handler, NULL, +			    NULL, NULL); - -	acpi_walk_namespace(ACPI_TYPE_DEVICE, -			    ACPI_ROOT_OBJECT, -			    ACPI_UINT32_MAX, -			    container_walk_namespace_cb, NULL, &action, NULL); - -	acpi_bus_unregister_driver(&acpi_container_driver); - -	return; +	acpi_scan_add_handler(&container_device_handler);  } - -module_init(acpi_container_init); -module_exit(acpi_container_exit);  |