diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/acpi/button.c | 223 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 132 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 343 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 20 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 41 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 4 |
7 files changed, 435 insertions, 329 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 6f8c50ea54e1..b0897a0b206c 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -97,6 +97,7 @@ config ACPI_BATTERY | |||
97 | 97 | ||
98 | config ACPI_BUTTON | 98 | config ACPI_BUTTON |
99 | tristate "Button" | 99 | tristate "Button" |
100 | depends on INPUT | ||
100 | default y | 101 | default y |
101 | help | 102 | help |
102 | This driver handles events on the power, sleep and lid buttons. | 103 | This driver handles events on the power, sleep and lid buttons. |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 5ef885e82c78..ac860583c203 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/input.h> | ||
32 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
33 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
34 | 35 | ||
@@ -62,7 +63,7 @@ | |||
62 | #define _COMPONENT ACPI_BUTTON_COMPONENT | 63 | #define _COMPONENT ACPI_BUTTON_COMPONENT |
63 | ACPI_MODULE_NAME("acpi_button") | 64 | ACPI_MODULE_NAME("acpi_button") |
64 | 65 | ||
65 | MODULE_AUTHOR("Paul Diefenbaugh"); | 66 | MODULE_AUTHOR("Paul Diefenbaugh"); |
66 | MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); | 67 | MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); |
67 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
68 | 69 | ||
@@ -78,12 +79,14 @@ static struct acpi_driver acpi_button_driver = { | |||
78 | .ops = { | 79 | .ops = { |
79 | .add = acpi_button_add, | 80 | .add = acpi_button_add, |
80 | .remove = acpi_button_remove, | 81 | .remove = acpi_button_remove, |
81 | }, | 82 | }, |
82 | }; | 83 | }; |
83 | 84 | ||
84 | struct acpi_button { | 85 | struct acpi_button { |
85 | struct acpi_device *device; /* Fixed button kludge */ | 86 | struct acpi_device *device; /* Fixed button kludge */ |
86 | u8 type; | 87 | unsigned int type; |
88 | struct input_dev *input; | ||
89 | char phys[32]; /* for input device */ | ||
87 | unsigned long pushed; | 90 | unsigned long pushed; |
88 | }; | 91 | }; |
89 | 92 | ||
@@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir; | |||
109 | 112 | ||
110 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) | 113 | static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) |
111 | { | 114 | { |
112 | struct acpi_button *button = (struct acpi_button *)seq->private; | 115 | struct acpi_button *button = seq->private; |
113 | |||
114 | 116 | ||
115 | if (!button || !button->device) | 117 | if (!button || !button->device) |
116 | return 0; | 118 | return 0; |
@@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file) | |||
128 | 130 | ||
129 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | 131 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) |
130 | { | 132 | { |
131 | struct acpi_button *button = (struct acpi_button *)seq->private; | 133 | struct acpi_button *button = seq->private; |
132 | acpi_status status; | 134 | acpi_status status; |
133 | unsigned long state; | 135 | unsigned long state; |
134 | 136 | ||
135 | |||
136 | if (!button || !button->device) | 137 | if (!button || !button->device) |
137 | return 0; | 138 | return 0; |
138 | 139 | ||
139 | status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state); | 140 | status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state); |
140 | if (ACPI_FAILURE(status)) { | 141 | seq_printf(seq, "state: %s\n", |
141 | seq_printf(seq, "state: unsupported\n"); | 142 | ACPI_FAILURE(status) ? "unsupported" : |
142 | } else { | 143 | (state ? "open" : "closed")); |
143 | seq_printf(seq, "state: %s\n", | ||
144 | (state ? "open" : "closed")); | ||
145 | } | ||
146 | |||
147 | return 0; | 144 | return 0; |
148 | } | 145 | } |
149 | 146 | ||
@@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir; | |||
159 | static int acpi_button_add_fs(struct acpi_device *device) | 156 | static int acpi_button_add_fs(struct acpi_device *device) |
160 | { | 157 | { |
161 | struct proc_dir_entry *entry = NULL; | 158 | struct proc_dir_entry *entry = NULL; |
162 | struct acpi_button *button = NULL; | 159 | struct acpi_button *button; |
163 | |||
164 | 160 | ||
165 | if (!device || !acpi_driver_data(device)) | 161 | if (!device || !acpi_driver_data(device)) |
166 | return -EINVAL; | 162 | return -EINVAL; |
@@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device) | |||
228 | 224 | ||
229 | static int acpi_button_remove_fs(struct acpi_device *device) | 225 | static int acpi_button_remove_fs(struct acpi_device *device) |
230 | { | 226 | { |
231 | struct acpi_button *button = NULL; | 227 | struct acpi_button *button = acpi_driver_data(device); |
232 | |||
233 | 228 | ||
234 | button = acpi_driver_data(device); | ||
235 | if (acpi_device_dir(device)) { | 229 | if (acpi_device_dir(device)) { |
236 | if (button->type == ACPI_BUTTON_TYPE_LID) | 230 | if (button->type == ACPI_BUTTON_TYPE_LID) |
237 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, | 231 | remove_proc_entry(ACPI_BUTTON_FILE_STATE, |
@@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device) | |||
253 | 247 | ||
254 | static void acpi_button_notify(acpi_handle handle, u32 event, void *data) | 248 | static void acpi_button_notify(acpi_handle handle, u32 event, void *data) |
255 | { | 249 | { |
256 | struct acpi_button *button = (struct acpi_button *)data; | 250 | struct acpi_button *button = data; |
257 | 251 | struct input_dev *input; | |
258 | 252 | ||
259 | if (!button || !button->device) | 253 | if (!button || !button->device) |
260 | return; | 254 | return; |
261 | 255 | ||
262 | switch (event) { | 256 | switch (event) { |
263 | case ACPI_BUTTON_NOTIFY_STATUS: | 257 | case ACPI_BUTTON_NOTIFY_STATUS: |
258 | input = button->input; | ||
259 | |||
260 | if (button->type == ACPI_BUTTON_TYPE_LID) { | ||
261 | struct acpi_handle *handle = button->device->handle; | ||
262 | unsigned long state; | ||
263 | |||
264 | if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID", | ||
265 | NULL, &state))) | ||
266 | input_report_switch(input, SW_LID, !state); | ||
267 | |||
268 | } else { | ||
269 | int keycode = test_bit(KEY_SLEEP, input->keybit) ? | ||
270 | KEY_SLEEP : KEY_POWER; | ||
271 | |||
272 | input_report_key(input, keycode, 1); | ||
273 | input_sync(input); | ||
274 | input_report_key(input, keycode, 0); | ||
275 | } | ||
276 | input_sync(input); | ||
277 | |||
264 | acpi_bus_generate_event(button->device, event, | 278 | acpi_bus_generate_event(button->device, event, |
265 | ++button->pushed); | 279 | ++button->pushed); |
266 | break; | 280 | break; |
@@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) | |||
275 | 289 | ||
276 | static acpi_status acpi_button_notify_fixed(void *data) | 290 | static acpi_status acpi_button_notify_fixed(void *data) |
277 | { | 291 | { |
278 | struct acpi_button *button = (struct acpi_button *)data; | 292 | struct acpi_button *button = data; |
279 | |||
280 | 293 | ||
281 | if (!button) | 294 | if (!button) |
282 | return AE_BAD_PARAMETER; | 295 | return AE_BAD_PARAMETER; |
@@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data) | |||
286 | return AE_OK; | 299 | return AE_OK; |
287 | } | 300 | } |
288 | 301 | ||
289 | static int acpi_button_add(struct acpi_device *device) | 302 | static int acpi_button_install_notify_handlers(struct acpi_button *button) |
290 | { | 303 | { |
291 | int result = 0; | 304 | acpi_status status; |
292 | acpi_status status = AE_OK; | ||
293 | struct acpi_button *button = NULL; | ||
294 | 305 | ||
306 | switch (button->type) { | ||
307 | case ACPI_BUTTON_TYPE_POWERF: | ||
308 | status = | ||
309 | acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, | ||
310 | acpi_button_notify_fixed, | ||
311 | button); | ||
312 | break; | ||
313 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
314 | status = | ||
315 | acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, | ||
316 | acpi_button_notify_fixed, | ||
317 | button); | ||
318 | break; | ||
319 | default: | ||
320 | status = acpi_install_notify_handler(button->device->handle, | ||
321 | ACPI_DEVICE_NOTIFY, | ||
322 | acpi_button_notify, | ||
323 | button); | ||
324 | break; | ||
325 | } | ||
326 | |||
327 | return ACPI_FAILURE(status) ? -ENODEV : 0; | ||
328 | } | ||
329 | |||
330 | static void acpi_button_remove_notify_handlers(struct acpi_button *button) | ||
331 | { | ||
332 | switch (button->type) { | ||
333 | case ACPI_BUTTON_TYPE_POWERF: | ||
334 | acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, | ||
335 | acpi_button_notify_fixed); | ||
336 | break; | ||
337 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
338 | acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, | ||
339 | acpi_button_notify_fixed); | ||
340 | break; | ||
341 | default: | ||
342 | acpi_remove_notify_handler(button->device->handle, | ||
343 | ACPI_DEVICE_NOTIFY, | ||
344 | acpi_button_notify); | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static int acpi_button_add(struct acpi_device *device) | ||
350 | { | ||
351 | int error; | ||
352 | struct acpi_button *button; | ||
353 | struct input_dev *input; | ||
295 | 354 | ||
296 | if (!device) | 355 | if (!device) |
297 | return -EINVAL; | 356 | return -EINVAL; |
298 | 357 | ||
299 | button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL); | 358 | button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); |
300 | if (!button) | 359 | if (!button) |
301 | return -ENOMEM; | 360 | return -ENOMEM; |
302 | memset(button, 0, sizeof(struct acpi_button)); | ||
303 | 361 | ||
304 | button->device = device; | 362 | button->device = device; |
305 | acpi_driver_data(device) = button; | 363 | acpi_driver_data(device) = button; |
306 | 364 | ||
365 | button->input = input = input_allocate_device(); | ||
366 | if (!input) { | ||
367 | error = -ENOMEM; | ||
368 | goto err_free_button; | ||
369 | } | ||
370 | |||
307 | /* | 371 | /* |
308 | * Determine the button type (via hid), as fixed-feature buttons | 372 | * Determine the button type (via hid), as fixed-feature buttons |
309 | * need to be handled a bit differently than generic-space. | 373 | * need to be handled a bit differently than generic-space. |
@@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device) | |||
338 | } else { | 402 | } else { |
339 | printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", | 403 | printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", |
340 | acpi_device_hid(device)); | 404 | acpi_device_hid(device)); |
341 | result = -ENODEV; | 405 | error = -ENODEV; |
342 | goto end; | 406 | goto err_free_input; |
343 | } | 407 | } |
344 | 408 | ||
345 | result = acpi_button_add_fs(device); | 409 | error = acpi_button_add_fs(device); |
346 | if (result) | 410 | if (error) |
347 | goto end; | 411 | goto err_free_input; |
412 | |||
413 | error = acpi_button_install_notify_handlers(button); | ||
414 | if (error) | ||
415 | goto err_remove_fs; | ||
416 | |||
417 | snprintf(button->phys, sizeof(button->phys), | ||
418 | "%s/button/input0", acpi_device_hid(device)); | ||
419 | |||
420 | input->name = acpi_device_name(device); | ||
421 | input->phys = button->phys; | ||
422 | input->id.bustype = BUS_HOST; | ||
423 | input->id.product = button->type; | ||
348 | 424 | ||
349 | switch (button->type) { | 425 | switch (button->type) { |
426 | case ACPI_BUTTON_TYPE_POWER: | ||
350 | case ACPI_BUTTON_TYPE_POWERF: | 427 | case ACPI_BUTTON_TYPE_POWERF: |
351 | status = | 428 | input->evbit[0] = BIT(EV_KEY); |
352 | acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, | 429 | set_bit(KEY_POWER, input->keybit); |
353 | acpi_button_notify_fixed, | ||
354 | button); | ||
355 | break; | 430 | break; |
431 | |||
432 | case ACPI_BUTTON_TYPE_SLEEP: | ||
356 | case ACPI_BUTTON_TYPE_SLEEPF: | 433 | case ACPI_BUTTON_TYPE_SLEEPF: |
357 | status = | 434 | input->evbit[0] = BIT(EV_KEY); |
358 | acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, | 435 | set_bit(KEY_SLEEP, input->keybit); |
359 | acpi_button_notify_fixed, | ||
360 | button); | ||
361 | break; | 436 | break; |
362 | default: | 437 | |
363 | status = acpi_install_notify_handler(device->handle, | 438 | case ACPI_BUTTON_TYPE_LID: |
364 | ACPI_DEVICE_NOTIFY, | 439 | input->evbit[0] = BIT(EV_SW); |
365 | acpi_button_notify, | 440 | set_bit(SW_LID, input->swbit); |
366 | button); | ||
367 | break; | 441 | break; |
368 | } | 442 | } |
369 | 443 | ||
370 | if (ACPI_FAILURE(status)) { | 444 | error = input_register_device(input); |
371 | result = -ENODEV; | 445 | if (error) |
372 | goto end; | 446 | goto err_remove_handlers; |
373 | } | ||
374 | 447 | ||
375 | if (device->wakeup.flags.valid) { | 448 | if (device->wakeup.flags.valid) { |
376 | /* Button's GPE is run-wake GPE */ | 449 | /* Button's GPE is run-wake GPE */ |
@@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device) | |||
385 | printk(KERN_INFO PREFIX "%s [%s]\n", | 458 | printk(KERN_INFO PREFIX "%s [%s]\n", |
386 | acpi_device_name(device), acpi_device_bid(device)); | 459 | acpi_device_name(device), acpi_device_bid(device)); |
387 | 460 | ||
388 | end: | 461 | return 0; |
389 | if (result) { | ||
390 | acpi_button_remove_fs(device); | ||
391 | kfree(button); | ||
392 | } | ||
393 | 462 | ||
394 | return result; | 463 | err_remove_handlers: |
464 | acpi_button_remove_notify_handlers(button); | ||
465 | err_remove_fs: | ||
466 | acpi_button_remove_fs(device); | ||
467 | err_free_input: | ||
468 | input_free_device(input); | ||
469 | err_free_button: | ||
470 | kfree(button); | ||
471 | return error; | ||
395 | } | 472 | } |
396 | 473 | ||
397 | static int acpi_button_remove(struct acpi_device *device, int type) | 474 | static int acpi_button_remove(struct acpi_device *device, int type) |
398 | { | 475 | { |
399 | acpi_status status = 0; | 476 | struct acpi_button *button; |
400 | struct acpi_button *button = NULL; | ||
401 | |||
402 | 477 | ||
403 | if (!device || !acpi_driver_data(device)) | 478 | if (!device || !acpi_driver_data(device)) |
404 | return -EINVAL; | 479 | return -EINVAL; |
405 | 480 | ||
406 | button = acpi_driver_data(device); | 481 | button = acpi_driver_data(device); |
407 | 482 | ||
408 | /* Unregister for device notifications. */ | 483 | acpi_button_remove_notify_handlers(button); |
409 | switch (button->type) { | ||
410 | case ACPI_BUTTON_TYPE_POWERF: | ||
411 | status = | ||
412 | acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, | ||
413 | acpi_button_notify_fixed); | ||
414 | break; | ||
415 | case ACPI_BUTTON_TYPE_SLEEPF: | ||
416 | status = | ||
417 | acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, | ||
418 | acpi_button_notify_fixed); | ||
419 | break; | ||
420 | default: | ||
421 | status = acpi_remove_notify_handler(device->handle, | ||
422 | ACPI_DEVICE_NOTIFY, | ||
423 | acpi_button_notify); | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | acpi_button_remove_fs(device); | 484 | acpi_button_remove_fs(device); |
428 | 485 | input_unregister_device(button->input); | |
429 | kfree(button); | 486 | kfree(button); |
430 | 487 | ||
431 | return 0; | 488 | return 0; |
@@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
433 | 490 | ||
434 | static int __init acpi_button_init(void) | 491 | static int __init acpi_button_init(void) |
435 | { | 492 | { |
436 | int result = 0; | 493 | int result; |
437 | |||
438 | 494 | ||
439 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | 495 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); |
440 | if (!acpi_button_dir) | 496 | if (!acpi_button_dir) |
@@ -451,7 +507,6 @@ static int __init acpi_button_init(void) | |||
451 | 507 | ||
452 | static void __exit acpi_button_exit(void) | 508 | static void __exit acpi_button_exit(void) |
453 | { | 509 | { |
454 | |||
455 | acpi_bus_unregister_driver(&acpi_button_driver); | 510 | acpi_bus_unregister_driver(&acpi_button_driver); |
456 | 511 | ||
457 | if (acpi_power_dir) | 512 | if (acpi_power_dir) |
@@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void) | |||
461 | if (acpi_lid_dir) | 516 | if (acpi_lid_dir) |
462 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); | 517 | remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); |
463 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | 518 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); |
464 | |||
465 | return; | ||
466 | } | 519 | } |
467 | 520 | ||
468 | module_init(acpi_button_init); | 521 | module_init(acpi_button_init); |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 578b99b71d9c..215f5b30a1f1 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/jiffies.h> | ||
30 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
31 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
32 | 34 | ||
@@ -38,6 +40,8 @@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME); | |||
38 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
39 | 41 | ||
40 | static struct atomic_notifier_head dock_notifier_list; | 42 | static struct atomic_notifier_head dock_notifier_list; |
43 | static struct platform_device dock_device; | ||
44 | static char dock_device_name[] = "dock"; | ||
41 | 45 | ||
42 | struct dock_station { | 46 | struct dock_station { |
43 | acpi_handle handle; | 47 | acpi_handle handle; |
@@ -322,10 +326,12 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) | |||
322 | 326 | ||
323 | static void dock_event(struct dock_station *ds, u32 event, int num) | 327 | static void dock_event(struct dock_station *ds, u32 event, int num) |
324 | { | 328 | { |
329 | struct device *dev = &dock_device.dev; | ||
325 | /* | 330 | /* |
326 | * we don't do events until someone tells me that | 331 | * Indicate that the status of the dock station has |
327 | * they would like to have them. | 332 | * changed. |
328 | */ | 333 | */ |
334 | kobject_uevent(&dev->kobj, KOBJ_CHANGE); | ||
329 | } | 335 | } |
330 | 336 | ||
331 | /** | 337 | /** |
@@ -440,6 +446,9 @@ static int dock_in_progress(struct dock_station *ds) | |||
440 | */ | 446 | */ |
441 | int register_dock_notifier(struct notifier_block *nb) | 447 | int register_dock_notifier(struct notifier_block *nb) |
442 | { | 448 | { |
449 | if (!dock_station) | ||
450 | return -ENODEV; | ||
451 | |||
443 | return atomic_notifier_chain_register(&dock_notifier_list, nb); | 452 | return atomic_notifier_chain_register(&dock_notifier_list, nb); |
444 | } | 453 | } |
445 | 454 | ||
@@ -451,6 +460,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier); | |||
451 | */ | 460 | */ |
452 | void unregister_dock_notifier(struct notifier_block *nb) | 461 | void unregister_dock_notifier(struct notifier_block *nb) |
453 | { | 462 | { |
463 | if (!dock_station) | ||
464 | return; | ||
465 | |||
454 | atomic_notifier_chain_unregister(&dock_notifier_list, nb); | 466 | atomic_notifier_chain_unregister(&dock_notifier_list, nb); |
455 | } | 467 | } |
456 | 468 | ||
@@ -511,6 +523,37 @@ void unregister_hotplug_dock_device(acpi_handle handle) | |||
511 | EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); | 523 | EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); |
512 | 524 | ||
513 | /** | 525 | /** |
526 | * handle_eject_request - handle an undock request checking for error conditions | ||
527 | * | ||
528 | * Check to make sure the dock device is still present, then undock and | ||
529 | * hotremove all the devices that may need removing. | ||
530 | */ | ||
531 | static int handle_eject_request(struct dock_station *ds, u32 event) | ||
532 | { | ||
533 | if (!dock_present(ds)) | ||
534 | return -ENODEV; | ||
535 | |||
536 | if (dock_in_progress(ds)) | ||
537 | return -EBUSY; | ||
538 | |||
539 | /* | ||
540 | * here we need to generate the undock | ||
541 | * event prior to actually doing the undock | ||
542 | * so that the device struct still exists. | ||
543 | */ | ||
544 | dock_event(ds, event, UNDOCK_EVENT); | ||
545 | hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); | ||
546 | undock(ds); | ||
547 | eject_dock(ds); | ||
548 | if (dock_present(ds)) { | ||
549 | printk(KERN_ERR PREFIX "Unable to undock!\n"); | ||
550 | return -EBUSY; | ||
551 | } | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | /** | ||
514 | * dock_notify - act upon an acpi dock notification | 557 | * dock_notify - act upon an acpi dock notification |
515 | * @handle: the dock station handle | 558 | * @handle: the dock station handle |
516 | * @event: the acpi event | 559 | * @event: the acpi event |
@@ -518,9 +561,7 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); | |||
518 | * | 561 | * |
519 | * If we are notified to dock, then check to see if the dock is | 562 | * If we are notified to dock, then check to see if the dock is |
520 | * present and then dock. Notify all drivers of the dock event, | 563 | * present and then dock. Notify all drivers of the dock event, |
521 | * and then hotplug and devices that may need hotplugging. For undock | 564 | * and then hotplug and devices that may need hotplugging. |
522 | * check to make sure the dock device is still present, then undock | ||
523 | * and hotremove all the devices that may need removing. | ||
524 | */ | 565 | */ |
525 | static void dock_notify(acpi_handle handle, u32 event, void *data) | 566 | static void dock_notify(acpi_handle handle, u32 event, void *data) |
526 | { | 567 | { |
@@ -552,19 +593,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
552 | * to the driver who wish to hotplug. | 593 | * to the driver who wish to hotplug. |
553 | */ | 594 | */ |
554 | case ACPI_NOTIFY_EJECT_REQUEST: | 595 | case ACPI_NOTIFY_EJECT_REQUEST: |
555 | if (!dock_in_progress(ds) && dock_present(ds)) { | 596 | handle_eject_request(ds, event); |
556 | /* | ||
557 | * here we need to generate the undock | ||
558 | * event prior to actually doing the undock | ||
559 | * so that the device struct still exists. | ||
560 | */ | ||
561 | dock_event(ds, event, UNDOCK_EVENT); | ||
562 | hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); | ||
563 | undock(ds); | ||
564 | eject_dock(ds); | ||
565 | if (dock_present(ds)) | ||
566 | printk(KERN_ERR PREFIX "Unable to undock!\n"); | ||
567 | } | ||
568 | break; | 597 | break; |
569 | default: | 598 | default: |
570 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); | 599 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); |
@@ -603,6 +632,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
603 | return AE_OK; | 632 | return AE_OK; |
604 | } | 633 | } |
605 | 634 | ||
635 | /* | ||
636 | * show_docked - read method for "docked" file in sysfs | ||
637 | */ | ||
638 | static ssize_t show_docked(struct device *dev, | ||
639 | struct device_attribute *attr, char *buf) | ||
640 | { | ||
641 | return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); | ||
642 | |||
643 | } | ||
644 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); | ||
645 | |||
646 | /* | ||
647 | * write_undock - write method for "undock" file in sysfs | ||
648 | */ | ||
649 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | ||
650 | const char *buf, size_t count) | ||
651 | { | ||
652 | int ret; | ||
653 | |||
654 | if (!count) | ||
655 | return -EINVAL; | ||
656 | |||
657 | ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); | ||
658 | return ret ? ret: count; | ||
659 | } | ||
660 | DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); | ||
661 | |||
606 | /** | 662 | /** |
607 | * dock_add - add a new dock station | 663 | * dock_add - add a new dock station |
608 | * @handle: the dock station handle | 664 | * @handle: the dock station handle |
@@ -628,6 +684,30 @@ static int dock_add(acpi_handle handle) | |||
628 | spin_lock_init(&dock_station->hp_lock); | 684 | spin_lock_init(&dock_station->hp_lock); |
629 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); | 685 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); |
630 | 686 | ||
687 | /* initialize platform device stuff */ | ||
688 | dock_device.name = dock_device_name; | ||
689 | ret = platform_device_register(&dock_device); | ||
690 | if (ret) { | ||
691 | printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); | ||
692 | kfree(dock_station); | ||
693 | return ret; | ||
694 | } | ||
695 | ret = device_create_file(&dock_device.dev, &dev_attr_docked); | ||
696 | if (ret) { | ||
697 | printk("Error %d adding sysfs file\n", ret); | ||
698 | platform_device_unregister(&dock_device); | ||
699 | kfree(dock_station); | ||
700 | return ret; | ||
701 | } | ||
702 | ret = device_create_file(&dock_device.dev, &dev_attr_undock); | ||
703 | if (ret) { | ||
704 | printk("Error %d adding sysfs file\n", ret); | ||
705 | device_remove_file(&dock_device.dev, &dev_attr_docked); | ||
706 | platform_device_unregister(&dock_device); | ||
707 | kfree(dock_station); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
631 | /* Find dependent devices */ | 711 | /* Find dependent devices */ |
632 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 712 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
633 | ACPI_UINT32_MAX, find_dock_devices, dock_station, | 713 | ACPI_UINT32_MAX, find_dock_devices, dock_station, |
@@ -637,7 +717,8 @@ static int dock_add(acpi_handle handle) | |||
637 | dd = alloc_dock_dependent_device(handle); | 717 | dd = alloc_dock_dependent_device(handle); |
638 | if (!dd) { | 718 | if (!dd) { |
639 | kfree(dock_station); | 719 | kfree(dock_station); |
640 | return -ENOMEM; | 720 | ret = -ENOMEM; |
721 | goto dock_add_err_unregister; | ||
641 | } | 722 | } |
642 | add_dock_dependent_device(dock_station, dd); | 723 | add_dock_dependent_device(dock_station, dd); |
643 | 724 | ||
@@ -657,8 +738,12 @@ static int dock_add(acpi_handle handle) | |||
657 | return 0; | 738 | return 0; |
658 | 739 | ||
659 | dock_add_err: | 740 | dock_add_err: |
660 | kfree(dock_station); | ||
661 | kfree(dd); | 741 | kfree(dd); |
742 | dock_add_err_unregister: | ||
743 | device_remove_file(&dock_device.dev, &dev_attr_docked); | ||
744 | device_remove_file(&dock_device.dev, &dev_attr_undock); | ||
745 | platform_device_unregister(&dock_device); | ||
746 | kfree(dock_station); | ||
662 | return ret; | 747 | return ret; |
663 | } | 748 | } |
664 | 749 | ||
@@ -685,6 +770,11 @@ static int dock_remove(void) | |||
685 | if (ACPI_FAILURE(status)) | 770 | if (ACPI_FAILURE(status)) |
686 | printk(KERN_ERR "Error removing notify handler\n"); | 771 | printk(KERN_ERR "Error removing notify handler\n"); |
687 | 772 | ||
773 | /* cleanup sysfs */ | ||
774 | device_remove_file(&dock_device.dev, &dev_attr_docked); | ||
775 | device_remove_file(&dock_device.dev, &dev_attr_undock); | ||
776 | platform_device_unregister(&dock_device); | ||
777 | |||
688 | /* free dock station memory */ | 778 | /* free dock station memory */ |
689 | kfree(dock_station); | 779 | kfree(dock_station); |
690 | return 0; | 780 | return 0; |
@@ -725,7 +815,7 @@ static int __init dock_init(void) | |||
725 | ACPI_UINT32_MAX, find_dock, &num, NULL); | 815 | ACPI_UINT32_MAX, find_dock, &num, NULL); |
726 | 816 | ||
727 | if (!num) | 817 | if (!num) |
728 | return -ENODEV; | 818 | printk(KERN_INFO "No dock devices found.\n"); |
729 | 819 | ||
730 | return 0; | 820 | return 0; |
731 | } | 821 | } |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e6d4b084dca2..d713f769b72d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -45,35 +45,34 @@ ACPI_MODULE_NAME("acpi_ec") | |||
45 | #define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" | 45 | #define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" |
46 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" | 46 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" |
47 | #define ACPI_EC_FILE_INFO "info" | 47 | #define ACPI_EC_FILE_INFO "info" |
48 | 48 | #undef PREFIX | |
49 | #define PREFIX "ACPI: EC: " | ||
49 | /* EC status register */ | 50 | /* EC status register */ |
50 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 51 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
51 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 52 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
52 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | 53 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ |
53 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 54 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
54 | |||
55 | /* EC commands */ | 55 | /* EC commands */ |
56 | #define ACPI_EC_COMMAND_READ 0x80 | 56 | enum ec_command { |
57 | #define ACPI_EC_COMMAND_WRITE 0x81 | 57 | ACPI_EC_COMMAND_READ = 0x80, |
58 | #define ACPI_EC_BURST_ENABLE 0x82 | 58 | ACPI_EC_COMMAND_WRITE = 0x81, |
59 | #define ACPI_EC_BURST_DISABLE 0x83 | 59 | ACPI_EC_BURST_ENABLE = 0x82, |
60 | #define ACPI_EC_COMMAND_QUERY 0x84 | 60 | ACPI_EC_BURST_DISABLE = 0x83, |
61 | 61 | ACPI_EC_COMMAND_QUERY = 0x84, | |
62 | }; | ||
62 | /* EC events */ | 63 | /* EC events */ |
63 | enum { | 64 | enum ec_event { |
64 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ | 65 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ |
65 | ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ | 66 | ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ |
66 | }; | 67 | }; |
67 | 68 | ||
68 | #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ | 69 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
69 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 70 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
70 | #define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ | ||
71 | #define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ | ||
72 | 71 | ||
73 | enum { | 72 | static enum ec_mode { |
74 | EC_INTR = 1, /* Output buffer full */ | 73 | EC_INTR = 1, /* Output buffer full */ |
75 | EC_POLL, /* Input buffer empty */ | 74 | EC_POLL, /* Input buffer empty */ |
76 | }; | 75 | } acpi_ec_mode = EC_INTR; |
77 | 76 | ||
78 | static int acpi_ec_remove(struct acpi_device *device, int type); | 77 | static int acpi_ec_remove(struct acpi_device *device, int type); |
79 | static int acpi_ec_start(struct acpi_device *device); | 78 | static int acpi_ec_start(struct acpi_device *device); |
@@ -96,19 +95,18 @@ static struct acpi_driver acpi_ec_driver = { | |||
96 | struct acpi_ec { | 95 | struct acpi_ec { |
97 | acpi_handle handle; | 96 | acpi_handle handle; |
98 | unsigned long uid; | 97 | unsigned long uid; |
99 | unsigned long gpe_bit; | 98 | unsigned long gpe; |
100 | unsigned long command_addr; | 99 | unsigned long command_addr; |
101 | unsigned long data_addr; | 100 | unsigned long data_addr; |
102 | unsigned long global_lock; | 101 | unsigned long global_lock; |
103 | struct semaphore sem; | 102 | struct mutex lock; |
104 | unsigned int expect_event; | 103 | atomic_t query_pending; |
105 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ | 104 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ |
106 | wait_queue_head_t wait; | 105 | wait_queue_head_t wait; |
107 | } *ec_ecdt; | 106 | } *ec_ecdt; |
108 | 107 | ||
109 | /* External interfaces use first EC only, so remember */ | 108 | /* External interfaces use first EC only, so remember */ |
110 | static struct acpi_device *first_ec; | 109 | static struct acpi_device *first_ec; |
111 | static int acpi_ec_mode = EC_INTR; | ||
112 | 110 | ||
113 | /* -------------------------------------------------------------------------- | 111 | /* -------------------------------------------------------------------------- |
114 | Transaction Management | 112 | Transaction Management |
@@ -134,54 +132,41 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | |||
134 | outb(data, ec->data_addr); | 132 | outb(data, ec->data_addr); |
135 | } | 133 | } |
136 | 134 | ||
137 | static int acpi_ec_check_status(u8 status, u8 event) | 135 | static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) |
138 | { | 136 | { |
139 | switch (event) { | 137 | u8 status = acpi_ec_read_status(ec); |
140 | case ACPI_EC_EVENT_OBF_1: | 138 | |
139 | if (event == ACPI_EC_EVENT_OBF_1) { | ||
141 | if (status & ACPI_EC_FLAG_OBF) | 140 | if (status & ACPI_EC_FLAG_OBF) |
142 | return 1; | 141 | return 1; |
143 | break; | 142 | } else if (event == ACPI_EC_EVENT_IBF_0) { |
144 | case ACPI_EC_EVENT_IBF_0: | ||
145 | if (!(status & ACPI_EC_FLAG_IBF)) | 143 | if (!(status & ACPI_EC_FLAG_IBF)) |
146 | return 1; | 144 | return 1; |
147 | break; | ||
148 | default: | ||
149 | break; | ||
150 | } | 145 | } |
151 | 146 | ||
152 | return 0; | 147 | return 0; |
153 | } | 148 | } |
154 | 149 | ||
155 | static int acpi_ec_wait(struct acpi_ec *ec, u8 event) | 150 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event) |
156 | { | 151 | { |
157 | int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; | 152 | if (acpi_ec_mode == EC_POLL) { |
158 | long time_left; | 153 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
159 | 154 | while (time_before(jiffies, delay)) { | |
160 | ec->expect_event = event; | 155 | if (acpi_ec_check_status(ec, event)) |
161 | if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { | ||
162 | ec->expect_event = 0; | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | do { | ||
167 | if (acpi_ec_mode == EC_POLL) { | ||
168 | udelay(ACPI_EC_UDELAY); | ||
169 | } else { | ||
170 | time_left = wait_event_timeout(ec->wait, | ||
171 | !ec->expect_event, | ||
172 | msecs_to_jiffies(ACPI_EC_DELAY)); | ||
173 | if (time_left > 0) { | ||
174 | ec->expect_event = 0; | ||
175 | return 0; | 156 | return 0; |
176 | } | ||
177 | } | 157 | } |
178 | if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { | 158 | } else { |
179 | ec->expect_event = 0; | 159 | if (wait_event_timeout(ec->wait, |
160 | acpi_ec_check_status(ec, event), | ||
161 | msecs_to_jiffies(ACPI_EC_DELAY)) || | ||
162 | acpi_ec_check_status(ec, event)) { | ||
180 | return 0; | 163 | return 0; |
164 | } else { | ||
165 | printk(KERN_ERR PREFIX "acpi_ec_wait timeout," | ||
166 | " status = %d, expect_event = %d\n", | ||
167 | acpi_ec_read_status(ec), event); | ||
181 | } | 168 | } |
182 | } while (--i > 0); | 169 | } |
183 | |||
184 | ec->expect_event = 0; | ||
185 | 170 | ||
186 | return -ETIME; | 171 | return -ETIME; |
187 | } | 172 | } |
@@ -196,7 +181,6 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec) | |||
196 | u8 tmp = 0; | 181 | u8 tmp = 0; |
197 | u8 status = 0; | 182 | u8 status = 0; |
198 | 183 | ||
199 | |||
200 | status = acpi_ec_read_status(ec); | 184 | status = acpi_ec_read_status(ec); |
201 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { | 185 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { |
202 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 186 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
@@ -212,7 +196,7 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec) | |||
212 | 196 | ||
213 | atomic_set(&ec->leaving_burst, 0); | 197 | atomic_set(&ec->leaving_burst, 0); |
214 | return 0; | 198 | return 0; |
215 | end: | 199 | end: |
216 | ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); | 200 | ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); |
217 | return -1; | 201 | return -1; |
218 | } | 202 | } |
@@ -221,58 +205,68 @@ int acpi_ec_leave_burst_mode(struct acpi_ec *ec) | |||
221 | { | 205 | { |
222 | u8 status = 0; | 206 | u8 status = 0; |
223 | 207 | ||
224 | |||
225 | status = acpi_ec_read_status(ec); | 208 | status = acpi_ec_read_status(ec); |
226 | if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ | 209 | if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) { |
227 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 210 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
228 | if(status) | 211 | if (status) |
229 | goto end; | 212 | goto end; |
230 | acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE); | 213 | acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE); |
231 | acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 214 | acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
232 | } | 215 | } |
233 | atomic_set(&ec->leaving_burst, 1); | 216 | atomic_set(&ec->leaving_burst, 1); |
234 | return 0; | 217 | return 0; |
235 | end: | 218 | end: |
236 | ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode")); | 219 | ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode")); |
237 | return -1; | 220 | return -1; |
238 | } | 221 | } |
239 | #endif /* ACPI_FUTURE_USAGE */ | 222 | #endif /* ACPI_FUTURE_USAGE */ |
240 | 223 | ||
241 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | 224 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, |
242 | const u8 *wdata, unsigned wdata_len, | 225 | const u8 * wdata, unsigned wdata_len, |
243 | u8 *rdata, unsigned rdata_len) | 226 | u8 * rdata, unsigned rdata_len) |
244 | { | 227 | { |
245 | int result; | 228 | int result = 0; |
246 | 229 | ||
247 | acpi_ec_write_cmd(ec, command); | 230 | acpi_ec_write_cmd(ec, command); |
248 | 231 | ||
249 | for (; wdata_len > 0; wdata_len --) { | 232 | for (; wdata_len > 0; --wdata_len) { |
250 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 233 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
251 | if (result) | 234 | if (result) { |
252 | return result; | 235 | printk(KERN_ERR PREFIX |
236 | "write_cmd timeout, command = %d\n", command); | ||
237 | goto end; | ||
238 | } | ||
253 | acpi_ec_write_data(ec, *(wdata++)); | 239 | acpi_ec_write_data(ec, *(wdata++)); |
254 | } | 240 | } |
255 | 241 | ||
256 | if (command == ACPI_EC_COMMAND_WRITE) { | 242 | if (!rdata_len) { |
257 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 243 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
258 | if (result) | 244 | if (result) { |
259 | return result; | 245 | printk(KERN_ERR PREFIX |
246 | "finish-write timeout, command = %d\n", command); | ||
247 | goto end; | ||
248 | } | ||
249 | } else if (command == ACPI_EC_COMMAND_QUERY) { | ||
250 | atomic_set(&ec->query_pending, 0); | ||
260 | } | 251 | } |
261 | 252 | ||
262 | for (; rdata_len > 0; rdata_len --) { | 253 | for (; rdata_len > 0; --rdata_len) { |
263 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); | 254 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); |
264 | if (result) | 255 | if (result) { |
265 | return result; | 256 | printk(KERN_ERR PREFIX "read timeout, command = %d\n", |
257 | command); | ||
258 | goto end; | ||
259 | } | ||
266 | 260 | ||
267 | *(rdata++) = acpi_ec_read_data(ec); | 261 | *(rdata++) = acpi_ec_read_data(ec); |
268 | } | 262 | } |
269 | 263 | end: | |
270 | return 0; | 264 | return result; |
271 | } | 265 | } |
272 | 266 | ||
273 | static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | 267 | static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, |
274 | const u8 *wdata, unsigned wdata_len, | 268 | const u8 * wdata, unsigned wdata_len, |
275 | u8 *rdata, unsigned rdata_len) | 269 | u8 * rdata, unsigned rdata_len) |
276 | { | 270 | { |
277 | int status; | 271 | int status; |
278 | u32 glk; | 272 | u32 glk; |
@@ -280,36 +274,40 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
280 | if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) | 274 | if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) |
281 | return -EINVAL; | 275 | return -EINVAL; |
282 | 276 | ||
283 | if (rdata) | 277 | if (rdata) |
284 | memset(rdata, 0, rdata_len); | 278 | memset(rdata, 0, rdata_len); |
285 | 279 | ||
280 | mutex_lock(&ec->lock); | ||
286 | if (ec->global_lock) { | 281 | if (ec->global_lock) { |
287 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 282 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
288 | if (ACPI_FAILURE(status)) | 283 | if (ACPI_FAILURE(status)) |
289 | return -ENODEV; | 284 | return -ENODEV; |
290 | } | 285 | } |
291 | down(&ec->sem); | 286 | |
287 | /* Make sure GPE is enabled before doing transaction */ | ||
288 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | ||
292 | 289 | ||
293 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 290 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
294 | if (status) { | 291 | if (status) { |
295 | printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); | 292 | printk(KERN_DEBUG PREFIX |
293 | "input buffer is not empty, aborting transaction\n"); | ||
296 | goto end; | 294 | goto end; |
297 | } | 295 | } |
298 | 296 | ||
299 | status = acpi_ec_transaction_unlocked(ec, command, | 297 | status = acpi_ec_transaction_unlocked(ec, command, |
300 | wdata, wdata_len, | 298 | wdata, wdata_len, |
301 | rdata, rdata_len); | 299 | rdata, rdata_len); |
302 | 300 | ||
303 | end: | 301 | end: |
304 | up(&ec->sem); | ||
305 | 302 | ||
306 | if (ec->global_lock) | 303 | if (ec->global_lock) |
307 | acpi_release_global_lock(glk); | 304 | acpi_release_global_lock(glk); |
305 | mutex_unlock(&ec->lock); | ||
308 | 306 | ||
309 | return status; | 307 | return status; |
310 | } | 308 | } |
311 | 309 | ||
312 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) | 310 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) |
313 | { | 311 | { |
314 | int result; | 312 | int result; |
315 | u8 d; | 313 | u8 d; |
@@ -322,15 +320,15 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) | |||
322 | 320 | ||
323 | static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) | 321 | static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) |
324 | { | 322 | { |
325 | u8 wdata[2] = { address, data }; | 323 | u8 wdata[2] = { address, data }; |
326 | return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, | 324 | return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, |
327 | wdata, 2, NULL, 0); | 325 | wdata, 2, NULL, 0); |
328 | } | 326 | } |
329 | 327 | ||
330 | /* | 328 | /* |
331 | * Externally callable EC access functions. For now, assume 1 EC only | 329 | * Externally callable EC access functions. For now, assume 1 EC only |
332 | */ | 330 | */ |
333 | int ec_read(u8 addr, u8 *val) | 331 | int ec_read(u8 addr, u8 * val) |
334 | { | 332 | { |
335 | struct acpi_ec *ec; | 333 | struct acpi_ec *ec; |
336 | int err; | 334 | int err; |
@@ -370,8 +368,8 @@ int ec_write(u8 addr, u8 val) | |||
370 | EXPORT_SYMBOL(ec_write); | 368 | EXPORT_SYMBOL(ec_write); |
371 | 369 | ||
372 | extern int ec_transaction(u8 command, | 370 | extern int ec_transaction(u8 command, |
373 | const u8 *wdata, unsigned wdata_len, | 371 | const u8 * wdata, unsigned wdata_len, |
374 | u8 *rdata, unsigned rdata_len) | 372 | u8 * rdata, unsigned rdata_len) |
375 | { | 373 | { |
376 | struct acpi_ec *ec; | 374 | struct acpi_ec *ec; |
377 | 375 | ||
@@ -386,65 +384,49 @@ extern int ec_transaction(u8 command, | |||
386 | 384 | ||
387 | EXPORT_SYMBOL(ec_transaction); | 385 | EXPORT_SYMBOL(ec_transaction); |
388 | 386 | ||
389 | static int acpi_ec_query(struct acpi_ec *ec, u8 *data) | 387 | static int acpi_ec_query(struct acpi_ec *ec, u8 * data) |
390 | { | 388 | { |
391 | int result; | 389 | int result; |
392 | u8 d; | 390 | u8 d; |
393 | 391 | ||
394 | if (!ec || !data) | 392 | if (!ec || !data) |
395 | return -EINVAL; | 393 | return -EINVAL; |
396 | 394 | ||
397 | /* | 395 | /* |
398 | * Query the EC to find out which _Qxx method we need to evaluate. | 396 | * Query the EC to find out which _Qxx method we need to evaluate. |
399 | * Note that successful completion of the query causes the ACPI_EC_SCI | 397 | * Note that successful completion of the query causes the ACPI_EC_SCI |
400 | * bit to be cleared (and thus clearing the interrupt source). | 398 | * bit to be cleared (and thus clearing the interrupt source). |
401 | */ | 399 | */ |
402 | 400 | ||
403 | result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); | 401 | result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); |
404 | if (result) | 402 | if (result) |
405 | return result; | 403 | return result; |
406 | 404 | ||
407 | if (!d) | 405 | if (!d) |
408 | return -ENODATA; | 406 | return -ENODATA; |
409 | 407 | ||
410 | *data = d; | 408 | *data = d; |
411 | return 0; | 409 | return 0; |
412 | } | 410 | } |
413 | 411 | ||
414 | /* -------------------------------------------------------------------------- | 412 | /* -------------------------------------------------------------------------- |
415 | Event Management | 413 | Event Management |
416 | -------------------------------------------------------------------------- */ | 414 | -------------------------------------------------------------------------- */ |
417 | 415 | ||
418 | struct acpi_ec_query_data { | ||
419 | acpi_handle handle; | ||
420 | u8 data; | ||
421 | }; | ||
422 | |||
423 | static void acpi_ec_gpe_query(void *ec_cxt) | 416 | static void acpi_ec_gpe_query(void *ec_cxt) |
424 | { | 417 | { |
425 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; | 418 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; |
426 | u8 value = 0; | 419 | u8 value = 0; |
427 | static char object_name[8]; | 420 | char object_name[8]; |
428 | 421 | ||
429 | if (!ec) | 422 | if (!ec || acpi_ec_query(ec, &value)) |
430 | goto end; | 423 | return; |
431 | |||
432 | value = acpi_ec_read_status(ec); | ||
433 | |||
434 | if (!(value & ACPI_EC_FLAG_SCI)) | ||
435 | goto end; | ||
436 | |||
437 | if (acpi_ec_query(ec, &value)) | ||
438 | goto end; | ||
439 | 424 | ||
440 | snprintf(object_name, 8, "_Q%2.2X", value); | 425 | snprintf(object_name, 8, "_Q%2.2X", value); |
441 | 426 | ||
442 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); | 427 | printk(KERN_INFO PREFIX "evaluating %s\n", object_name); |
443 | 428 | ||
444 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 429 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); |
445 | |||
446 | end: | ||
447 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | ||
448 | } | 430 | } |
449 | 431 | ||
450 | static u32 acpi_ec_gpe_handler(void *data) | 432 | static u32 acpi_ec_gpe_handler(void *data) |
@@ -453,22 +435,18 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
453 | u8 value; | 435 | u8 value; |
454 | struct acpi_ec *ec = (struct acpi_ec *)data; | 436 | struct acpi_ec *ec = (struct acpi_ec *)data; |
455 | 437 | ||
456 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); | ||
457 | value = acpi_ec_read_status(ec); | ||
458 | |||
459 | if (acpi_ec_mode == EC_INTR) { | 438 | if (acpi_ec_mode == EC_INTR) { |
460 | if (acpi_ec_check_status(value, ec->expect_event)) { | 439 | wake_up(&ec->wait); |
461 | ec->expect_event = 0; | ||
462 | wake_up(&ec->wait); | ||
463 | } | ||
464 | } | 440 | } |
465 | 441 | ||
466 | if (value & ACPI_EC_FLAG_SCI) { | 442 | value = acpi_ec_read_status(ec); |
467 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); | 443 | if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { |
468 | return status == AE_OK ? | 444 | atomic_set(&ec->query_pending, 1); |
469 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 445 | status = |
446 | acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, | ||
447 | ec); | ||
470 | } | 448 | } |
471 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 449 | |
472 | return status == AE_OK ? | 450 | return status == AE_OK ? |
473 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 451 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
474 | } | 452 | } |
@@ -504,7 +482,6 @@ acpi_ec_space_handler(u32 function, | |||
504 | acpi_integer f_v = 0; | 482 | acpi_integer f_v = 0; |
505 | int i = 0; | 483 | int i = 0; |
506 | 484 | ||
507 | |||
508 | if ((address > 0xFF) || !value || !handler_context) | 485 | if ((address > 0xFF) || !value || !handler_context) |
509 | return AE_BAD_PARAMETER; | 486 | return AE_BAD_PARAMETER; |
510 | 487 | ||
@@ -518,7 +495,7 @@ acpi_ec_space_handler(u32 function, | |||
518 | switch (function) { | 495 | switch (function) { |
519 | case ACPI_READ: | 496 | case ACPI_READ: |
520 | temp = 0; | 497 | temp = 0; |
521 | result = acpi_ec_read(ec, (u8) address, (u8 *) &temp); | 498 | result = acpi_ec_read(ec, (u8) address, (u8 *) & temp); |
522 | break; | 499 | break; |
523 | case ACPI_WRITE: | 500 | case ACPI_WRITE: |
524 | result = acpi_ec_write(ec, (u8) address, (u8) temp); | 501 | result = acpi_ec_write(ec, (u8) address, (u8) temp); |
@@ -571,18 +548,15 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset) | |||
571 | { | 548 | { |
572 | struct acpi_ec *ec = (struct acpi_ec *)seq->private; | 549 | struct acpi_ec *ec = (struct acpi_ec *)seq->private; |
573 | 550 | ||
574 | |||
575 | if (!ec) | 551 | if (!ec) |
576 | goto end; | 552 | goto end; |
577 | 553 | ||
578 | seq_printf(seq, "gpe bit: 0x%02x\n", | 554 | seq_printf(seq, "gpe: 0x%02x\n", (u32) ec->gpe); |
579 | (u32) ec->gpe_bit); | ||
580 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", | 555 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", |
581 | (u32) ec->command_addr, | 556 | (u32) ec->command_addr, (u32) ec->data_addr); |
582 | (u32) ec->data_addr); | ||
583 | seq_printf(seq, "use global lock: %s\n", | 557 | seq_printf(seq, "use global lock: %s\n", |
584 | ec->global_lock ? "yes" : "no"); | 558 | ec->global_lock ? "yes" : "no"); |
585 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 559 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
586 | 560 | ||
587 | end: | 561 | end: |
588 | return 0; | 562 | return 0; |
@@ -605,7 +579,6 @@ static int acpi_ec_add_fs(struct acpi_device *device) | |||
605 | { | 579 | { |
606 | struct proc_dir_entry *entry = NULL; | 580 | struct proc_dir_entry *entry = NULL; |
607 | 581 | ||
608 | |||
609 | if (!acpi_device_dir(device)) { | 582 | if (!acpi_device_dir(device)) { |
610 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 583 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
611 | acpi_ec_dir); | 584 | acpi_ec_dir); |
@@ -648,7 +621,6 @@ static int acpi_ec_add(struct acpi_device *device) | |||
648 | acpi_status status = AE_OK; | 621 | acpi_status status = AE_OK; |
649 | struct acpi_ec *ec = NULL; | 622 | struct acpi_ec *ec = NULL; |
650 | 623 | ||
651 | |||
652 | if (!device) | 624 | if (!device) |
653 | return -EINVAL; | 625 | return -EINVAL; |
654 | 626 | ||
@@ -659,7 +631,8 @@ static int acpi_ec_add(struct acpi_device *device) | |||
659 | 631 | ||
660 | ec->handle = device->handle; | 632 | ec->handle = device->handle; |
661 | ec->uid = -1; | 633 | ec->uid = -1; |
662 | init_MUTEX(&ec->sem); | 634 | mutex_init(&ec->lock); |
635 | atomic_set(&ec->query_pending, 0); | ||
663 | if (acpi_ec_mode == EC_INTR) { | 636 | if (acpi_ec_mode == EC_INTR) { |
664 | atomic_set(&ec->leaving_burst, 1); | 637 | atomic_set(&ec->leaving_burst, 1); |
665 | init_waitqueue_head(&ec->wait); | 638 | init_waitqueue_head(&ec->wait); |
@@ -669,8 +642,7 @@ static int acpi_ec_add(struct acpi_device *device) | |||
669 | acpi_driver_data(device) = ec; | 642 | acpi_driver_data(device) = ec; |
670 | 643 | ||
671 | /* Use the global lock for all EC transactions? */ | 644 | /* Use the global lock for all EC transactions? */ |
672 | acpi_evaluate_integer(ec->handle, "_GLK", NULL, | 645 | acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); |
673 | &ec->global_lock); | ||
674 | 646 | ||
675 | /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: | 647 | /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: |
676 | http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ | 648 | http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ |
@@ -679,7 +651,7 @@ static int acpi_ec_add(struct acpi_device *device) | |||
679 | ACPI_ADR_SPACE_EC, | 651 | ACPI_ADR_SPACE_EC, |
680 | &acpi_ec_space_handler); | 652 | &acpi_ec_space_handler); |
681 | 653 | ||
682 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, | 654 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe, |
683 | &acpi_ec_gpe_handler); | 655 | &acpi_ec_gpe_handler); |
684 | 656 | ||
685 | kfree(ec_ecdt); | 657 | kfree(ec_ecdt); |
@@ -687,11 +659,10 @@ static int acpi_ec_add(struct acpi_device *device) | |||
687 | 659 | ||
688 | /* Get GPE bit assignment (EC events). */ | 660 | /* Get GPE bit assignment (EC events). */ |
689 | /* TODO: Add support for _GPE returning a package */ | 661 | /* TODO: Add support for _GPE returning a package */ |
690 | status = | 662 | status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe); |
691 | acpi_evaluate_integer(ec->handle, "_GPE", NULL, | ||
692 | &ec->gpe_bit); | ||
693 | if (ACPI_FAILURE(status)) { | 663 | if (ACPI_FAILURE(status)) { |
694 | ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment")); | 664 | ACPI_EXCEPTION((AE_INFO, status, |
665 | "Obtaining GPE bit assignment")); | ||
695 | result = -ENODEV; | 666 | result = -ENODEV; |
696 | goto end; | 667 | goto end; |
697 | } | 668 | } |
@@ -701,13 +672,13 @@ static int acpi_ec_add(struct acpi_device *device) | |||
701 | goto end; | 672 | goto end; |
702 | 673 | ||
703 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", | 674 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", |
704 | acpi_device_name(device), acpi_device_bid(device), | 675 | acpi_device_name(device), acpi_device_bid(device), |
705 | (u32) ec->gpe_bit)); | 676 | (u32) ec->gpe)); |
706 | 677 | ||
707 | if (!first_ec) | 678 | if (!first_ec) |
708 | first_ec = device; | 679 | first_ec = device; |
709 | 680 | ||
710 | end: | 681 | end: |
711 | if (result) | 682 | if (result) |
712 | kfree(ec); | 683 | kfree(ec); |
713 | 684 | ||
@@ -718,7 +689,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type) | |||
718 | { | 689 | { |
719 | struct acpi_ec *ec = NULL; | 690 | struct acpi_ec *ec = NULL; |
720 | 691 | ||
721 | |||
722 | if (!device) | 692 | if (!device) |
723 | return -EINVAL; | 693 | return -EINVAL; |
724 | 694 | ||
@@ -761,7 +731,6 @@ static int acpi_ec_start(struct acpi_device *device) | |||
761 | acpi_status status = AE_OK; | 731 | acpi_status status = AE_OK; |
762 | struct acpi_ec *ec = NULL; | 732 | struct acpi_ec *ec = NULL; |
763 | 733 | ||
764 | |||
765 | if (!device) | 734 | if (!device) |
766 | return -EINVAL; | 735 | return -EINVAL; |
767 | 736 | ||
@@ -782,27 +751,26 @@ static int acpi_ec_start(struct acpi_device *device) | |||
782 | } | 751 | } |
783 | 752 | ||
784 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", | 753 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", |
785 | ec->gpe_bit, ec->command_addr, ec->data_addr)); | 754 | ec->gpe, ec->command_addr, ec->data_addr)); |
786 | 755 | ||
787 | /* | 756 | /* |
788 | * Install GPE handler | 757 | * Install GPE handler |
789 | */ | 758 | */ |
790 | status = acpi_install_gpe_handler(NULL, ec->gpe_bit, | 759 | status = acpi_install_gpe_handler(NULL, ec->gpe, |
791 | ACPI_GPE_EDGE_TRIGGERED, | 760 | ACPI_GPE_EDGE_TRIGGERED, |
792 | &acpi_ec_gpe_handler, ec); | 761 | &acpi_ec_gpe_handler, ec); |
793 | if (ACPI_FAILURE(status)) { | 762 | if (ACPI_FAILURE(status)) { |
794 | return -ENODEV; | 763 | return -ENODEV; |
795 | } | 764 | } |
796 | acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 765 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); |
797 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 766 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
798 | 767 | ||
799 | status = acpi_install_address_space_handler(ec->handle, | 768 | status = acpi_install_address_space_handler(ec->handle, |
800 | ACPI_ADR_SPACE_EC, | 769 | ACPI_ADR_SPACE_EC, |
801 | &acpi_ec_space_handler, | 770 | &acpi_ec_space_handler, |
802 | &acpi_ec_space_setup, ec); | 771 | &acpi_ec_space_setup, ec); |
803 | if (ACPI_FAILURE(status)) { | 772 | if (ACPI_FAILURE(status)) { |
804 | acpi_remove_gpe_handler(NULL, ec->gpe_bit, | 773 | acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); |
805 | &acpi_ec_gpe_handler); | ||
806 | return -ENODEV; | 774 | return -ENODEV; |
807 | } | 775 | } |
808 | 776 | ||
@@ -814,7 +782,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
814 | acpi_status status = AE_OK; | 782 | acpi_status status = AE_OK; |
815 | struct acpi_ec *ec = NULL; | 783 | struct acpi_ec *ec = NULL; |
816 | 784 | ||
817 | |||
818 | if (!device) | 785 | if (!device) |
819 | return -EINVAL; | 786 | return -EINVAL; |
820 | 787 | ||
@@ -826,9 +793,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
826 | if (ACPI_FAILURE(status)) | 793 | if (ACPI_FAILURE(status)) |
827 | return -ENODEV; | 794 | return -ENODEV; |
828 | 795 | ||
829 | status = | 796 | status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); |
830 | acpi_remove_gpe_handler(NULL, ec->gpe_bit, | ||
831 | &acpi_ec_gpe_handler); | ||
832 | if (ACPI_FAILURE(status)) | 797 | if (ACPI_FAILURE(status)) |
833 | return -ENODEV; | 798 | return -ENODEV; |
834 | 799 | ||
@@ -841,7 +806,7 @@ acpi_fake_ecdt_callback(acpi_handle handle, | |||
841 | { | 806 | { |
842 | acpi_status status; | 807 | acpi_status status; |
843 | 808 | ||
844 | init_MUTEX(&ec_ecdt->sem); | 809 | mutex_init(&ec_ecdt->lock); |
845 | if (acpi_ec_mode == EC_INTR) { | 810 | if (acpi_ec_mode == EC_INTR) { |
846 | init_waitqueue_head(&ec_ecdt->wait); | 811 | init_waitqueue_head(&ec_ecdt->wait); |
847 | } | 812 | } |
@@ -853,16 +818,15 @@ acpi_fake_ecdt_callback(acpi_handle handle, | |||
853 | ec_ecdt->uid = -1; | 818 | ec_ecdt->uid = -1; |
854 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); | 819 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); |
855 | 820 | ||
856 | status = | 821 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe); |
857 | acpi_evaluate_integer(handle, "_GPE", NULL, | ||
858 | &ec_ecdt->gpe_bit); | ||
859 | if (ACPI_FAILURE(status)) | 822 | if (ACPI_FAILURE(status)) |
860 | return status; | 823 | return status; |
861 | ec_ecdt->global_lock = TRUE; | 824 | ec_ecdt->global_lock = TRUE; |
862 | ec_ecdt->handle = handle; | 825 | ec_ecdt->handle = handle; |
863 | 826 | ||
864 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", | 827 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", |
865 | ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr)); | 828 | ec_ecdt->gpe, ec_ecdt->command_addr, |
829 | ec_ecdt->data_addr)); | ||
866 | 830 | ||
867 | return AE_CTRL_TERMINATE; | 831 | return AE_CTRL_TERMINATE; |
868 | } | 832 | } |
@@ -901,7 +865,7 @@ static int __init acpi_ec_fake_ecdt(void) | |||
901 | goto error; | 865 | goto error; |
902 | } | 866 | } |
903 | return 0; | 867 | return 0; |
904 | error: | 868 | error: |
905 | return ret; | 869 | return ret; |
906 | } | 870 | } |
907 | 871 | ||
@@ -926,25 +890,24 @@ static int __init acpi_ec_get_real_ecdt(void) | |||
926 | return -ENOMEM; | 890 | return -ENOMEM; |
927 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); | 891 | memset(ec_ecdt, 0, sizeof(struct acpi_ec)); |
928 | 892 | ||
929 | init_MUTEX(&ec_ecdt->sem); | 893 | mutex_init(&ec_ecdt->lock); |
930 | if (acpi_ec_mode == EC_INTR) { | 894 | if (acpi_ec_mode == EC_INTR) { |
931 | init_waitqueue_head(&ec_ecdt->wait); | 895 | init_waitqueue_head(&ec_ecdt->wait); |
932 | } | 896 | } |
933 | ec_ecdt->command_addr = ecdt_ptr->ec_control.address; | 897 | ec_ecdt->command_addr = ecdt_ptr->ec_control.address; |
934 | ec_ecdt->data_addr = ecdt_ptr->ec_data.address; | 898 | ec_ecdt->data_addr = ecdt_ptr->ec_data.address; |
935 | ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; | 899 | ec_ecdt->gpe = ecdt_ptr->gpe_bit; |
936 | /* use the GL just to be safe */ | 900 | /* use the GL just to be safe */ |
937 | ec_ecdt->global_lock = TRUE; | 901 | ec_ecdt->global_lock = TRUE; |
938 | ec_ecdt->uid = ecdt_ptr->uid; | 902 | ec_ecdt->uid = ecdt_ptr->uid; |
939 | 903 | ||
940 | status = | 904 | status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); |
941 | acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); | ||
942 | if (ACPI_FAILURE(status)) { | 905 | if (ACPI_FAILURE(status)) { |
943 | goto error; | 906 | goto error; |
944 | } | 907 | } |
945 | 908 | ||
946 | return 0; | 909 | return 0; |
947 | error: | 910 | error: |
948 | ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); | 911 | ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); |
949 | kfree(ec_ecdt); | 912 | kfree(ec_ecdt); |
950 | ec_ecdt = NULL; | 913 | ec_ecdt = NULL; |
@@ -970,14 +933,14 @@ int __init acpi_ec_ecdt_probe(void) | |||
970 | /* | 933 | /* |
971 | * Install GPE handler | 934 | * Install GPE handler |
972 | */ | 935 | */ |
973 | status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, | 936 | status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe, |
974 | ACPI_GPE_EDGE_TRIGGERED, | 937 | ACPI_GPE_EDGE_TRIGGERED, |
975 | &acpi_ec_gpe_handler, ec_ecdt); | 938 | &acpi_ec_gpe_handler, ec_ecdt); |
976 | if (ACPI_FAILURE(status)) { | 939 | if (ACPI_FAILURE(status)) { |
977 | goto error; | 940 | goto error; |
978 | } | 941 | } |
979 | acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); | 942 | acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME); |
980 | acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); | 943 | acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR); |
981 | 944 | ||
982 | status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, | 945 | status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, |
983 | ACPI_ADR_SPACE_EC, | 946 | ACPI_ADR_SPACE_EC, |
@@ -985,7 +948,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
985 | &acpi_ec_space_setup, | 948 | &acpi_ec_space_setup, |
986 | ec_ecdt); | 949 | ec_ecdt); |
987 | if (ACPI_FAILURE(status)) { | 950 | if (ACPI_FAILURE(status)) { |
988 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, | 951 | acpi_remove_gpe_handler(NULL, ec_ecdt->gpe, |
989 | &acpi_ec_gpe_handler); | 952 | &acpi_ec_gpe_handler); |
990 | goto error; | 953 | goto error; |
991 | } | 954 | } |
@@ -1004,7 +967,6 @@ static int __init acpi_ec_init(void) | |||
1004 | { | 967 | { |
1005 | int result = 0; | 968 | int result = 0; |
1006 | 969 | ||
1007 | |||
1008 | if (acpi_disabled) | 970 | if (acpi_disabled) |
1009 | return 0; | 971 | return 0; |
1010 | 972 | ||
@@ -1057,7 +1019,8 @@ static int __init acpi_ec_set_intr_mode(char *str) | |||
1057 | acpi_ec_mode = EC_POLL; | 1019 | acpi_ec_mode = EC_POLL; |
1058 | } | 1020 | } |
1059 | acpi_ec_driver.ops.add = acpi_ec_add; | 1021 | acpi_ec_driver.ops.add = acpi_ec_add; |
1060 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling")); | 1022 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", |
1023 | intr ? "interrupt" : "polling")); | ||
1061 | 1024 | ||
1062 | return 1; | 1025 | return 1; |
1063 | } | 1026 | } |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 10f160dc75b1..a2f46d587d55 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
267 | { | 267 | { |
268 | acpi_status status; | 268 | acpi_status status; |
269 | 269 | ||
270 | if (dev->firmware_data) { | 270 | if (dev->archdata.acpi_handle) { |
271 | printk(KERN_WARNING PREFIX | 271 | printk(KERN_WARNING PREFIX |
272 | "Drivers changed 'firmware_data' for %s\n", dev->bus_id); | 272 | "Drivers changed 'acpi_handle' for %s\n", dev->bus_id); |
273 | return -EINVAL; | 273 | return -EINVAL; |
274 | } | 274 | } |
275 | get_device(dev); | 275 | get_device(dev); |
@@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
278 | put_device(dev); | 278 | put_device(dev); |
279 | return -EINVAL; | 279 | return -EINVAL; |
280 | } | 280 | } |
281 | dev->firmware_data = handle; | 281 | dev->archdata.acpi_handle = handle; |
282 | 282 | ||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int acpi_unbind_one(struct device *dev) | 286 | static int acpi_unbind_one(struct device *dev) |
287 | { | 287 | { |
288 | if (!dev->firmware_data) | 288 | if (!dev->archdata.acpi_handle) |
289 | return 0; | 289 | return 0; |
290 | if (dev == acpi_get_physical_device(dev->firmware_data)) { | 290 | if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { |
291 | /* acpi_get_physical_device increase refcnt by one */ | 291 | /* acpi_get_physical_device increase refcnt by one */ |
292 | put_device(dev); | 292 | put_device(dev); |
293 | acpi_detach_data(dev->firmware_data, acpi_glue_data_handler); | 293 | acpi_detach_data(dev->archdata.acpi_handle, |
294 | dev->firmware_data = NULL; | 294 | acpi_glue_data_handler); |
295 | dev->archdata.acpi_handle = NULL; | ||
295 | /* acpi_bind_one increase refcnt by one */ | 296 | /* acpi_bind_one increase refcnt by one */ |
296 | put_device(dev); | 297 | put_device(dev); |
297 | } else { | 298 | } else { |
298 | printk(KERN_ERR PREFIX | 299 | printk(KERN_ERR PREFIX |
299 | "Oops, 'firmware_data' corrupt for %s\n", dev->bus_id); | 300 | "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id); |
300 | } | 301 | } |
301 | return 0; | 302 | return 0; |
302 | } | 303 | } |
@@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev) | |||
328 | if (!ret) { | 329 | if (!ret) { |
329 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 330 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
330 | 331 | ||
331 | acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer); | 332 | acpi_get_name(dev->archdata.acpi_handle, |
333 | ACPI_FULL_PATHNAME, &buffer); | ||
332 | DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); | 334 | DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); |
333 | kfree(buffer.pointer); | 335 | kfree(buffer.pointer); |
334 | } else | 336 | } else |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c84286cbbe25..02b30ae6a68e 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -50,6 +50,7 @@ ACPI_MODULE_NAME("osl") | |||
50 | struct acpi_os_dpc { | 50 | struct acpi_os_dpc { |
51 | acpi_osd_exec_callback function; | 51 | acpi_osd_exec_callback function; |
52 | void *context; | 52 | void *context; |
53 | struct work_struct work; | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | #ifdef CONFIG_ACPI_CUSTOM_DSDT | 56 | #ifdef CONFIG_ACPI_CUSTOM_DSDT |
@@ -73,7 +74,6 @@ static unsigned int acpi_irq_irq; | |||
73 | static acpi_osd_handler acpi_irq_handler; | 74 | static acpi_osd_handler acpi_irq_handler; |
74 | static void *acpi_irq_context; | 75 | static void *acpi_irq_context; |
75 | static struct workqueue_struct *kacpid_wq; | 76 | static struct workqueue_struct *kacpid_wq; |
76 | static struct workqueue_struct *kacpi_notify_wq; | ||
77 | 77 | ||
78 | acpi_status acpi_os_initialize(void) | 78 | acpi_status acpi_os_initialize(void) |
79 | { | 79 | { |
@@ -92,9 +92,8 @@ acpi_status acpi_os_initialize1(void) | |||
92 | return AE_NULL_ENTRY; | 92 | return AE_NULL_ENTRY; |
93 | } | 93 | } |
94 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 94 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
95 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | ||
96 | BUG_ON(!kacpid_wq); | 95 | BUG_ON(!kacpid_wq); |
97 | BUG_ON(!kacpi_notify_wq); | 96 | |
98 | return AE_OK; | 97 | return AE_OK; |
99 | } | 98 | } |
100 | 99 | ||
@@ -106,7 +105,6 @@ acpi_status acpi_os_terminate(void) | |||
106 | } | 105 | } |
107 | 106 | ||
108 | destroy_workqueue(kacpid_wq); | 107 | destroy_workqueue(kacpid_wq); |
109 | destroy_workqueue(kacpi_notify_wq); | ||
110 | 108 | ||
111 | return AE_OK; | 109 | return AE_OK; |
112 | } | 110 | } |
@@ -567,9 +565,9 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ | |||
567 | acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); | 565 | acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); |
568 | } | 566 | } |
569 | 567 | ||
570 | static void acpi_os_execute_deferred(void *context) | 568 | static void acpi_os_execute_deferred(struct work_struct *work) |
571 | { | 569 | { |
572 | struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; | 570 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
573 | if (!dpc) { | 571 | if (!dpc) { |
574 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | 572 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); |
575 | return; | 573 | return; |
@@ -602,40 +600,41 @@ acpi_status acpi_os_execute(acpi_execute_type type, | |||
602 | { | 600 | { |
603 | acpi_status status = AE_OK; | 601 | acpi_status status = AE_OK; |
604 | struct acpi_os_dpc *dpc; | 602 | struct acpi_os_dpc *dpc; |
605 | struct work_struct *task; | 603 | |
604 | ACPI_FUNCTION_TRACE("os_queue_for_execution"); | ||
606 | 605 | ||
607 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 606 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
608 | "Scheduling function [%p(%p)] for deferred execution.\n", | 607 | "Scheduling function [%p(%p)] for deferred execution.\n", |
609 | function, context)); | 608 | function, context)); |
610 | 609 | ||
611 | if (!function) | 610 | if (!function) |
612 | return AE_BAD_PARAMETER; | 611 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
613 | 612 | ||
614 | /* | 613 | /* |
615 | * Allocate/initialize DPC structure. Note that this memory will be | 614 | * Allocate/initialize DPC structure. Note that this memory will be |
616 | * freed by the callee. The kernel handles the tq_struct list in a | 615 | * freed by the callee. The kernel handles the work_struct list in a |
617 | * way that allows us to also free its memory inside the callee. | 616 | * way that allows us to also free its memory inside the callee. |
618 | * Because we may want to schedule several tasks with different | 617 | * Because we may want to schedule several tasks with different |
619 | * parameters we can't use the approach some kernel code uses of | 618 | * parameters we can't use the approach some kernel code uses of |
620 | * having a static tq_struct. | 619 | * having a static work_struct. |
621 | * We can save time and code by allocating the DPC and tq_structs | ||
622 | * from the same memory. | ||
623 | */ | 620 | */ |
624 | 621 | ||
625 | dpc = kmalloc(sizeof(struct acpi_os_dpc) + | 622 | dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); |
626 | sizeof(struct work_struct), GFP_ATOMIC); | ||
627 | if (!dpc) | 623 | if (!dpc) |
628 | return AE_NO_MEMORY; | 624 | return_ACPI_STATUS(AE_NO_MEMORY); |
625 | |||
629 | dpc->function = function; | 626 | dpc->function = function; |
630 | dpc->context = context; | 627 | dpc->context = context; |
631 | task = (void *)(dpc + 1); | 628 | |
632 | INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); | 629 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); |
633 | if (!queue_work((type == OSL_NOTIFY_HANDLER)? | 630 | if (!queue_work(kacpid_wq, &dpc->work)) { |
634 | kacpi_notify_wq : kacpid_wq, task)) { | 631 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
635 | status = AE_ERROR; | 632 | "Call to queue_work() failed.\n")); |
636 | kfree(dpc); | 633 | kfree(dpc); |
634 | status = AE_ERROR; | ||
637 | } | 635 | } |
638 | return status; | 636 | |
637 | return_ACPI_STATUS(status); | ||
639 | } | 638 | } |
640 | 639 | ||
641 | EXPORT_SYMBOL(acpi_os_execute); | 640 | EXPORT_SYMBOL(acpi_os_execute); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 7ba5e49ab302..6fd174a37149 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -83,10 +83,8 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, | |||
83 | goto out; | 83 | goto out; |
84 | 84 | ||
85 | ppc = (unsigned int)pr->performance_platform_limit; | 85 | ppc = (unsigned int)pr->performance_platform_limit; |
86 | if (!ppc) | ||
87 | goto out; | ||
88 | 86 | ||
89 | if (ppc > pr->performance->state_count) | 87 | if (ppc >= pr->performance->state_count) |
90 | goto out; | 88 | goto out; |
91 | 89 | ||
92 | cpufreq_verify_within_limits(policy, 0, | 90 | cpufreq_verify_within_limits(policy, 0, |