diff options
Diffstat (limited to 'drivers/acpi/osl.c')
| -rw-r--r-- | drivers/acpi/osl.c | 159 |
1 files changed, 112 insertions, 47 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 13b5fd5854a8..1bb558adee66 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
| 38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
| 39 | #include <linux/nmi.h> | 39 | #include <linux/nmi.h> |
| 40 | #include <linux/kthread.h> | ||
| 40 | #include <acpi/acpi.h> | 41 | #include <acpi/acpi.h> |
| 41 | #include <asm/io.h> | 42 | #include <asm/io.h> |
| 42 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
| @@ -600,23 +601,41 @@ static void acpi_os_execute_deferred(void *context) | |||
| 600 | return_VOID; | 601 | return_VOID; |
| 601 | } | 602 | } |
| 602 | 603 | ||
| 603 | acpi_status | 604 | static int acpi_os_execute_thread(void *context) |
| 604 | acpi_os_queue_for_execution(u32 priority, | 605 | { |
| 606 | struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; | ||
| 607 | if (dpc) { | ||
| 608 | dpc->function(dpc->context); | ||
| 609 | kfree(dpc); | ||
| 610 | } | ||
| 611 | do_exit(0); | ||
| 612 | } | ||
| 613 | |||
| 614 | /******************************************************************************* | ||
| 615 | * | ||
| 616 | * FUNCTION: acpi_os_execute | ||
| 617 | * | ||
| 618 | * PARAMETERS: Type - Type of the callback | ||
| 619 | * Function - Function to be executed | ||
| 620 | * Context - Function parameters | ||
| 621 | * | ||
| 622 | * RETURN: Status | ||
| 623 | * | ||
| 624 | * DESCRIPTION: Depending on type, either queues function for deferred execution or | ||
| 625 | * immediately executes function on a separate thread. | ||
| 626 | * | ||
| 627 | ******************************************************************************/ | ||
| 628 | |||
| 629 | acpi_status acpi_os_execute(acpi_execute_type type, | ||
| 605 | acpi_osd_exec_callback function, void *context) | 630 | acpi_osd_exec_callback function, void *context) |
| 606 | { | 631 | { |
| 607 | acpi_status status = AE_OK; | 632 | acpi_status status = AE_OK; |
| 608 | struct acpi_os_dpc *dpc; | 633 | struct acpi_os_dpc *dpc; |
| 609 | struct work_struct *task; | 634 | struct work_struct *task; |
| 610 | 635 | struct task_struct *p; | |
| 611 | ACPI_FUNCTION_TRACE("os_queue_for_execution"); | ||
| 612 | |||
| 613 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 614 | "Scheduling function [%p(%p)] for deferred execution.\n", | ||
| 615 | function, context)); | ||
| 616 | 636 | ||
| 617 | if (!function) | 637 | if (!function) |
| 618 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 638 | return AE_BAD_PARAMETER; |
| 619 | |||
| 620 | /* | 639 | /* |
| 621 | * Allocate/initialize DPC structure. Note that this memory will be | 640 | * Allocate/initialize DPC structure. Note that this memory will be |
| 622 | * freed by the callee. The kernel handles the tq_struct list in a | 641 | * freed by the callee. The kernel handles the tq_struct list in a |
| @@ -627,30 +646,37 @@ acpi_os_queue_for_execution(u32 priority, | |||
| 627 | * We can save time and code by allocating the DPC and tq_structs | 646 | * We can save time and code by allocating the DPC and tq_structs |
| 628 | * from the same memory. | 647 | * from the same memory. |
| 629 | */ | 648 | */ |
| 630 | 649 | if (type == OSL_NOTIFY_HANDLER) { | |
| 631 | dpc = | 650 | dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL); |
| 632 | kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), | 651 | } else { |
| 633 | GFP_ATOMIC); | 652 | dpc = kmalloc(sizeof(struct acpi_os_dpc) + |
| 653 | sizeof(struct work_struct), GFP_ATOMIC); | ||
| 654 | } | ||
| 634 | if (!dpc) | 655 | if (!dpc) |
| 635 | return_ACPI_STATUS(AE_NO_MEMORY); | 656 | return AE_NO_MEMORY; |
| 636 | |||
| 637 | dpc->function = function; | 657 | dpc->function = function; |
| 638 | dpc->context = context; | 658 | dpc->context = context; |
| 639 | 659 | ||
| 640 | task = (void *)(dpc + 1); | 660 | if (type == OSL_NOTIFY_HANDLER) { |
| 641 | INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); | 661 | p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify"); |
| 642 | 662 | if (!IS_ERR(p)) { | |
| 643 | if (!queue_work(kacpid_wq, task)) { | 663 | wake_up_process(p); |
| 644 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 664 | } else { |
| 645 | "Call to queue_work() failed.\n")); | 665 | status = AE_NO_MEMORY; |
| 646 | kfree(dpc); | 666 | kfree(dpc); |
| 647 | status = AE_ERROR; | 667 | } |
| 668 | } else { | ||
| 669 | task = (void *)(dpc + 1); | ||
| 670 | INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); | ||
| 671 | if (!queue_work(kacpid_wq, task)) { | ||
| 672 | status = AE_ERROR; | ||
| 673 | kfree(dpc); | ||
| 674 | } | ||
| 648 | } | 675 | } |
| 649 | 676 | return status; | |
| 650 | return_ACPI_STATUS(status); | ||
| 651 | } | 677 | } |
| 652 | 678 | ||
| 653 | EXPORT_SYMBOL(acpi_os_queue_for_execution); | 679 | EXPORT_SYMBOL(acpi_os_execute); |
| 654 | 680 | ||
| 655 | void acpi_os_wait_events_complete(void *context) | 681 | void acpi_os_wait_events_complete(void *context) |
| 656 | { | 682 | { |
| @@ -769,9 +795,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) | |||
| 769 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", | 795 | ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", |
| 770 | handle, units, timeout)); | 796 | handle, units, timeout)); |
| 771 | 797 | ||
| 772 | if (in_atomic()) | ||
| 773 | timeout = 0; | ||
| 774 | |||
| 775 | switch (timeout) { | 798 | switch (timeout) { |
| 776 | /* | 799 | /* |
| 777 | * No Wait: | 800 | * No Wait: |
| @@ -896,14 +919,6 @@ u8 acpi_os_writable(void *ptr, acpi_size len) | |||
| 896 | } | 919 | } |
| 897 | #endif | 920 | #endif |
| 898 | 921 | ||
| 899 | u32 acpi_os_get_thread_id(void) | ||
| 900 | { | ||
| 901 | if (!in_atomic()) | ||
| 902 | return current->pid; | ||
| 903 | |||
| 904 | return 0; | ||
| 905 | } | ||
| 906 | |||
| 907 | acpi_status acpi_os_signal(u32 function, void *info) | 922 | acpi_status acpi_os_signal(u32 function, void *info) |
| 908 | { | 923 | { |
| 909 | switch (function) { | 924 | switch (function) { |
| @@ -1050,12 +1065,12 @@ void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags) | |||
| 1050 | * | 1065 | * |
| 1051 | * FUNCTION: acpi_os_create_cache | 1066 | * FUNCTION: acpi_os_create_cache |
| 1052 | * | 1067 | * |
| 1053 | * PARAMETERS: CacheName - Ascii name for the cache | 1068 | * PARAMETERS: name - Ascii name for the cache |
| 1054 | * ObjectSize - Size of each cached object | 1069 | * size - Size of each cached object |
| 1055 | * MaxDepth - Maximum depth of the cache (in objects) | 1070 | * depth - Maximum depth of the cache (in objects) <ignored> |
| 1056 | * ReturnCache - Where the new cache object is returned | 1071 | * cache - Where the new cache object is returned |
| 1057 | * | 1072 | * |
| 1058 | * RETURN: Status | 1073 | * RETURN: status |
| 1059 | * | 1074 | * |
| 1060 | * DESCRIPTION: Create a cache object | 1075 | * DESCRIPTION: Create a cache object |
| 1061 | * | 1076 | * |
| @@ -1065,7 +1080,10 @@ acpi_status | |||
| 1065 | acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) | 1080 | acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) |
| 1066 | { | 1081 | { |
| 1067 | *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL); | 1082 | *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL); |
| 1068 | return AE_OK; | 1083 | if (cache == NULL) |
| 1084 | return AE_ERROR; | ||
| 1085 | else | ||
| 1086 | return AE_OK; | ||
| 1069 | } | 1087 | } |
| 1070 | 1088 | ||
| 1071 | /******************************************************************************* | 1089 | /******************************************************************************* |
| @@ -1134,16 +1152,63 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) | |||
| 1134 | * | 1152 | * |
| 1135 | * RETURN: Status | 1153 | * RETURN: Status |
| 1136 | * | 1154 | * |
| 1137 | * DESCRIPTION: Get an object from the specified cache. If cache is empty, | 1155 | * DESCRIPTION: Return a zero-filled object. |
| 1138 | * the object is allocated. | ||
| 1139 | * | 1156 | * |
| 1140 | ******************************************************************************/ | 1157 | ******************************************************************************/ |
| 1141 | 1158 | ||
| 1142 | void *acpi_os_acquire_object(acpi_cache_t * cache) | 1159 | void *acpi_os_acquire_object(acpi_cache_t * cache) |
| 1143 | { | 1160 | { |
| 1144 | void *object = kmem_cache_alloc(cache, GFP_KERNEL); | 1161 | void *object = kmem_cache_zalloc(cache, GFP_KERNEL); |
| 1145 | WARN_ON(!object); | 1162 | WARN_ON(!object); |
| 1146 | return object; | 1163 | return object; |
| 1147 | } | 1164 | } |
| 1148 | 1165 | ||
| 1166 | /****************************************************************************** | ||
| 1167 | * | ||
| 1168 | * FUNCTION: acpi_os_validate_interface | ||
| 1169 | * | ||
| 1170 | * PARAMETERS: interface - Requested interface to be validated | ||
| 1171 | * | ||
| 1172 | * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise | ||
| 1173 | * | ||
| 1174 | * DESCRIPTION: Match an interface string to the interfaces supported by the | ||
| 1175 | * host. Strings originate from an AML call to the _OSI method. | ||
| 1176 | * | ||
| 1177 | *****************************************************************************/ | ||
| 1178 | |||
| 1179 | acpi_status | ||
| 1180 | acpi_os_validate_interface (char *interface) | ||
| 1181 | { | ||
| 1182 | |||
| 1183 | return AE_SUPPORT; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | |||
| 1187 | /****************************************************************************** | ||
| 1188 | * | ||
| 1189 | * FUNCTION: acpi_os_validate_address | ||
| 1190 | * | ||
| 1191 | * PARAMETERS: space_id - ACPI space ID | ||
| 1192 | * address - Physical address | ||
| 1193 | * length - Address length | ||
| 1194 | * | ||
| 1195 | * RETURN: AE_OK if address/length is valid for the space_id. Otherwise, | ||
| 1196 | * should return AE_AML_ILLEGAL_ADDRESS. | ||
| 1197 | * | ||
| 1198 | * DESCRIPTION: Validate a system address via the host OS. Used to validate | ||
| 1199 | * the addresses accessed by AML operation regions. | ||
| 1200 | * | ||
| 1201 | *****************************************************************************/ | ||
| 1202 | |||
| 1203 | acpi_status | ||
| 1204 | acpi_os_validate_address ( | ||
| 1205 | u8 space_id, | ||
| 1206 | acpi_physical_address address, | ||
| 1207 | acpi_size length) | ||
| 1208 | { | ||
| 1209 | |||
| 1210 | return AE_OK; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | |||
| 1149 | #endif | 1214 | #endif |
