diff options
author | Patrick Mochel <mochel@linux.intel.com> | 2006-12-07 07:56:27 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-12-15 23:38:34 -0500 |
commit | 5d9464a46918ced087c351a10f38cee95725f85b (patch) | |
tree | acb45582f9c43a867a60cc5fa8ae2c6197dc1d2d | |
parent | d43ec68e9837dfa6618ab473622683fdbf6e68a9 (diff) |
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 <shaohua.li@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/battery.c | 4 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 8 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 158 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 4 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 9 |
5 files changed, 105 insertions, 78 deletions
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); | |||
64 | 64 | ||
65 | static int acpi_battery_add(struct acpi_device *device); | 65 | static int acpi_battery_add(struct acpi_device *device); |
66 | static int acpi_battery_remove(struct acpi_device *device, int type); | 66 | static int acpi_battery_remove(struct acpi_device *device, int type); |
67 | static int acpi_battery_resume(struct acpi_device *device, int status); | 67 | static int acpi_battery_resume(struct acpi_device *device); |
68 | 68 | ||
69 | static struct acpi_driver acpi_battery_driver = { | 69 | static struct acpi_driver acpi_battery_driver = { |
70 | .name = ACPI_BATTERY_DRIVER_NAME, | 70 | .name = ACPI_BATTERY_DRIVER_NAME, |
@@ -756,7 +756,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
756 | } | 756 | } |
757 | 757 | ||
758 | /* this is needed to learn about changes made in suspended state */ | 758 | /* this is needed to learn about changes made in suspended state */ |
759 | static int acpi_battery_resume(struct acpi_device *device, int state) | 759 | static int acpi_battery_resume(struct acpi_device *device) |
760 | { | 760 | { |
761 | struct acpi_battery *battery; | 761 | struct acpi_battery *battery; |
762 | 762 | ||
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"); | |||
48 | 48 | ||
49 | static int acpi_fan_add(struct acpi_device *device); | 49 | static int acpi_fan_add(struct acpi_device *device); |
50 | static int acpi_fan_remove(struct acpi_device *device, int type); | 50 | static int acpi_fan_remove(struct acpi_device *device, int type); |
51 | static int acpi_fan_suspend(struct acpi_device *device, int state); | 51 | static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); |
52 | static int acpi_fan_resume(struct acpi_device *device, int state); | 52 | static int acpi_fan_resume(struct acpi_device *device); |
53 | 53 | ||
54 | static struct acpi_driver acpi_fan_driver = { | 54 | static struct acpi_driver acpi_fan_driver = { |
55 | .name = ACPI_FAN_DRIVER_NAME, | 55 | .name = ACPI_FAN_DRIVER_NAME, |
@@ -238,7 +238,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int acpi_fan_suspend(struct acpi_device *device, int state) | 241 | static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) |
242 | { | 242 | { |
243 | if (!device) | 243 | if (!device) |
244 | return -EINVAL; | 244 | return -EINVAL; |
@@ -248,7 +248,7 @@ static int acpi_fan_suspend(struct acpi_device *device, int state) | |||
248 | return AE_OK; | 248 | return AE_OK; |
249 | } | 249 | } |
250 | 250 | ||
251 | static int acpi_fan_resume(struct acpi_device *device, int state) | 251 | static int acpi_fan_resume(struct acpi_device *device) |
252 | { | 252 | { |
253 | int result = 0; | 253 | int result = 0; |
254 | int power_state = 0; | 254 | 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) | |||
222 | /* -------------------------------------------------------------------------- | 222 | /* -------------------------------------------------------------------------- |
223 | ACPI Bus operations | 223 | ACPI Bus operations |
224 | -------------------------------------------------------------------------- */ | 224 | -------------------------------------------------------------------------- */ |
225 | static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) | 225 | static int acpi_device_suspend(struct device *dev, pm_message_t state) |
226 | { | 226 | { |
227 | struct acpi_device * dev, * next; | 227 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
228 | int result; | 228 | struct acpi_driver *acpi_drv = acpi_dev->driver; |
229 | 229 | ||
230 | spin_lock(&acpi_device_lock); | 230 | if (acpi_drv && acpi_drv->ops.suspend) |
231 | list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | 231 | return acpi_drv->ops.suspend(acpi_dev, state); |
232 | if (dev->driver && dev->driver->ops.suspend) { | ||
233 | spin_unlock(&acpi_device_lock); | ||
234 | result = dev->driver->ops.suspend(dev, 0); | ||
235 | if (result) { | ||
236 | printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||
237 | acpi_device_name(dev), | ||
238 | acpi_device_bid(dev), result); | ||
239 | } | ||
240 | spin_lock(&acpi_device_lock); | ||
241 | } | ||
242 | } | ||
243 | spin_unlock(&acpi_device_lock); | ||
244 | return 0; | 232 | return 0; |
245 | } | 233 | } |
246 | 234 | ||
247 | static int acpi_device_suspend(struct device * dev, pm_message_t state) | 235 | static int acpi_device_resume(struct device *dev) |
248 | { | 236 | { |
249 | struct acpi_device * acpi_dev = to_acpi_device(dev); | 237 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
238 | struct acpi_driver *acpi_drv = acpi_dev->driver; | ||
250 | 239 | ||
251 | /* | 240 | if (acpi_drv && acpi_drv->ops.resume) |
252 | * For now, we should only register 1 generic device - | 241 | return acpi_drv->ops.resume(acpi_dev); |
253 | * the ACPI root device - and from there, we walk the | ||
254 | * tree of ACPI devices to suspend each one using the | ||
255 | * ACPI driver methods. | ||
256 | */ | ||
257 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
258 | root_suspend(acpi_dev, state); | ||
259 | return 0; | 242 | return 0; |
260 | } | 243 | } |
261 | 244 | ||
262 | static int root_resume(struct acpi_device * acpi_dev) | 245 | static int acpi_bus_match(struct device *dev, struct device_driver *drv) |
263 | { | 246 | { |
264 | struct acpi_device * dev, * next; | 247 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
265 | int result; | 248 | struct acpi_driver *acpi_drv = to_acpi_driver(drv); |
266 | 249 | ||
267 | spin_lock(&acpi_device_lock); | 250 | if (acpi_drv->ops.match) |
268 | list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | 251 | return !acpi_drv->ops.match(acpi_dev, acpi_drv); |
269 | if (dev->driver && dev->driver->ops.resume) { | 252 | return !acpi_match_ids(acpi_dev, acpi_drv->ids); |
270 | spin_unlock(&acpi_device_lock); | 253 | } |
271 | result = dev->driver->ops.resume(dev, 0); | 254 | |
272 | if (result) { | 255 | static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, |
273 | printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | 256 | char *buffer, int buffer_size) |
274 | acpi_device_name(dev), | 257 | { |
275 | acpi_device_bid(dev), result); | 258 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
276 | } | 259 | int i = 0, length = 0, ret = 0; |
277 | spin_lock(&acpi_device_lock); | 260 | |
261 | if (acpi_dev->flags.hardware_id) | ||
262 | ret = add_uevent_var(envp, num_envp, &i, | ||
263 | buffer, buffer_size, &length, | ||
264 | "HWID=%s", acpi_dev->pnp.hardware_id); | ||
265 | if (ret) | ||
266 | return -ENOMEM; | ||
267 | if (acpi_dev->flags.compatible_ids) { | ||
268 | int j; | ||
269 | struct acpi_compatible_id_list *cid_list; | ||
270 | |||
271 | cid_list = acpi_dev->pnp.cid_list; | ||
272 | |||
273 | for (j = 0; j < cid_list->count; j++) { | ||
274 | ret = add_uevent_var(envp, num_envp, &i, buffer, | ||
275 | buffer_size, &length, "COMPTID=%s", | ||
276 | cid_list->id[j].value); | ||
277 | if (ret) | ||
278 | return -ENOMEM; | ||
278 | } | 279 | } |
279 | } | 280 | } |
280 | spin_unlock(&acpi_device_lock); | 281 | |
282 | envp[i] = NULL; | ||
281 | return 0; | 283 | return 0; |
282 | } | 284 | } |
283 | 285 | ||
284 | static int acpi_device_resume(struct device * dev) | 286 | static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); |
287 | static int acpi_start_single_object(struct acpi_device *); | ||
288 | static int acpi_device_probe(struct device * dev) | ||
285 | { | 289 | { |
286 | struct acpi_device * acpi_dev = to_acpi_device(dev); | 290 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
291 | struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); | ||
292 | int ret; | ||
293 | |||
294 | ret = acpi_bus_driver_init(acpi_dev, acpi_drv); | ||
295 | if (!ret) { | ||
296 | acpi_start_single_object(acpi_dev); | ||
297 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
298 | "Found driver [%s] for device [%s]\n", | ||
299 | acpi_drv->name, acpi_dev->pnp.bus_id)); | ||
300 | get_device(dev); | ||
301 | } | ||
302 | return ret; | ||
303 | } | ||
287 | 304 | ||
288 | /* | 305 | static int acpi_device_remove(struct device * dev) |
289 | * For now, we should only register 1 generic device - | 306 | { |
290 | * the ACPI root device - and from there, we walk the | 307 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
291 | * tree of ACPI devices to resume each one using the | 308 | struct acpi_driver *acpi_drv = acpi_dev->driver; |
292 | * ACPI driver methods. | 309 | |
293 | */ | 310 | if (acpi_drv) { |
294 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | 311 | if (acpi_drv->ops.stop) |
295 | root_resume(acpi_dev); | 312 | acpi_drv->ops.stop(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); |
313 | if (acpi_drv->ops.remove) | ||
314 | acpi_drv->ops.remove(acpi_dev, ACPI_BUS_REMOVAL_NORMAL); | ||
315 | } | ||
316 | acpi_dev->driver = NULL; | ||
317 | acpi_driver_data(dev) = NULL; | ||
318 | |||
319 | put_device(dev); | ||
296 | return 0; | 320 | return 0; |
297 | } | 321 | } |
298 | 322 | ||
299 | /** | 323 | static void acpi_device_shutdown(struct device *dev) |
300 | * acpi_bus_match - match device IDs to driver's supported IDs | ||
301 | * @device: the device that we are trying to match to a driver | ||
302 | * @driver: driver whose device id table is being checked | ||
303 | * | ||
304 | * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it | ||
305 | * matches the specified driver's criteria. | ||
306 | */ | ||
307 | static int | ||
308 | acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver) | ||
309 | { | 324 | { |
310 | if (driver && driver->ops.match) | 325 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
311 | return driver->ops.match(device, driver); | 326 | struct acpi_driver *acpi_drv = acpi_dev->driver; |
312 | return acpi_match_ids(device, driver->ids); | 327 | |
328 | if (acpi_drv && acpi_drv->ops.shutdown) | ||
329 | acpi_drv->ops.shutdown(acpi_dev); | ||
330 | |||
331 | return ; | ||
313 | } | 332 | } |
314 | 333 | ||
315 | static struct bus_type acpi_bus_type = { | 334 | static struct bus_type acpi_bus_type = { |
316 | .name = "acpi", | 335 | .name = "acpi", |
317 | .suspend = acpi_device_suspend, | 336 | .suspend = acpi_device_suspend, |
318 | .resume = acpi_device_resume, | 337 | .resume = acpi_device_resume, |
338 | .shutdown = acpi_device_shutdown, | ||
339 | .match = acpi_bus_match, | ||
340 | .probe = acpi_device_probe, | ||
341 | .remove = acpi_device_remove, | ||
342 | .uevent = acpi_device_uevent, | ||
319 | }; | 343 | }; |
320 | 344 | ||
321 | static void acpi_device_register(struct acpi_device *device, | 345 | static void acpi_device_register(struct acpi_device *device, |
@@ -449,7 +473,7 @@ static void acpi_driver_attach(struct acpi_driver *drv) | |||
449 | continue; | 473 | continue; |
450 | spin_unlock(&acpi_device_lock); | 474 | spin_unlock(&acpi_device_lock); |
451 | 475 | ||
452 | if (!acpi_bus_match(dev, drv)) { | 476 | if (!acpi_bus_match(&(dev->dev), &(drv->drv))) { |
453 | if (!acpi_bus_driver_init(dev, drv)) { | 477 | if (!acpi_bus_driver_init(dev, drv)) { |
454 | acpi_start_single_object(dev); | 478 | acpi_start_single_object(dev); |
455 | atomic_inc(&drv->references); | 479 | atomic_inc(&drv->references); |
@@ -551,7 +575,7 @@ static int acpi_bus_find_driver(struct acpi_device *device) | |||
551 | 575 | ||
552 | atomic_inc(&driver->references); | 576 | atomic_inc(&driver->references); |
553 | spin_unlock(&acpi_device_lock); | 577 | spin_unlock(&acpi_device_lock); |
554 | if (!acpi_bus_match(device, driver)) { | 578 | if (!acpi_bus_match(&(device->dev), &(driver->drv))) { |
555 | result = acpi_bus_driver_init(device, driver); | 579 | result = acpi_bus_driver_init(device, driver); |
556 | if (!result) | 580 | if (!result) |
557 | goto Done; | 581 | 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"); | |||
82 | 82 | ||
83 | static int acpi_thermal_add(struct acpi_device *device); | 83 | static int acpi_thermal_add(struct acpi_device *device); |
84 | static int acpi_thermal_remove(struct acpi_device *device, int type); | 84 | static int acpi_thermal_remove(struct acpi_device *device, int type); |
85 | static int acpi_thermal_resume(struct acpi_device *device, int state); | 85 | static int acpi_thermal_resume(struct acpi_device *device); |
86 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); | 86 | static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); |
87 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); | 87 | static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); |
88 | static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); | 88 | 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) | |||
1356 | return 0; | 1356 | return 0; |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | static int acpi_thermal_resume(struct acpi_device *device, int state) | 1359 | static int acpi_thermal_resume(struct acpi_device *device) |
1360 | { | 1360 | { |
1361 | struct acpi_thermal *tz = NULL; | 1361 | struct acpi_thermal *tz = NULL; |
1362 | int i; | 1362 | 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); | |||
92 | typedef int (*acpi_op_lock) (struct acpi_device * device, int type); | 92 | typedef int (*acpi_op_lock) (struct acpi_device * device, int type); |
93 | typedef int (*acpi_op_start) (struct acpi_device * device); | 93 | typedef int (*acpi_op_start) (struct acpi_device * device); |
94 | typedef int (*acpi_op_stop) (struct acpi_device * device, int type); | 94 | typedef int (*acpi_op_stop) (struct acpi_device * device, int type); |
95 | typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); | 95 | typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state); |
96 | typedef int (*acpi_op_resume) (struct acpi_device * device, int state); | 96 | typedef int (*acpi_op_resume) (struct acpi_device * device); |
97 | typedef int (*acpi_op_scan) (struct acpi_device * device); | 97 | typedef int (*acpi_op_scan) (struct acpi_device * device); |
98 | typedef int (*acpi_op_bind) (struct acpi_device * device); | 98 | typedef int (*acpi_op_bind) (struct acpi_device * device); |
99 | typedef int (*acpi_op_unbind) (struct acpi_device * device); | 99 | typedef int (*acpi_op_unbind) (struct acpi_device * device); |
100 | typedef int (*acpi_op_match) (struct acpi_device * device, | 100 | typedef int (*acpi_op_match) (struct acpi_device * device, |
101 | struct acpi_driver * driver); | 101 | struct acpi_driver * driver); |
102 | typedef int (*acpi_op_shutdown) (struct acpi_device * device); | ||
102 | 103 | ||
103 | struct acpi_bus_ops { | 104 | struct acpi_bus_ops { |
104 | u32 acpi_op_add:1; | 105 | u32 acpi_op_add:1; |
@@ -112,7 +113,8 @@ struct acpi_bus_ops { | |||
112 | u32 acpi_op_bind:1; | 113 | u32 acpi_op_bind:1; |
113 | u32 acpi_op_unbind:1; | 114 | u32 acpi_op_unbind:1; |
114 | u32 acpi_op_match:1; | 115 | u32 acpi_op_match:1; |
115 | u32 reserved:21; | 116 | u32 acpi_op_shutdown:1; |
117 | u32 reserved:20; | ||
116 | }; | 118 | }; |
117 | 119 | ||
118 | struct acpi_device_ops { | 120 | struct acpi_device_ops { |
@@ -127,6 +129,7 @@ struct acpi_device_ops { | |||
127 | acpi_op_bind bind; | 129 | acpi_op_bind bind; |
128 | acpi_op_unbind unbind; | 130 | acpi_op_unbind unbind; |
129 | acpi_op_match match; | 131 | acpi_op_match match; |
132 | acpi_op_shutdown shutdown; | ||
130 | }; | 133 | }; |
131 | 134 | ||
132 | struct acpi_driver { | 135 | struct acpi_driver { |