aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c72
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 364end_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 414end_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 612end_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;