|
|
|
@ -38,42 +38,31 @@
|
|
|
|
|
|
|
|
|
|
#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);
|
|
|
|
|
|
|
|
|
|
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,49 +81,6 @@ static int is_device_present(acpi_handle handle)
|
|
|
|
|
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_container_device(const char *hid)
|
|
|
|
|
{
|
|
|
|
|
const struct acpi_device_id *container_id;
|
|
|
|
|
|
|
|
|
|
for (container_id = container_device_ids;
|
|
|
|
|
container_id->id[0]; container_id++) {
|
|
|
|
|
if (!strcmp((char *)container_id->id, hid))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
|
|
|
static int acpi_container_add(struct acpi_device *device)
|
|
|
|
|
{
|
|
|
|
|
struct acpi_container *container;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
acpi_status status = AE_OK;
|
|
|
|
|
struct acpi_container *pc = NULL;
|
|
|
|
|
|
|
|
|
|
pc = acpi_driver_data(device);
|
|
|
|
|
kfree(pc);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
|
|
|
|
{
|
|
|
|
|
struct acpi_device *device = NULL;
|
|
|
|
@ -199,84 +145,43 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
status = acpi_get_object_info(handle, &info);
|
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
|
|
return AE_OK;
|
|
|
|
|
if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (info->valid & ACPI_VALID_HID) {
|
|
|
|
|
const struct acpi_device_id *id;
|
|
|
|
|
|
|
|
|
|
for (id = container_device_ids; id->id[0]; id++) {
|
|
|
|
|
ret = !strcmp((char *)id->id, info->hardware_id.string);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info->valid & ACPI_VALID_HID)
|
|
|
|
|
hid = info->hardware_id.string;
|
|
|
|
|
|
|
|
|
|
if (hid == NULL) {
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_container_device(hid))
|
|
|
|
|
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 ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
|
|
|
|
|
u32 lvl, void *ctxt,
|
|
|
|
|
void **retv)
|
|
|
|
|
{
|
|
|
|
|
if (is_container(handle))
|
|
|
|
|
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
|
|
|
|
|
container_notify_cb, NULL);
|
|
|
|
|
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __init acpi_container_init(void)
|
|
|
|
|
void __init acpi_container_init(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
|
int action = INSTALL_NOTIFY_HANDLER;
|
|
|
|
|
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
|
|
|
|
acpi_container_register_notify_handler, NULL,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
|
|
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_device_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);
|
|
|
|
|
|
|
|
|
|
acpi_bus_unregister_driver(&acpi_container_driver);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module_init(acpi_container_init);
|
|
|
|
|
module_exit(acpi_container_exit);
|
|
|
|
|