From d43ec68e9837dfa6618ab473622683fdbf6e68a9 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 7 Dec 2006 20:56:23 +0800 Subject: ACPI: add device_driver and hepler functions Add device_driver into acpi_driver for driver model. Add helper functions 'to_acpi_device' and 'to_acpi_driver' to get structure acpi_device/acpi_driver by device/device_driver. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- include/acpi/acpi_bus.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/acpi/acpi_bus.h') diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index fdd10953b2b6..a09538eb61e7 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -136,6 +136,7 @@ struct acpi_driver { atomic_t references; char *ids; /* Supported Hardware IDs */ struct acpi_device_ops ops; + struct device_driver drv; }; /* @@ -301,6 +302,8 @@ struct acpi_device { }; #define acpi_driver_data(d) ((d)->driver_data) +#define to_acpi_device(d) container_of(d, struct acpi_device, dev) +#define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) /* * Events -- cgit v1.2.3 From 5d9464a46918ced087c351a10f38cee95725f85b Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 7 Dec 2006 20:56:27 +0800 Subject: ACPI: add ACPI bus_type for driver model Add ACPI bus_type for Linux driver model. 1. .shutdown method is added into acpi_driver.ops needed by bus_type operations. 2. remove useless parameter 'int state' in .resume method. 3. change parameter 'int state' to 'pm_message_t state' in .suspend method. Note: The new .uevent method mark ACPI drivers by PNPID instead of by name. Udev script needs to look for "HWID=" or "COMPTID=" to load ACPI drivers as a result. Signed-off-by: Li Shaohua Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/battery.c | 4 +- drivers/acpi/fan.c | 8 +-- drivers/acpi/scan.c | 158 ++++++++++++++++++++++++++++-------------------- drivers/acpi/thermal.c | 4 +- include/acpi/acpi_bus.h | 9 ++- 5 files changed, 105 insertions(+), 78 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 026e40755cdd..07c3c276ad34 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -64,7 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); static int acpi_battery_add(struct acpi_device *device); static int acpi_battery_remove(struct acpi_device *device, int type); -static int acpi_battery_resume(struct acpi_device *device, int status); +static int acpi_battery_resume(struct acpi_device *device); static struct acpi_driver acpi_battery_driver = { .name = ACPI_BATTERY_DRIVER_NAME, @@ -756,7 +756,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) } /* this is needed to learn about changes made in suspended state */ -static int acpi_battery_resume(struct acpi_device *device, int state) +static int acpi_battery_resume(struct acpi_device *device) { struct acpi_battery *battery; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 045c89477e59..b24942041b3f 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -48,8 +48,8 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); -static int acpi_fan_suspend(struct acpi_device *device, int state); -static int acpi_fan_resume(struct acpi_device *device, int state); +static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); +static int acpi_fan_resume(struct acpi_device *device); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -238,7 +238,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) return 0; } -static int acpi_fan_suspend(struct acpi_device *device, int state) +static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) { if (!device) return -EINVAL; @@ -248,7 +248,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state) return AE_OK; } -static int acpi_fan_resume(struct acpi_device *device, int state) +static int acpi_fan_resume(struct acpi_device *device) { int result = 0; int power_state = 0; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5b42948ea97f..464746257d8e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -222,100 +222,124 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) /* -------------------------------------------------------------------------- ACPI Bus operations -------------------------------------------------------------------------- */ -static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) +static int acpi_device_suspend(struct device *dev, pm_message_t state) { - struct acpi_device * dev, * next; - int result; + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = acpi_dev->driver; - spin_lock(&acpi_device_lock); - list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { - if (dev->driver && dev->driver->ops.suspend) { - spin_unlock(&acpi_device_lock); - result = dev->driver->ops.suspend(dev, 0); - if (result) { - printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", - acpi_device_name(dev), - acpi_device_bid(dev), result); - } - spin_lock(&acpi_device_lock); - } - } - spin_unlock(&acpi_device_lock); + if (acpi_drv && acpi_drv->ops.suspend) + return acpi_drv->ops.suspend(acpi_dev, state); return 0; } -static int acpi_device_suspend(struct device * dev, pm_message_t state) +static int acpi_device_resume(struct device *dev) { - struct acpi_device * acpi_dev = to_acpi_device(dev); + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = acpi_dev->driver; - /* - * For now, we should only register 1 generic device - - * the ACPI root device - and from there, we walk the - * tree of ACPI devices to suspend each one using the - * ACPI driver methods. - */ - if (acpi_dev->handle == ACPI_ROOT_OBJECT) - root_suspend(acpi_dev, state); + if (acpi_drv && acpi_drv->ops.resume) + return acpi_drv->ops.resume(acpi_dev); return 0; } -static int root_resume(struct acpi_device * acpi_dev) +static int acpi_bus_match(struct device *dev, struct device_driver *drv) { - struct acpi_device * dev, * next; - int result; + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = to_acpi_driver(drv); - spin_lock(&acpi_device_lock); - list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { - if (dev->driver && dev->driver->ops.resume) { - spin_unlock(&acpi_device_lock); - result = dev->driver->ops.resume(dev, 0); - if (result) { - printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", - acpi_device_name(dev), - acpi_device_bid(dev), result); - } - spin_lock(&acpi_device_lock); + if (acpi_drv->ops.match) + return !acpi_drv->ops.match(acpi_dev, acpi_drv); + return !acpi_match_ids(acpi_dev, acpi_drv->ids); +} + +static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct acpi_device *acpi_dev = to_acpi_device(dev); + int i = 0, length = 0, ret = 0; + + if (acpi_dev->flags.hardware_id) + ret = add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "HWID=%s", acpi_dev->pnp.hardware_id); + if (ret) + return -ENOMEM; + if (acpi_dev->flags.compatible_ids) { + int j; + struct acpi_compatible_id_list *cid_list; + + cid_list = acpi_dev->pnp.cid_list; + + for (j = 0; j < cid_list->count; j++) { + ret = add_uevent_var(envp, num_envp, &i, buffer, + buffer_size, &length, "COMPTID=%s", + cid_list->id[j].value); + if (ret) + return -ENOMEM; } } - spin_unlock(&acpi_device_lock); + + envp[i] = NULL; return 0; } -static int acpi_device_resume(struct device * dev) +static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); +static int acpi_start_single_object(struct acpi_device *); +static int acpi_device_probe(struct device * dev) { - struct acpi_device * acpi_dev = to_acpi_device(dev); + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); + int ret; + + ret = acpi_bus_driver_init(acpi_dev, acpi_drv); + if (!ret) { + acpi_start_single_object(acpi_dev); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found driver [%s] for device [%s]\n", + acpi_drv->name, acpi_dev->pnp.bus_id)); + get_device(dev); + } + return ret; +} - /* - * For now, we should only register 1 generic device - - * the ACPI root device - and from there, we walk the - * tree of ACPI devices to resume each one using the - * ACPI driver methods. - */ - if (acpi_dev->handle == ACPI_ROOT_OBJECT) - root_resume(acpi_dev); +static int acpi_device_remove(struct device * dev) +{ + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = acpi_dev->driver; + + if (acpi_drv) { + if (acpi_drv->ops.stop) + acpi_drv->ops.stop(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); + if (acpi_drv->ops.remove) + acpi_drv->ops.remove(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); + } + acpi_dev->driver = NULL; + acpi_driver_data(dev) = NULL; + + put_device(dev); return 0; } -/** - * acpi_bus_match - match device IDs to driver's supported IDs - * @device: the device that we are trying to match to a driver - * @driver: driver whose device id table is being checked - * - * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it - * matches the specified driver's criteria. - */ -static int -acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver) +static void acpi_device_shutdown(struct device *dev) { - if (driver && driver->ops.match) - return driver->ops.match(device, driver); - return acpi_match_ids(device, driver->ids); + struct acpi_device *acpi_dev = to_acpi_device(dev); + struct acpi_driver *acpi_drv = acpi_dev->driver; + + if (acpi_drv && acpi_drv->ops.shutdown) + acpi_drv->ops.shutdown(acpi_dev); + + return ; } static struct bus_type acpi_bus_type = { .name = "acpi", .suspend = acpi_device_suspend, .resume = acpi_device_resume, + .shutdown = acpi_device_shutdown, + .match = acpi_bus_match, + .probe = acpi_device_probe, + .remove = acpi_device_remove, + .uevent = acpi_device_uevent, }; static void acpi_device_register(struct acpi_device *device, @@ -449,7 +473,7 @@ static void acpi_driver_attach(struct acpi_driver *drv) continue; spin_unlock(&acpi_device_lock); - if (!acpi_bus_match(dev, drv)) { + if (!acpi_bus_match(&(dev->dev), &(drv->drv))) { if (!acpi_bus_driver_init(dev, drv)) { acpi_start_single_object(dev); atomic_inc(&drv->references); @@ -551,7 +575,7 @@ static int acpi_bus_find_driver(struct acpi_device *device) atomic_inc(&driver->references); spin_unlock(&acpi_device_lock); - if (!acpi_bus_match(device, driver)) { + if (!acpi_bus_match(&(device->dev), &(driver->drv))) { result = acpi_bus_driver_init(device, driver); if (!result) goto Done; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 5753d06b7860..3650654f878e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -82,7 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_remove(struct acpi_device *device, int type); -static int acpi_thermal_resume(struct acpi_device *device, int state); +static int acpi_thermal_resume(struct acpi_device *device); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); @@ -1356,7 +1356,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) return 0; } -static int acpi_thermal_resume(struct acpi_device *device, int state) +static int acpi_thermal_resume(struct acpi_device *device) { struct acpi_thermal *tz = NULL; int i; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a09538eb61e7..d7dd52615456 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -92,13 +92,14 @@ typedef int (*acpi_op_remove) (struct acpi_device * device, int type); typedef int (*acpi_op_lock) (struct acpi_device * device, int type); typedef int (*acpi_op_start) (struct acpi_device * device); typedef int (*acpi_op_stop) (struct acpi_device * device, int type); -typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); -typedef int (*acpi_op_resume) (struct acpi_device * device, int state); +typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state); +typedef int (*acpi_op_resume) (struct acpi_device * device); typedef int (*acpi_op_scan) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef int (*acpi_op_match) (struct acpi_device * device, struct acpi_driver * driver); +typedef int (*acpi_op_shutdown) (struct acpi_device * device); struct acpi_bus_ops { u32 acpi_op_add:1; @@ -112,7 +113,8 @@ struct acpi_bus_ops { u32 acpi_op_bind:1; u32 acpi_op_unbind:1; u32 acpi_op_match:1; - u32 reserved:21; + u32 acpi_op_shutdown:1; + u32 reserved:20; }; struct acpi_device_ops { @@ -127,6 +129,7 @@ struct acpi_device_ops { acpi_op_bind bind; acpi_op_unbind unbind; acpi_op_match match; + acpi_op_shutdown shutdown; }; struct acpi_driver { -- cgit v1.2.3 From 1890a97ab3f66d1e99768439f8067608b9b97fe3 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 7 Dec 2006 20:56:31 +0800 Subject: ACPI: change registration interface to follow driver model ACPI device/driver registration Interfaces are modified to follow Linux driver model. Signed-off-by: Li Shaohua Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 175 ++++++++---------------------------------------- include/acpi/acpi_bus.h | 3 +- 2 files changed, 30 insertions(+), 148 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 464746257d8e..b616e17de522 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -25,7 +25,7 @@ DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -static void acpi_device_release(struct kobject *kobj) +static void acpi_device_release_legacy(struct kobject *kobj) { struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); kfree(dev->pnp.cid_list); @@ -75,7 +75,7 @@ static struct sysfs_ops acpi_device_sysfs_ops = { static struct kobj_type ktype_acpi_ns = { .sysfs_ops = &acpi_device_sysfs_ops, - .release = acpi_device_release, + .release = acpi_device_release_legacy, }; static int namespace_uevent(struct kset *kset, struct kobject *kobj, @@ -222,6 +222,14 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) /* -------------------------------------------------------------------------- ACPI Bus operations -------------------------------------------------------------------------- */ +static void acpi_device_release(struct device *dev) +{ + struct acpi_device *acpi_dev = to_acpi_device(dev); + + kfree(acpi_dev->pnp.cid_list); + kfree(acpi_dev); +} + static int acpi_device_suspend(struct device *dev, pm_message_t state) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -377,6 +385,14 @@ static void acpi_device_register(struct acpi_device *device, printk(KERN_WARNING "%s: kobject_register error: %d\n", __FUNCTION__, err); create_sysfs_device_files(device); + + if (device->parent) + device->dev.parent = &parent->dev; + device->dev.bus = &acpi_bus_type; + device_initialize(&device->dev); + sprintf(device->dev.bus_id, "%s", device->pnp.bus_id); + device->dev.release = &acpi_device_release; + device_add(&device->dev); } static void acpi_device_unregister(struct acpi_device *device, int type) @@ -395,20 +411,20 @@ static void acpi_device_unregister(struct acpi_device *device, int type) acpi_detach_data(device->handle, acpi_bus_data_handler); remove_sysfs_device_files(device); kobject_unregister(&device->kobj); + + device_unregister(&device->dev); } /* -------------------------------------------------------------------------- Driver Management -------------------------------------------------------------------------- */ -static LIST_HEAD(acpi_bus_drivers); - /** * acpi_bus_driver_init - add a device to a driver * @device: the device to add and initialize * @driver: driver for the device * * Used to initialize a device via its device driver. Called whenever a - * driver is bound to a device. Invokes the driver's add() and start() ops. + * driver is bound to a device. Invokes the driver's add() ops. */ static int acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) @@ -459,57 +475,6 @@ static int acpi_start_single_object(struct acpi_device *device) return result; } -static void acpi_driver_attach(struct acpi_driver *drv) -{ - struct list_head *node, *next; - - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, g_list); - - if (dev->driver || !dev->status.present) - continue; - spin_unlock(&acpi_device_lock); - - if (!acpi_bus_match(&(dev->dev), &(drv->drv))) { - if (!acpi_bus_driver_init(dev, drv)) { - acpi_start_single_object(dev); - atomic_inc(&drv->references); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found driver [%s] for device [%s]\n", - drv->name, dev->pnp.bus_id)); - } - } - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); -} - -static void acpi_driver_detach(struct acpi_driver *drv) -{ - struct list_head *node, *next; - - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_device_list) { - struct acpi_device *dev = - container_of(node, struct acpi_device, g_list); - - if (dev->driver == drv) { - spin_unlock(&acpi_device_lock); - if (drv->ops.remove) - drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL); - spin_lock(&acpi_device_lock); - dev->driver = NULL; - dev->driver_data = NULL; - atomic_dec(&drv->references); - } - } - spin_unlock(&acpi_device_lock); -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -520,16 +485,16 @@ static void acpi_driver_detach(struct acpi_driver *drv) */ int acpi_bus_register_driver(struct acpi_driver *driver) { + int ret; if (acpi_disabled) return -ENODEV; + driver->drv.name = driver->name; + driver->drv.bus = &acpi_bus_type; + driver->drv.owner = driver->owner; - spin_lock(&acpi_device_lock); - list_add_tail(&driver->node, &acpi_bus_drivers); - spin_unlock(&acpi_device_lock); - acpi_driver_attach(driver); - - return 0; + ret = driver_register(&driver->drv); + return ret; } EXPORT_SYMBOL(acpi_bus_register_driver); @@ -543,52 +508,11 @@ EXPORT_SYMBOL(acpi_bus_register_driver); */ void acpi_bus_unregister_driver(struct acpi_driver *driver) { - acpi_driver_detach(driver); - - if (!atomic_read(&driver->references)) { - spin_lock(&acpi_device_lock); - list_del_init(&driver->node); - spin_unlock(&acpi_device_lock); - } - return; + driver_unregister(&driver->drv); } EXPORT_SYMBOL(acpi_bus_unregister_driver); -/** - * acpi_bus_find_driver - check if there is a driver installed for the device - * @device: device that we are trying to find a supporting driver for - * - * Parses the list of registered drivers looking for a driver applicable for - * the specified device. - */ -static int acpi_bus_find_driver(struct acpi_device *device) -{ - int result = 0; - struct list_head *node, *next; - - - spin_lock(&acpi_device_lock); - list_for_each_safe(node, next, &acpi_bus_drivers) { - struct acpi_driver *driver = - container_of(node, struct acpi_driver, node); - - atomic_inc(&driver->references); - spin_unlock(&acpi_device_lock); - if (!acpi_bus_match(&(device->dev), &(driver->drv))) { - result = acpi_bus_driver_init(device, driver); - if (!result) - goto Done; - } - atomic_dec(&driver->references); - spin_lock(&acpi_device_lock); - } - spin_unlock(&acpi_device_lock); - - Done: - return result; -} - /* -------------------------------------------------------------------------- Device Enumeration -------------------------------------------------------------------------- */ @@ -1033,32 +957,10 @@ static void acpi_device_get_debug_info(struct acpi_device *device, static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) { - int result = 0; - struct acpi_driver *driver; - - if (!dev) return -EINVAL; - driver = dev->driver; - - if ((driver) && (driver->ops.remove)) { - - if (driver->ops.stop) { - result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT); - if (result) - return result; - } - - result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT); - if (result) { - return result; - } - - atomic_dec(&dev->driver->references); - dev->driver = NULL; - acpi_driver_data(dev) = NULL; - } + device_release_driver(&dev->dev); if (!rmdevice) return 0; @@ -1193,17 +1095,6 @@ acpi_add_single_object(struct acpi_device **child, device->parent->ops.bind(device); } - /* - * Locate & Attach Driver - * ---------------------- - * If there's a hardware id (_HID) or compatible ids (_CID) we check - * to see if there's a driver installed for this kind of device. Note - * that drivers can install before or after a device is enumerated. - * - * TBD: Assumes LDM provides driver hot-plug capability. - */ - acpi_bus_find_driver(device); - end: if (!result) *child = device; @@ -1484,14 +1375,6 @@ static int __init acpi_scan_init(void) if (result) goto Done; - acpi_root->dev.bus = &acpi_bus_type; - snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); - result = device_register(&acpi_root->dev); - if (result) { - /* We don't want to quit even if we failed to add suspend/resume */ - printk(KERN_ERR PREFIX "Could not register device\n"); - } - /* * Enumerate devices in the ACPI namespace. */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index d7dd52615456..807acf69a704 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -133,13 +133,12 @@ struct acpi_device_ops { }; struct acpi_driver { - struct list_head node; char name[80]; char class[80]; - atomic_t references; char *ids; /* Supported Hardware IDs */ struct acpi_device_ops ops; struct device_driver drv; + struct module *owner; }; /* -- cgit v1.2.3 From f883d9db008deb20d4969c26475100cec2b7f6f8 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 7 Dec 2006 20:56:38 +0800 Subject: ACPI: convert to sysfs framework Setup new sysfs framework 1. Remove /sys/firmware/acpi 2. Add ACPI device in device tree. File "eject" for every device that has _EJ0 method is moved from /sys/firmware to /sys/devices. Operation on this file is exactly the same as before. i.e. echo 1 to "eject" will cause hot removal of this device. Corresponding changes should be made in userspace for hot removal. Signed-off-by: Li Shaohua Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 2 +- drivers/acpi/container.c | 6 +- drivers/acpi/processor_core.c | 8 +- drivers/acpi/scan.c | 187 +++++++++--------------------------------- include/acpi/acpi_bus.h | 1 - 5 files changed, 49 insertions(+), 155 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 279c4bac92e5..da471f647d07 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -195,7 +195,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", - device->kobj.name)); + device->dev.kobj.name)); return -ENODEV; } /* diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 871aa520ece7..914f56ae4b44 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -168,7 +168,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (ACPI_FAILURE(status) || !device) { result = container_device_add(&device, handle); if (!result) - kobject_uevent(&device->kobj, + kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); else printk("Failed to add container\n"); @@ -176,13 +176,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) } else { if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ - kobject_uevent(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); } } break; case ACPI_NOTIFY_EJECT_REQUEST: if (!acpi_bus_get_device(handle, &device) && device) { - kobject_uevent(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); } break; default: diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 1908e0d20222..46e72c388711 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -711,7 +711,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) return -ENODEV; if ((pr->id >= 0) && (pr->id < NR_CPUS)) { - kobject_uevent(&(*device)->kobj, KOBJ_ONLINE); + kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); } return 0; } @@ -749,13 +749,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) } if (pr->id >= 0 && (pr->id < NR_CPUS)) { - kobject_uevent(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { - kobject_uevent(&device->kobj, KOBJ_ONLINE); + kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); } else { printk(KERN_ERR PREFIX "Device [%s] failed to start\n", acpi_device_bid(device)); @@ -778,7 +778,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) } if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) - kobject_uevent(&device->kobj, KOBJ_OFFLINE); + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b616e17de522..97f6bbd6ef3c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -24,126 +24,6 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); - -static void acpi_device_release_legacy(struct kobject *kobj) -{ - struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); - kfree(dev->pnp.cid_list); - kfree(dev); -} - -struct acpi_device_attribute { - struct attribute attr; - ssize_t(*show) (struct acpi_device *, char *); - ssize_t(*store) (struct acpi_device *, const char *, size_t); -}; - -typedef void acpi_device_sysfs_files(struct kobject *, - const struct attribute *); - -static void setup_sys_fs_device_files(struct acpi_device *dev, - acpi_device_sysfs_files * func); - -#define create_sysfs_device_files(dev) \ - setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file) -#define remove_sysfs_device_files(dev) \ - setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file) - -#define to_acpi_dev(n) container_of(n, struct acpi_device, kobj) -#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr); - -static ssize_t acpi_device_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct acpi_device *device = to_acpi_dev(kobj); - struct acpi_device_attribute *attribute = to_handle_attr(attr); - return attribute->show ? attribute->show(device, buf) : -EIO; -} -static ssize_t acpi_device_attr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, - size_t len) -{ - struct acpi_device *device = to_acpi_dev(kobj); - struct acpi_device_attribute *attribute = to_handle_attr(attr); - return attribute->store ? attribute->store(device, buf, len) : -EIO; -} - -static struct sysfs_ops acpi_device_sysfs_ops = { - .show = acpi_device_attr_show, - .store = acpi_device_attr_store, -}; - -static struct kobj_type ktype_acpi_ns = { - .sysfs_ops = &acpi_device_sysfs_ops, - .release = acpi_device_release_legacy, -}; - -static int namespace_uevent(struct kset *kset, struct kobject *kobj, - char **envp, int num_envp, char *buffer, - int buffer_size) -{ - struct acpi_device *dev = to_acpi_dev(kobj); - int i = 0; - int len = 0; - - if (!dev->driver) - return 0; - - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, - "PHYSDEVDRIVER=%s", dev->driver->name)) - return -ENOMEM; - - envp[i] = NULL; - - return 0; -} - -static struct kset_uevent_ops namespace_uevent_ops = { - .uevent = &namespace_uevent, -}; - -static struct kset acpi_namespace_kset = { - .kobj = { - .name = "namespace", - }, - .subsys = &acpi_subsys, - .ktype = &ktype_acpi_ns, - .uevent_ops = &namespace_uevent_ops, -}; - -/* -------------------------------------------------------------------------- - ACPI sysfs device file support - -------------------------------------------------------------------------- */ -static ssize_t acpi_eject_store(struct acpi_device *device, - const char *buf, size_t count); - -#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \ -static struct acpi_device_attribute acpi_device_attr_##_name = \ - __ATTR(_name, _mode, _show, _store) - -ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); - -/** - * setup_sys_fs_device_files - sets up the device files under device namespace - * @dev: acpi_device object - * @func: function pointer to create or destroy the device file - */ -static void -setup_sys_fs_device_files(struct acpi_device *dev, - acpi_device_sysfs_files * func) -{ - acpi_status status; - acpi_handle temp = NULL; - - /* - * If device has _EJ0, 'eject' file is created that is used to trigger - * hot-removal function from userland. - */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr); -} - static int acpi_eject_operation(acpi_handle handle, int lockable) { struct acpi_object_list arg_list; @@ -180,7 +60,8 @@ static int acpi_eject_operation(acpi_handle handle, int lockable) } static ssize_t -acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) +acpi_eject_store(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) { int result; int ret = count; @@ -188,26 +69,27 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) acpi_status status; acpi_handle handle; acpi_object_type type = 0; + struct acpi_device *acpi_device = to_acpi_device(d); if ((!count) || (buf[0] != '1')) { return -EINVAL; } #ifndef FORCE_EJECT - if (device->driver == NULL) { + if (acpi_device->driver == NULL) { ret = -ENODEV; goto err; } #endif - status = acpi_get_type(device->handle, &type); - if (ACPI_FAILURE(status) || (!device->flags.ejectable)) { + status = acpi_get_type(acpi_device->handle, &type); + if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { ret = -ENODEV; goto err; } - islockable = device->flags.lockable; - handle = device->handle; + islockable = acpi_device->flags.lockable; + handle = acpi_device->handle; - result = acpi_bus_trim(device, 1); + result = acpi_bus_trim(acpi_device, 1); if (!result) result = acpi_eject_operation(handle, islockable); @@ -219,6 +101,35 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) return ret; } +static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); + +static void acpi_device_setup_files(struct acpi_device *dev) +{ + acpi_status status; + acpi_handle temp; + + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ + status = acpi_get_handle(dev->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) + device_create_file(&dev->dev, &dev_attr_eject); +} + +static void acpi_device_remove_files(struct acpi_device *dev) +{ + acpi_status status; + acpi_handle temp; + + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ + status = acpi_get_handle(dev->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) + device_remove_file(&dev->dev, &dev_attr_eject); +} /* -------------------------------------------------------------------------- ACPI Bus operations -------------------------------------------------------------------------- */ @@ -353,8 +264,6 @@ static struct bus_type acpi_bus_type = { static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { - int err; - /* * Linkage * ------- @@ -375,17 +284,6 @@ static void acpi_device_register(struct acpi_device *device, list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); spin_unlock(&acpi_device_lock); - strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN); - if (parent) - device->kobj.parent = &parent->kobj; - device->kobj.ktype = &ktype_acpi_ns; - device->kobj.kset = &acpi_namespace_kset; - err = kobject_register(&device->kobj); - if (err < 0) - printk(KERN_WARNING "%s: kobject_register error: %d\n", - __FUNCTION__, err); - create_sysfs_device_files(device); - if (device->parent) device->dev.parent = &parent->dev; device->dev.bus = &acpi_bus_type; @@ -393,6 +291,8 @@ static void acpi_device_register(struct acpi_device *device, sprintf(device->dev.bus_id, "%s", device->pnp.bus_id); device->dev.release = &acpi_device_release; device_add(&device->dev); + + acpi_device_setup_files(device); } static void acpi_device_unregister(struct acpi_device *device, int type) @@ -409,9 +309,8 @@ static void acpi_device_unregister(struct acpi_device *device, int type) spin_unlock(&acpi_device_lock); acpi_detach_data(device->handle, acpi_bus_data_handler); - remove_sysfs_device_files(device); - kobject_unregister(&device->kobj); + acpi_device_remove_files(device); device_unregister(&device->dev); } @@ -1353,10 +1252,6 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - result = kset_register(&acpi_namespace_kset); - if (result < 0) - printk(KERN_ERR PREFIX "kset_register error: %d\n", result); - result = bus_register(&acpi_bus_type); if (result) { /* We don't want to quit even if we failed to add suspend/resume */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 807acf69a704..598fab352814 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -299,7 +299,6 @@ struct acpi_device { struct acpi_device_ops ops; struct acpi_driver *driver; void *driver_data; - struct kobject kobj; struct device dev; }; -- cgit v1.2.3 From c4168bff32e218b8400cb48b48adb9b7f7bb31b8 Mon Sep 17 00:00:00 2001 From: Li Shaohua Date: Thu, 7 Dec 2006 20:56:41 +0800 Subject: ACPI: add acpi_bus_ops in acpi_device Add acpi_bus_ops in acpi_device to support acpi hot plug. NOTE: Two methods .add and .start in acpi_driver.ops are called separately to probe ACPI devices, while only .probe method is called in driver model. As executing .add and .start separately is critical for ACPI device hot plug, we use acpi_bus_ops to distinguish different code path. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 55 +++++++++++++++++++++++++------------------------ include/acpi/acpi_bus.h | 1 + 2 files changed, 29 insertions(+), 27 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 97f6bbd6ef3c..2a82645c9dfe 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -212,7 +212,8 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - acpi_start_single_object(acpi_dev); + if (acpi_dev->bus_ops.acpi_op_start) + acpi_start_single_object(acpi_dev); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", acpi_drv->name, acpi_dev->pnp.bus_id)); @@ -305,7 +306,6 @@ static void acpi_device_unregister(struct acpi_device *device, int type) list_del(&device->g_list); list_del(&device->wakeup_list); - spin_unlock(&acpi_device_lock); acpi_detach_data(device->handle, acpi_bus_data_handler); @@ -876,7 +876,8 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) static int acpi_add_single_object(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type) + struct acpi_device *parent, acpi_handle handle, int type, + struct acpi_bus_ops *ops) { int result = 0; struct acpi_device *device = NULL; @@ -894,6 +895,8 @@ acpi_add_single_object(struct acpi_device **child, device->handle = handle; device->parent = parent; + device->bus_ops = *ops; /* workround for not call .start */ + acpi_device_get_busid(device, handle, type); @@ -1079,14 +1082,14 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) if (ops->acpi_op_add) status = acpi_add_single_object(&child, parent, - chandle, type); + chandle, type, ops); else status = acpi_bus_get_device(chandle, &child); if (ACPI_FAILURE(status)) continue; - if (ops->acpi_op_start) { + if (ops->acpi_op_start && !(ops->acpi_op_add)) { status = acpi_start_single_object(child); if (ACPI_FAILURE(status)) continue; @@ -1124,13 +1127,13 @@ acpi_bus_add(struct acpi_device **child, int result; struct acpi_bus_ops ops; + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; - result = acpi_add_single_object(child, parent, handle, type); - if (!result) { - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + result = acpi_add_single_object(child, parent, handle, type, &ops); + if (!result) result = acpi_bus_scan(*child, &ops); - } + return result; } @@ -1216,28 +1219,30 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) { int result = 0; struct acpi_device *device = NULL; - + struct acpi_bus_ops ops; if (!root) return -ENODEV; + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + ops.acpi_op_start = 1; + /* * Enumerate all fixed-feature devices. */ if (acpi_fadt.pwr_button == 0) { result = acpi_add_single_object(&device, acpi_root, NULL, - ACPI_BUS_TYPE_POWER_BUTTON); - if (!result) - result = acpi_start_single_object(device); + ACPI_BUS_TYPE_POWER_BUTTON, + &ops); } if (acpi_fadt.sleep_button == 0) { result = acpi_add_single_object(&device, acpi_root, NULL, - ACPI_BUS_TYPE_SLEEP_BUTTON); - if (!result) - result = acpi_start_single_object(device); + ACPI_BUS_TYPE_SLEEP_BUTTON, + &ops); } return result; @@ -1252,6 +1257,10 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + ops.acpi_op_start = 1; + result = bus_register(&acpi_bus_type); if (result) { /* We don't want to quit even if we failed to add suspend/resume */ @@ -1262,11 +1271,7 @@ static int __init acpi_scan_init(void) * Create the root device in the bus's device tree */ result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, - ACPI_BUS_TYPE_SYSTEM); - if (result) - goto Done; - - result = acpi_start_single_object(acpi_root); + ACPI_BUS_TYPE_SYSTEM, &ops); if (result) goto Done; @@ -1274,12 +1279,8 @@ static int __init acpi_scan_init(void) * Enumerate devices in the ACPI namespace. */ result = acpi_bus_scan_fixed(acpi_root); - if (!result) { - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; + if (!result) result = acpi_bus_scan(acpi_root, &ops); - } if (result) acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 598fab352814..8976dbea63ca 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -300,6 +300,7 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; + struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ }; #define acpi_driver_data(d) ((d)->driver_data) -- cgit v1.2.3 From 96333578b023957537c3e98b50af7f3b7e08e411 Mon Sep 17 00:00:00 2001 From: Li Shaohua Date: Thu, 7 Dec 2006 20:56:46 +0800 Subject: ACPI: add acpi_bus_removal_type in acpi_device Add removal_type in structure acpi_device for hot removal. ACPI_BUS_REMOVAL_EJECT is used for ACPI device hot removal. Only one parameter is allowed in .remove method due to driver model. So removal_type is added to indicate different removal type. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 6 ++++-- include/acpi/acpi_bus.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2a82645c9dfe..06b86faf037f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -229,9 +229,9 @@ static int acpi_device_remove(struct device * dev) if (acpi_drv) { if (acpi_drv->ops.stop) - acpi_drv->ops.stop(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); + acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type); if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); + acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); } acpi_dev->driver = NULL; acpi_driver_data(dev) = NULL; @@ -294,6 +294,7 @@ static void acpi_device_register(struct acpi_device *device, device_add(&device->dev); acpi_device_setup_files(device); + device->removal_type = ACPI_BUS_REMOVAL_NORMAL; } static void acpi_device_unregister(struct acpi_device *device, int type) @@ -859,6 +860,7 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) if (!dev) return -EINVAL; + dev->removal_type = ACPI_BUS_REMOVAL_EJECT; device_release_driver(&dev->dev); if (!rmdevice) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 8976dbea63ca..58dc8f651861 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -301,6 +301,7 @@ struct acpi_device { void *driver_data; struct device dev; struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ + enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ }; #define acpi_driver_data(d) ((d)->driver_data) -- cgit v1.2.3 From ae8433324be16673c75951986dcf85f29c090557 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 7 Dec 2006 20:57:10 +0800 Subject: ACPI: Set fake hid for non-PNPID ACPI devices We do this mainly because: 1. hid is used to match ACPI devices and drivers. .match method which is incompatible to driver model can be deleted from acpi_driver.ops then. 2. As the .uevent method mark ACPI drivers by PNPID, fake hid is set to non-PNPID devices so that udev script can load the right ACPI driver by looking for "HWID = " or "COMPTID = ". Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/pci_bind.c | 20 ++------------- drivers/acpi/scan.c | 59 +++++++++++++++++++++++++++++++++++++++++++-- drivers/acpi/video.c | 37 +--------------------------- include/acpi/acpi_bus.h | 6 +---- include/acpi/acpi_drivers.h | 2 ++ 5 files changed, 63 insertions(+), 61 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index d83327468358..aa05e92464e6 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -379,32 +379,16 @@ acpi_pci_bind_root(struct acpi_device *device, static int acpi_pci_bridge_add(struct acpi_device *device); static int acpi_pci_bridge_remove(struct acpi_device *device, int type); -static int acpi_pci_bridge_match(struct acpi_device *device, - struct acpi_driver *driver); + static struct acpi_driver acpi_pci_bridge_driver = { .name = ACPI_PCI_BRIDGE_DRIVER_NAME, + .ids = ACPI_PCI_BRIDGE_HID, .ops = { .add = acpi_pci_bridge_add, .remove = acpi_pci_bridge_remove, - .match = acpi_pci_bridge_match, }, }; -static int acpi_pci_bridge_match(struct acpi_device *device, - struct acpi_driver *driver) -{ - acpi_status status; - acpi_handle handle; - - /* pci bridge has _PRT but isn't PNP0A03 */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_FAILURE(status)) - return -ENODEV; - if (!acpi_match_ids(device, "PNP0A03")) - return -ENODEV; - return 0; -} - static int acpi_pci_bridge_add(struct acpi_device *device) { return acpi_pci_bind(device); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c566c74e8a31..9efe3e9dbf21 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -166,8 +166,6 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - if (acpi_drv->ops.match) - return !acpi_drv->ops.match(acpi_dev, acpi_drv); return !acpi_match_ids(acpi_dev, acpi_drv->ids); } @@ -706,6 +704,53 @@ static void acpi_device_get_busid(struct acpi_device *device, } } +static int +acpi_video_bus_match(struct acpi_device *device) +{ + acpi_handle h_dummy1; + acpi_handle h_dummy2; + acpi_handle h_dummy3; + + + if (!device) + return -EINVAL; + + /* Since there is no HID, CID for ACPI Video drivers, we have + * to check well known required nodes for each feature we support. + */ + + /* Does this device able to support video switching ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) + return 0; + + /* Does this device able to retrieve a video ROM ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) + return 0; + + /* Does this device able to configure which video head to be POSTed ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) + return 0; + + return -ENODEV; +} + +static int acpi_pci_bridge_match(struct acpi_device *device) +{ + acpi_status status; + acpi_handle handle; + + /* pci bridge has _PRT but isn't PNP0A03 */ + status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); + if (ACPI_FAILURE(status)) + return -ENODEV; + if (!acpi_match_ids(device, "PNP0A03")) + return -ENODEV; + return 0; +} + static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) @@ -736,6 +781,16 @@ static void acpi_device_set_id(struct acpi_device *device, device->pnp.bus_address = info->address; device->flags.bus_address = 1; } + + if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ + status = acpi_video_bus_match(device); + if(ACPI_SUCCESS(status)) + hid = ACPI_VIDEO_HID; + + status = acpi_pci_bridge_match(device); + if(ACPI_SUCCESS(status)) + hid = ACPI_PCI_BRIDGE_HID; + } break; case ACPI_BUS_TYPE_POWER: hid = ACPI_POWER_HID; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 56666a982476..6e99eea689c8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -65,16 +65,14 @@ MODULE_LICENSE("GPL"); static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); -static int acpi_video_bus_match(struct acpi_device *device, - struct acpi_driver *driver); static struct acpi_driver acpi_video_bus = { .name = ACPI_VIDEO_DRIVER_NAME, .class = ACPI_VIDEO_CLASS, + .ids = ACPI_VIDEO_HID, .ops = { .add = acpi_video_bus_add, .remove = acpi_video_bus_remove, - .match = acpi_video_bus_match, }, }; @@ -1774,39 +1772,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } -static int -acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver) -{ - acpi_handle h_dummy1; - acpi_handle h_dummy2; - acpi_handle h_dummy3; - - - if (!device || !driver) - return -EINVAL; - - /* Since there is no HID, CID for ACPI Video drivers, we have - * to check well known required nodes for each feature we support. - */ - - /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) - return 0; - - /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) - return 0; - - /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) - return 0; - - return -ENODEV; -} - static int __init acpi_video_init(void) { int result = 0; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 58dc8f651861..a6b4037beeae 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -97,8 +97,6 @@ typedef int (*acpi_op_resume) (struct acpi_device * device); typedef int (*acpi_op_scan) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); -typedef int (*acpi_op_match) (struct acpi_device * device, - struct acpi_driver * driver); typedef int (*acpi_op_shutdown) (struct acpi_device * device); struct acpi_bus_ops { @@ -112,9 +110,8 @@ struct acpi_bus_ops { u32 acpi_op_scan:1; u32 acpi_op_bind:1; u32 acpi_op_unbind:1; - u32 acpi_op_match:1; u32 acpi_op_shutdown:1; - u32 reserved:20; + u32 reserved:21; }; struct acpi_device_ops { @@ -128,7 +125,6 @@ struct acpi_device_ops { acpi_op_scan scan; acpi_op_bind bind; acpi_op_unbind unbind; - acpi_op_match match; acpi_op_shutdown shutdown; }; diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 6a5bdcefec64..be67750ec88b 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -43,6 +43,8 @@ #define ACPI_BUTTON_HID_POWERF "ACPI_FPB" #define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" +#define ACPI_VIDEO_HID "ACPI_VID" +#define ACPI_PCI_BRIDGE_HID "ACPI_PCI" /* -------------------------------------------------------------------------- PCI -------------------------------------------------------------------------- */ -- cgit v1.2.3 From bb0958544f3c7c016b2a3025ab3694363e403aa1 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 4 Jan 2007 15:03:18 +0800 Subject: ACPI: use more understandable bus_id for ACPI devices Some of the ACPI devices use the internal fake hids which are exposed to userspace as devces' bus_id after sysfs conversion. To make it more friendly, we convert them to more understandable strings. For those devices w/o PNPids, we use "device:instance_no" as the bus_id instead of "PNPIDNON:instance_no". Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/scan.c | 6 +++--- include/acpi/acpi_bus.h | 2 +- include/acpi/acpi_drivers.h | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 30a39baeac51..4139e65d0ff5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -26,7 +26,7 @@ DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); struct acpi_device_bus_id{ - char bus_id[9]; + char bus_id[15]; unsigned int instance_no; struct list_head node; }; @@ -342,7 +342,7 @@ static int acpi_device_register(struct acpi_device *device, * If failed, create one and link it into acpi_bus_id_list */ list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) { - if(!strcmp(acpi_device_bus_id->bus_id, device->flags.hardware_id? device->pnp.hardware_id : "PNPIDNON")) { + if(!strcmp(acpi_device_bus_id->bus_id, device->flags.hardware_id? device->pnp.hardware_id : "device")) { acpi_device_bus_id->instance_no ++; found = 1; kfree(new_bus_id); @@ -351,7 +351,7 @@ static int acpi_device_register(struct acpi_device *device, } if(!found) { acpi_device_bus_id = new_bus_id; - strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "PNPIDNON"); + strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); acpi_device_bus_id->instance_no = 0; list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a6b4037beeae..e7df8423d15c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -184,7 +184,7 @@ struct acpi_device_dir { typedef char acpi_bus_id[5]; typedef unsigned long acpi_bus_address; -typedef char acpi_hardware_id[9]; +typedef char acpi_hardware_id[15]; typedef char acpi_unique_id[9]; typedef char acpi_device_name[40]; typedef char acpi_device_class[20]; diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 2781e6628645..1b18c36da789 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -36,14 +36,14 @@ /* _HID definitions */ -#define ACPI_POWER_HID "ACPI_PWR" -#define ACPI_PROCESSOR_HID "ACPI_CPU" -#define ACPI_SYSTEM_HID "ACPI_SYS" -#define ACPI_THERMAL_HID "ACPI_THM" -#define ACPI_BUTTON_HID_POWERF "ACPI_FPB" -#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" - -#define ACPI_VIDEO_HID "ACPI_VID" +#define ACPI_POWER_HID "power_resource" +#define ACPI_PROCESSOR_HID "processor" +#define ACPI_SYSTEM_HID "acpi_system" +#define ACPI_THERMAL_HID "thermal" +#define ACPI_BUTTON_HID_POWERF "button_power" +#define ACPI_BUTTON_HID_SLEEPF "button_sleep" +#define ACPI_VIDEO_HID "video" +#define ACPI_BAY_HID "bay" /* -------------------------------------------------------------------------- PCI -------------------------------------------------------------------------- */ -- cgit v1.2.3