diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index eee0864ba300..18b3ea9dace2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -116,7 +116,7 @@ union acpi_ec { | |||
116 | struct acpi_generic_address command_addr; | 116 | struct acpi_generic_address command_addr; |
117 | struct acpi_generic_address data_addr; | 117 | struct acpi_generic_address data_addr; |
118 | unsigned long global_lock; | 118 | unsigned long global_lock; |
119 | spinlock_t lock; | 119 | struct semaphore sem; |
120 | } poll; | 120 | } poll; |
121 | }; | 121 | }; |
122 | 122 | ||
@@ -323,7 +323,6 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) | |||
323 | { | 323 | { |
324 | acpi_status status = AE_OK; | 324 | acpi_status status = AE_OK; |
325 | int result = 0; | 325 | int result = 0; |
326 | unsigned long flags = 0; | ||
327 | u32 glk = 0; | 326 | u32 glk = 0; |
328 | 327 | ||
329 | ACPI_FUNCTION_TRACE("acpi_ec_read"); | 328 | ACPI_FUNCTION_TRACE("acpi_ec_read"); |
@@ -339,8 +338,11 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) | |||
339 | return_VALUE(-ENODEV); | 338 | return_VALUE(-ENODEV); |
340 | } | 339 | } |
341 | 340 | ||
342 | spin_lock_irqsave(&ec->poll.lock, flags); | 341 | if (down_interruptible(&ec->poll.sem)) { |
343 | 342 | result = -ERESTARTSYS; | |
343 | goto end_nosem; | ||
344 | } | ||
345 | |||
344 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, | 346 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, |
345 | &ec->common.command_addr); | 347 | &ec->common.command_addr); |
346 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 348 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
@@ -358,8 +360,8 @@ static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) | |||
358 | *data, address)); | 360 | *data, address)); |
359 | 361 | ||
360 | end: | 362 | end: |
361 | spin_unlock_irqrestore(&ec->poll.lock, flags); | 363 | up(&ec->poll.sem); |
362 | 364 | end_nosem: | |
363 | if (ec->common.global_lock) | 365 | if (ec->common.global_lock) |
364 | acpi_release_global_lock(glk); | 366 | acpi_release_global_lock(glk); |
365 | 367 | ||
@@ -370,7 +372,6 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) | |||
370 | { | 372 | { |
371 | int result = 0; | 373 | int result = 0; |
372 | acpi_status status = AE_OK; | 374 | acpi_status status = AE_OK; |
373 | unsigned long flags = 0; | ||
374 | u32 glk = 0; | 375 | u32 glk = 0; |
375 | 376 | ||
376 | ACPI_FUNCTION_TRACE("acpi_ec_write"); | 377 | ACPI_FUNCTION_TRACE("acpi_ec_write"); |
@@ -384,8 +385,11 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) | |||
384 | return_VALUE(-ENODEV); | 385 | return_VALUE(-ENODEV); |
385 | } | 386 | } |
386 | 387 | ||
387 | spin_lock_irqsave(&ec->poll.lock, flags); | 388 | if (down_interruptible(&ec->poll.sem)) { |
388 | 389 | result = -ERESTARTSYS; | |
390 | goto end_nosem; | ||
391 | } | ||
392 | |||
389 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, | 393 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, |
390 | &ec->common.command_addr); | 394 | &ec->common.command_addr); |
391 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 395 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
@@ -406,8 +410,8 @@ static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) | |||
406 | data, address)); | 410 | data, address)); |
407 | 411 | ||
408 | end: | 412 | end: |
409 | spin_unlock_irqrestore(&ec->poll.lock, flags); | 413 | up(&ec->poll.sem); |
410 | 414 | end_nosem: | |
411 | if (ec->common.global_lock) | 415 | if (ec->common.global_lock) |
412 | acpi_release_global_lock(glk); | 416 | acpi_release_global_lock(glk); |
413 | 417 | ||
@@ -568,7 +572,6 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) | |||
568 | { | 572 | { |
569 | int result = 0; | 573 | int result = 0; |
570 | acpi_status status = AE_OK; | 574 | acpi_status status = AE_OK; |
571 | unsigned long flags = 0; | ||
572 | u32 glk = 0; | 575 | u32 glk = 0; |
573 | 576 | ||
574 | ACPI_FUNCTION_TRACE("acpi_ec_query"); | 577 | ACPI_FUNCTION_TRACE("acpi_ec_query"); |
@@ -589,8 +592,11 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) | |||
589 | * Note that successful completion of the query causes the ACPI_EC_SCI | 592 | * Note that successful completion of the query causes the ACPI_EC_SCI |
590 | * bit to be cleared (and thus clearing the interrupt source). | 593 | * bit to be cleared (and thus clearing the interrupt source). |
591 | */ | 594 | */ |
592 | spin_lock_irqsave(&ec->poll.lock, flags); | 595 | if (down_interruptible(&ec->poll.sem)) { |
593 | 596 | result = -ERESTARTSYS; | |
597 | goto end_nosem; | ||
598 | } | ||
599 | |||
594 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, | 600 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, |
595 | &ec->common.command_addr); | 601 | &ec->common.command_addr); |
596 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 602 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
@@ -602,8 +608,8 @@ static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data) | |||
602 | result = -ENODATA; | 608 | result = -ENODATA; |
603 | 609 | ||
604 | end: | 610 | end: |
605 | spin_unlock_irqrestore(&ec->poll.lock, flags); | 611 | up(&ec->poll.sem); |
606 | 612 | end_nosem: | |
607 | if (ec->common.global_lock) | 613 | if (ec->common.global_lock) |
608 | acpi_release_global_lock(glk); | 614 | acpi_release_global_lock(glk); |
609 | 615 | ||
@@ -680,7 +686,6 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) | |||
680 | { | 686 | { |
681 | union acpi_ec *ec = (union acpi_ec *)ec_cxt; | 687 | union acpi_ec *ec = (union acpi_ec *)ec_cxt; |
682 | u32 value = 0; | 688 | u32 value = 0; |
683 | unsigned long flags = 0; | ||
684 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; | 689 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; |
685 | const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', | 690 | const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', |
686 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | 691 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
@@ -691,9 +696,11 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) | |||
691 | if (!ec_cxt) | 696 | if (!ec_cxt) |
692 | goto end; | 697 | goto end; |
693 | 698 | ||
694 | spin_lock_irqsave(&ec->poll.lock, flags); | 699 | if (down_interruptible (&ec->poll.sem)) { |
700 | return_VOID; | ||
701 | } | ||
695 | acpi_hw_low_level_read(8, &value, &ec->common.command_addr); | 702 | acpi_hw_low_level_read(8, &value, &ec->common.command_addr); |
696 | spin_unlock_irqrestore(&ec->poll.lock, flags); | 703 | up(&ec->poll.sem); |
697 | 704 | ||
698 | /* TBD: Implement asynch events! | 705 | /* TBD: Implement asynch events! |
699 | * NOTE: All we care about are EC-SCI's. Other EC events are | 706 | * NOTE: All we care about are EC-SCI's. Other EC events are |
@@ -763,8 +770,7 @@ static u32 acpi_ec_gpe_poll_handler(void *data) | |||
763 | 770 | ||
764 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | 771 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
765 | 772 | ||
766 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 773 | status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); |
767 | acpi_ec_gpe_query, ec); | ||
768 | 774 | ||
769 | if (status == AE_OK) | 775 | if (status == AE_OK) |
770 | return ACPI_INTERRUPT_HANDLED; | 776 | return ACPI_INTERRUPT_HANDLED; |
@@ -799,7 +805,7 @@ static u32 acpi_ec_gpe_intr_handler(void *data) | |||
799 | 805 | ||
800 | if (value & ACPI_EC_FLAG_SCI) { | 806 | if (value & ACPI_EC_FLAG_SCI) { |
801 | atomic_add(1, &ec->intr.pending_gpe); | 807 | atomic_add(1, &ec->intr.pending_gpe); |
802 | status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, | 808 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
803 | acpi_ec_gpe_query, ec); | 809 | acpi_ec_gpe_query, ec); |
804 | return status == AE_OK ? | 810 | return status == AE_OK ? |
805 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 811 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
@@ -991,7 +997,6 @@ static int acpi_ec_poll_add(struct acpi_device *device) | |||
991 | int result = 0; | 997 | int result = 0; |
992 | acpi_status status = AE_OK; | 998 | acpi_status status = AE_OK; |
993 | union acpi_ec *ec = NULL; | 999 | union acpi_ec *ec = NULL; |
994 | unsigned long uid; | ||
995 | 1000 | ||
996 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | 1001 | ACPI_FUNCTION_TRACE("acpi_ec_add"); |
997 | 1002 | ||
@@ -1005,7 +1010,7 @@ static int acpi_ec_poll_add(struct acpi_device *device) | |||
1005 | 1010 | ||
1006 | ec->common.handle = device->handle; | 1011 | ec->common.handle = device->handle; |
1007 | ec->common.uid = -1; | 1012 | ec->common.uid = -1; |
1008 | spin_lock_init(&ec->poll.lock); | 1013 | init_MUTEX(&ec->poll.sem); |
1009 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | 1014 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
1010 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | 1015 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
1011 | acpi_driver_data(device) = ec; | 1016 | acpi_driver_data(device) = ec; |
@@ -1014,10 +1019,9 @@ static int acpi_ec_poll_add(struct acpi_device *device) | |||
1014 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, | 1019 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, |
1015 | &ec->common.global_lock); | 1020 | &ec->common.global_lock); |
1016 | 1021 | ||
1017 | /* If our UID matches the UID for the ECDT-enumerated EC, | 1022 | /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: |
1018 | we now have the *real* EC info, so kill the makeshift one. */ | 1023 | http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ |
1019 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); | 1024 | if (ec_ecdt) { |
1020 | if (ec_ecdt && ec_ecdt->common.uid == uid) { | ||
1021 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | 1025 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, |
1022 | ACPI_ADR_SPACE_EC, | 1026 | ACPI_ADR_SPACE_EC, |
1023 | &acpi_ec_space_handler); | 1027 | &acpi_ec_space_handler); |
@@ -1062,7 +1066,6 @@ static int acpi_ec_intr_add(struct acpi_device *device) | |||
1062 | int result = 0; | 1066 | int result = 0; |
1063 | acpi_status status = AE_OK; | 1067 | acpi_status status = AE_OK; |
1064 | union acpi_ec *ec = NULL; | 1068 | union acpi_ec *ec = NULL; |
1065 | unsigned long uid; | ||
1066 | 1069 | ||
1067 | ACPI_FUNCTION_TRACE("acpi_ec_add"); | 1070 | ACPI_FUNCTION_TRACE("acpi_ec_add"); |
1068 | 1071 | ||
@@ -1088,10 +1091,9 @@ static int acpi_ec_intr_add(struct acpi_device *device) | |||
1088 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, | 1091 | acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, |
1089 | &ec->common.global_lock); | 1092 | &ec->common.global_lock); |
1090 | 1093 | ||
1091 | /* If our UID matches the UID for the ECDT-enumerated EC, | 1094 | /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: |
1092 | we now have the *real* EC info, so kill the makeshift one. */ | 1095 | http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ |
1093 | acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); | 1096 | if (ec_ecdt) { |
1094 | if (ec_ecdt && ec_ecdt->common.uid == uid) { | ||
1095 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, | 1097 | acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, |
1096 | ACPI_ADR_SPACE_EC, | 1098 | ACPI_ADR_SPACE_EC, |
1097 | &acpi_ec_space_handler); | 1099 | &acpi_ec_space_handler); |
@@ -1300,7 +1302,7 @@ acpi_fake_ecdt_poll_callback(acpi_handle handle, | |||
1300 | &ec_ecdt->common.gpe_bit); | 1302 | &ec_ecdt->common.gpe_bit); |
1301 | if (ACPI_FAILURE(status)) | 1303 | if (ACPI_FAILURE(status)) |
1302 | return status; | 1304 | return status; |
1303 | spin_lock_init(&ec_ecdt->poll.lock); | 1305 | init_MUTEX(&ec_ecdt->poll.sem); |
1304 | ec_ecdt->common.global_lock = TRUE; | 1306 | ec_ecdt->common.global_lock = TRUE; |
1305 | ec_ecdt->common.handle = handle; | 1307 | ec_ecdt->common.handle = handle; |
1306 | 1308 | ||
@@ -1416,7 +1418,7 @@ static int __init acpi_ec_poll_get_real_ecdt(void) | |||
1416 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; | 1418 | ec_ecdt->common.status_addr = ecdt_ptr->ec_control; |
1417 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; | 1419 | ec_ecdt->common.data_addr = ecdt_ptr->ec_data; |
1418 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; | 1420 | ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; |
1419 | spin_lock_init(&ec_ecdt->poll.lock); | 1421 | init_MUTEX(&ec_ecdt->poll.sem); |
1420 | /* use the GL just to be safe */ | 1422 | /* use the GL just to be safe */ |
1421 | ec_ecdt->common.global_lock = TRUE; | 1423 | ec_ecdt->common.global_lock = TRUE; |
1422 | ec_ecdt->common.uid = ecdt_ptr->uid; | 1424 | ec_ecdt->common.uid = ecdt_ptr->uid; |