📄 osl.c
字号:
if (ACPI_SUCCESS(status)) { pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); if (*is_bridge) pci_id->bus = *bus_number; /* any nicer way to get bus number of bridge ? */ status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); if (ACPI_SUCCESS(status) && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8); if (!ACPI_SUCCESS(status)) { /* Certainly broken... FIX ME */ return; } *is_bridge = 1; pci_id->bus = tu8; status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); if (ACPI_SUCCESS(status)) { *bus_number = tu8; } } else *is_bridge = 0; } }}voidacpi_os_derive_pci_id ( acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ struct acpi_pci_id **id){ int is_bridge = 1; u8 bus_number = (*id)->bus; acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);}#else /*!CONFIG_ACPI_PCI*/acpi_statusacpi_os_write_pci_configuration ( struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width){ return (AE_SUPPORT);}acpi_statusacpi_os_read_pci_configuration ( struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width){ return (AE_SUPPORT);}voidacpi_os_derive_pci_id ( acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ struct acpi_pci_id **id){}#endif /*CONFIG_ACPI_PCI*/static voidacpi_os_execute_deferred ( void *context){ struct acpi_os_dpc *dpc = NULL; ACPI_FUNCTION_TRACE ("os_execute_deferred"); dpc = (struct acpi_os_dpc *) context; if (!dpc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); return_VOID; } dpc->function(dpc->context); kfree(dpc); return_VOID;}acpi_statusacpi_os_queue_for_execution( u32 priority, acpi_osd_exec_callback function, void *context){ acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct work_struct *task; ACPI_FUNCTION_TRACE ("os_queue_for_execution"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) return_ACPI_STATUS (AE_BAD_PARAMETER); /* * Allocate/initialize DPC structure. Note that this memory will be * freed by the callee. The kernel handles the tq_struct list in a * way that allows us to also free its memory inside the callee. * Because we may want to schedule several tasks with different * parameters we can't use the approach some kernel code uses of * having a static tq_struct. * We can save time and code by allocating the DPC and tq_structs * from the same memory. */ dpc = kmalloc(sizeof(struct acpi_os_dpc)+sizeof(struct work_struct), GFP_ATOMIC); if (!dpc) return_ACPI_STATUS (AE_NO_MEMORY); dpc->function = function; dpc->context = context; task = (void *)(dpc+1); INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc); if (!queue_work(kacpid_wq, task)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); kfree(dpc); status = AE_ERROR; } return_ACPI_STATUS (status);}voidacpi_os_wait_events_complete( void *context){ flush_workqueue(kacpid_wq);}/* * Allocate the memory for a spinlock and initialize it. */acpi_statusacpi_os_create_lock ( acpi_handle *out_handle){ spinlock_t *lock_ptr; ACPI_FUNCTION_TRACE ("os_create_lock"); lock_ptr = acpi_os_allocate(sizeof(spinlock_t)); spin_lock_init(lock_ptr); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr)); *out_handle = lock_ptr; return_ACPI_STATUS (AE_OK);}/* * Deallocate the memory for a spinlock. */voidacpi_os_delete_lock ( acpi_handle handle){ ACPI_FUNCTION_TRACE ("os_create_lock"); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle)); acpi_os_free(handle); return_VOID;}/* * Acquire a spinlock. * * handle is a pointer to the spinlock_t. * flags is *not* the result of save_flags - it is an ACPI-specific flag variable * that indicates whether we are at interrupt level. */voidacpi_os_acquire_lock ( acpi_handle handle, u32 flags){ ACPI_FUNCTION_TRACE ("os_acquire_lock"); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle, ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); if (flags & ACPI_NOT_ISR) ACPI_DISABLE_IRQS(); spin_lock((spinlock_t *)handle); return_VOID;}/* * Release a spinlock. See above. */voidacpi_os_release_lock ( acpi_handle handle, u32 flags){ ACPI_FUNCTION_TRACE ("os_release_lock"); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle, ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); spin_unlock((spinlock_t *)handle); if (flags & ACPI_NOT_ISR) ACPI_ENABLE_IRQS(); return_VOID;}acpi_statusacpi_os_create_semaphore( u32 max_units, u32 initial_units, acpi_handle *handle){ struct semaphore *sem = NULL; ACPI_FUNCTION_TRACE ("os_create_semaphore"); sem = acpi_os_allocate(sizeof(struct semaphore)); if (!sem) return_ACPI_STATUS (AE_NO_MEMORY); memset(sem, 0, sizeof(struct semaphore)); sema_init(sem, initial_units); *handle = (acpi_handle*)sem; ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units)); return_ACPI_STATUS (AE_OK);}/* * TODO: A better way to delete semaphores? Linux doesn't have a * 'delete_semaphore()' function -- may result in an invalid * pointer dereference for non-synchronized consumers. Should * we at least check for blocked threads and signal/cancel them? */acpi_statusacpi_os_delete_semaphore( acpi_handle handle){ struct semaphore *sem = (struct semaphore*) handle; ACPI_FUNCTION_TRACE ("os_delete_semaphore"); if (!sem) return_ACPI_STATUS (AE_BAD_PARAMETER); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); acpi_os_free(sem); sem = NULL; return_ACPI_STATUS (AE_OK);}/* * TODO: The kernel doesn't have a 'down_timeout' function -- had to * improvise. The process is to sleep for one scheduler quantum * until the semaphore becomes available. Downside is that this * may result in starvation for timeout-based waits when there's * lots of semaphore activity. * * TODO: Support for units > 1? */acpi_statusacpi_os_wait_semaphore( acpi_handle handle, u32 units, u16 timeout){ acpi_status status = AE_OK; struct semaphore *sem = (struct semaphore*)handle; int ret = 0; ACPI_FUNCTION_TRACE ("os_wait_semaphore"); if (!sem || (units < 1)) return_ACPI_STATUS (AE_BAD_PARAMETER); if (units > 1) return_ACPI_STATUS (AE_SUPPORT); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); if (in_atomic()) timeout = 0; switch (timeout) { /* * No Wait: * -------- * A zero timeout value indicates that we shouldn't wait - just * acquire the semaphore if available otherwise return AE_TIME * (a.k.a. 'would block'). */ case 0: if(down_trylock(sem)) status = AE_TIME; break; /* * Wait Indefinitely: * ------------------ */ case ACPI_WAIT_FOREVER: down(sem); break; /* * Wait w/ Timeout: * ---------------- */ default: // TODO: A better timeout algorithm? { int i = 0; static const int quantum_ms = 1000/HZ; ret = down_trylock(sem); for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); ret = down_trylock(sem); } if (ret != 0) status = AE_TIME; } break; } if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", handle, units, timeout, acpi_format_exception(status))); } else { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); } return_ACPI_STATUS (status);}/* * TODO: Support for units > 1? */acpi_statusacpi_os_signal_semaphore( acpi_handle handle, u32 units){ struct semaphore *sem = (struct semaphore *) handle; ACPI_FUNCTION_TRACE ("os_signal_semaphore"); if (!sem || (units < 1)) return_ACPI_STATUS (AE_BAD_PARAMETER); if (units > 1) return_ACPI_STATUS (AE_SUPPORT); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units)); up(sem); return_ACPI_STATUS (AE_OK);}u32acpi_os_get_line(char *buffer){#ifdef ENABLE_DEBUGGER if (acpi_in_debugger) { u32 chars; kdb_read(buffer, sizeof(line_buf)); /* remove the CR kdb includes */ chars = strlen(buffer) - 1; buffer[chars] = '\0'; }#endif return 0;}/* Assumes no unreadable holes inbetween */u8acpi_os_readable(void *ptr, acpi_size len){#if defined(__i386__) || defined(__x86_64__) char tmp; return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);#endif return 1;}u8acpi_os_writable(void *ptr, acpi_size len){ /* could do dummy write (racy) or a kernel page table lookup. The later may be difficult at early boot when kmap doesn't work yet. */ return 1;}u32acpi_os_get_thread_id (void){ if (!in_atomic()) return current->pid; return 0;}acpi_statusacpi_os_signal ( u32 function, void *info){ switch (function) { case ACPI_SIGNAL_FATAL: printk(KERN_ERR PREFIX "Fatal opcode executed\n"); break; case ACPI_SIGNAL_BREAKPOINT: { char *bp_info = (char*) info; printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); } default: break; } return AE_OK;}int __initacpi_os_name_setup(char *str){ char *p = acpi_os_name; int count = ACPI_MAX_OVERRIDE_LEN-1; if (!str || !*str) return 0; for (; count-- && str && *str; str++) { if (isalnum(*str) || *str == ' ' || *str == ':') *p++ = *str; else if (*str == '\'' || *str == '"') continue; else break; } *p = 0; return 1; }__setup("acpi_os_name=", acpi_os_name_setup);/* * _OSI control * empty string disables _OSI * TBD additional string adds to _OSI */int __initacpi_osi_setup(char *str){ if (str == NULL || *str == '\0') { printk(KERN_INFO PREFIX "_OSI method disabled\n"); acpi_gbl_create_osi_method = FALSE; } else { /* TBD */ printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str); } return 1;}__setup("acpi_osi=", acpi_osi_setup);/* enable serialization to combat AE_ALREADY_EXISTS errors */int __initacpi_serialize_setup(char *str){ printk(KERN_INFO PREFIX "serialize enabled\n"); acpi_gbl_all_methods_serialized = TRUE; return 1;}__setup("acpi_serialize", acpi_serialize_setup);/* * Wake and Run-Time GPES are expected to be separate. * We disable wake-GPEs at run-time to prevent spurious * interrupts. * * However, if a system exists that shares Wake and * Run-time events on the same GPE this flag is available * to tell Linux to keep the wake-time GPEs enabled at run-time. */int __initacpi_wake_gpes_always_on_setup(char *str){ printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); acpi_gbl_leave_wake_gpes_disabled = FALSE; return 1;}__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -