static int int3400_thermal_run_osc(acpi_handle handle, enum int3400_thermal_uuid uuid, bool enable) { u32 ret, buf[2]; acpi_status status; int result = 0; struct acpi_osc_context context = { .uuid_str = int3400_thermal_uuids[uuid], .rev = 1, .cap.length = 8, }; buf[OSC_QUERY_DWORD] = 0; buf[OSC_SUPPORT_DWORD] = enable; context.cap.pointer = buf; status = acpi_run_osc(handle, &context); if (ACPI_SUCCESS(status)) { ret = *((u32 *)(context.ret.pointer + 4)); if (ret != enable) result = -EPERM; } else result = -EPERM; kfree(context.ret.pointer); return result; } static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, unsigned long *temp) { *temp = 20 * 1000; /* faked temp sensor with 20C */ return 0; }
static acpi_status acpi_pci_run_osc(acpi_handle handle, const u32 *capbuf, u32 *retval) { struct acpi_osc_context context = { .uuid_str = pci_osc_uuid_str, .rev = 1, .cap.length = 12, .cap.pointer = (void *)capbuf, }; acpi_status status; status = acpi_run_osc(handle, &context); if (ACPI_SUCCESS(status)) { *retval = *((u32 *)(context.ret.pointer + 8)); kfree(context.ret.pointer); } return status; } static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 support, u32 *control) { acpi_status status; u32 result, capbuf[3]; support &= OSC_PCI_SUPPORT_MASKS; support |= root->osc_support_set; capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = support; if (control) { *control &= OSC_PCI_CONTROL_MASKS; capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; } else { /* Run _OSC query only with existing controls. */ capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); if (ACPI_SUCCESS(status)) { root->osc_support_set = support; if (control) *control = result; } return status; }
static void acpi_bus_osc_support(void) { u32 capbuf[2]; struct acpi_osc_context context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; acpi_handle handle; capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) || \ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; #endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) kfree(context.ret.pointer); /* do we need to check the returned cap? Sounds no */ } /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_PROC_EVENT static DEFINE_SPINLOCK(acpi_bus_event_lock); LIST_HEAD(acpi_bus_event_list); DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); extern int event_is_open; int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data) { struct acpi_bus_event *event; unsigned long flags = 0; /* drop event on the floor if no one's listening */ if (!event_is_open) return 0; event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); if (!event) return -ENOMEM; strcpy(event->device_class, device_class); strcpy(event->bus_id, bus_id); event->type = type; event->data = data; spin_lock_irqsave(&acpi_bus_event_lock, flags); list_add_tail(&event->node, &acpi_bus_event_list); spin_unlock_irqrestore(&acpi_bus_event_lock, flags); wake_up_interruptible(&acpi_bus_event_queue); return 0; } EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4); int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) { if (!device) return -EINVAL; return acpi_bus_generate_proc_event4(device->pnp.device_class, device->pnp.bus_id, type, data); } EXPORT_SYMBOL(acpi_bus_generate_proc_event); int acpi_bus_receive_event(struct acpi_bus_event *event) { unsigned long flags = 0; struct acpi_bus_event *entry = NULL; DECLARE_WAITQUEUE(wait, current); if (!event) return -EINVAL; if (list_empty(&acpi_bus_event_list)) { set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&acpi_bus_event_queue, &wait); if (list_empty(&acpi_bus_event_list)) schedule(); remove_wait_queue(&acpi_bus_event_queue, &wait); set_current_state(TASK_RUNNING); if (signal_pending(current)) return -ERESTARTSYS; } spin_lock_irqsave(&acpi_bus_event_lock, flags); if (!list_empty(&acpi_bus_event_list)) { entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); list_del(&entry->node); }
static void acpi_bus_osc_support(void) { u32 capbuf[2]; struct acpi_osc_context context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; acpi_handle handle; capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ if (IS_ENABLED(CONFIG_ACPI_PROCESSOR_AGGREGATOR)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PROCESSOR)) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; if (context.ret.length > OSC_SUPPORT_DWORD) osc_sb_apei_support_acked = capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ } /* -------------------------------------------------------------------------- Notification Handling -------------------------------------------------------------------------- */ /** * acpi_bus_notify * --------------- * Callback for all 'system-level' device notifications (values 0x00-0x7F). */ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) { struct acpi_device *adev; struct acpi_driver *driver; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; bool hotplug_event = false; switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_WAKE: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n"); break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n"); /* TBD: Exactly what does 'light' mean? */ break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: acpi_handle_err(handle, "Device cannot be configured due " "to a frequency mismatch\n"); break; case ACPI_NOTIFY_BUS_MODE_MISMATCH: acpi_handle_err(handle, "Device cannot be configured due " "to a bus mode mismatch\n"); break; case ACPI_NOTIFY_POWER_FAULT: acpi_handle_err(handle, "Device has suffered a power fault\n"); break; default: acpi_handle_debug(handle, "Unknown event type 0x%x\n", type); break; } adev = acpi_bus_get_acpi_device(handle); if (!adev) goto err; driver = adev->driver; if (driver && driver->ops.notify && (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) driver->ops.notify(adev, type); if (hotplug_event && ACPI_SUCCESS(acpi_hotplug_schedule(adev, type))) return; acpi_bus_put_acpi_device(adev); return; err: acpi_evaluate_ost(handle, type, ost_code, NULL); } static void acpi_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_device *device = data; device->driver->ops.notify(device, event); } static void acpi_device_notify_fixed(void *data) { struct acpi_device *device = data; /* Fixed hardware devices have no handles */ acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); } static u32 acpi_device_fixed_event(void *data) { acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); return ACPI_INTERRUPT_HANDLED; }
static void acpi_bus_osc_support(void) { u32 capbuf[2]; struct acpi_osc_context context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; acpi_handle handle; capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; #endif capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; if (context.ret.length > OSC_SUPPORT_DWORD) osc_sb_apei_support_acked = capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ } /* -------------------------------------------------------------------------- Notification Handling -------------------------------------------------------------------------- */ /** * acpi_bus_notify * --------------- * Callback for all 'system-level' device notifications (values 0x00-0x7F). */ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) { struct acpi_device *adev; struct acpi_driver *driver; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; bool hotplug_event = false; switch (type) { case ACPI_NOTIFY_BUS_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_CHECK: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_WAKE: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n"); break; case ACPI_NOTIFY_EJECT_REQUEST: acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); hotplug_event = true; break; case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n"); /* TBD: Exactly what does 'light' mean? */ break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: acpi_handle_err(handle, "Device cannot be configured due " "to a frequency mismatch\n"); break; case ACPI_NOTIFY_BUS_MODE_MISMATCH: acpi_handle_err(handle, "Device cannot be configured due " "to a bus mode mismatch\n"); break; case ACPI_NOTIFY_POWER_FAULT: acpi_handle_err(handle, "Device has suffered a power fault\n"); break; default: acpi_handle_debug(handle, "Unknown event type 0x%x\n", type); break; } adev = acpi_bus_get_acpi_device(handle); if (!adev) goto err; driver = adev->driver; if (driver && driver->ops.notify && (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) driver->ops.notify(adev, type); if (hotplug_event && ACPI_SUCCESS(acpi_hotplug_schedule(adev, type))) return; acpi_bus_put_acpi_device(adev); return; err: acpi_evaluate_ost(handle, type, ost_code, NULL); } /* -------------------------------------------------------------------------- Initialization/Cleanup -------------------------------------------------------------------------- */ static int __init acpi_bus_init_irq(void) { acpi_status status; char *message = NULL; /* * Let the system know what interrupt model we are using by * evaluating the \_PIC object, if exists. */ switch (acpi_irq_model) { case ACPI_IRQ_MODEL_PIC: message = "PIC"; break; case ACPI_IRQ_MODEL_IOAPIC: message = "IOAPIC"; break; case ACPI_IRQ_MODEL_IOSAPIC: message = "IOSAPIC"; break; case ACPI_IRQ_MODEL_PLATFORM: message = "platform specific model"; break; default: printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); return -ENODEV; } printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); return -ENODEV; } return 0; }
static void acpi_bus_osc_support(void) { u32 capbuf[2]; struct acpi_osc_context context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; acpi_handle handle; capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; #endif #ifdef ACPI_HOTPLUG_OST capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT; #endif if (!ghes_disable) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; if (context.ret.length > OSC_SUPPORT_TYPE) osc_sb_apei_support_acked = capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ } /* -------------------------------------------------------------------------- Notification Handling -------------------------------------------------------------------------- */ static void acpi_bus_check_device(acpi_handle handle) { struct acpi_device *device; acpi_status status; struct acpi_device_status old_status; if (acpi_bus_get_device(handle, &device)) return; if (!device) return; old_status = device->status; /* * Make sure this device's parent is present before we go about * messing with the device. */ if (device->parent && !device->parent->status.present) { device->status = device->parent->status; return; } status = acpi_bus_get_status(device); if (ACPI_FAILURE(status)) return; if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) return; /* * Device Insertion/Removal */ if ((device->status.present) && !(old_status.present)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); /* TBD: Handle device insertion */ } else if (!(device->status.present) && (old_status.present)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); /* TBD: Handle device removal */ } } static void acpi_bus_check_scope(acpi_handle handle) { /* Status Change? */ acpi_bus_check_device(handle); /* * TBD: Enumerate child devices within this device's scope and * run acpi_bus_check_device()'s on them. */ }
static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, u32 lvl, void *context, void **rv) { u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; u32 capbuf[2]; struct acpi_osc_context osc_context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; if (acpi_hwp_native_thermal_lvt_set) return AE_CTRL_TERMINATE; capbuf[0] = 0x0000; capbuf[1] = 0x1000; /* set bit 12 */ if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { if (osc_context.ret.pointer && osc_context.ret.length > 1) { u32 *capbuf_ret = osc_context.ret.pointer; if (capbuf_ret[1] & 0x1000) { acpi_handle_info(handle, "_OSC native thermal LVT Acked\n"); acpi_hwp_native_thermal_lvt_set = true; } } kfree(osc_context.ret.pointer); } return AE_OK; } void __init acpi_early_processor_osc(void) { if (boot_cpu_has(X86_FEATURE_HWP)) { acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_hwp_native_thermal_lvt_osc, NULL, NULL, NULL); acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_hwp_native_thermal_lvt_osc, NULL, NULL); } } #endif /* * The following ACPI IDs are known to be suitable for representing as * processor devices. */ static const struct acpi_device_id processor_device_ids[] = { { ACPI_PROCESSOR_OBJECT_HID, }, { ACPI_PROCESSOR_DEVICE_HID, }, { } }; static struct acpi_scan_handler processor_handler = { .ids = processor_device_ids, .attach = acpi_processor_add, #ifdef CONFIG_ACPI_HOTPLUG_CPU .detach = acpi_processor_remove, #endif .hotplug = { .enabled = true, }, }; static int acpi_processor_container_attach(struct acpi_device *dev, const struct acpi_device_id *id) { return 1; } static const struct acpi_device_id processor_container_ids[] = { { ACPI_PROCESSOR_CONTAINER_HID, }, { } }; static struct acpi_scan_handler processor_container_handler = { .ids = processor_container_ids, .attach = acpi_processor_container_attach, }; /* The number of the unique processor IDs */ static int nr_unique_ids __initdata; /* The number of the duplicate processor IDs */ static int nr_duplicate_ids; /* Used to store the unique processor IDs */ static int unique_processor_ids[] __initdata = { [0 ... NR_CPUS - 1] = -1, }; /* Used to store the duplicate processor IDs */ static int duplicate_processor_ids[] = { [0 ... NR_CPUS - 1] = -1, }; static void __init processor_validated_ids_update(int proc_id) { int i; if (nr_unique_ids == NR_CPUS||nr_duplicate_ids == NR_CPUS) return; /* * Firstly, compare the proc_id with duplicate IDs, if the proc_id is * already in the IDs, do nothing. */ for (i = 0; i < nr_duplicate_ids; i++) { if (duplicate_processor_ids[i] == proc_id) return; } /* * Secondly, compare the proc_id with unique IDs, if the proc_id is in * the IDs, put it in the duplicate IDs. */ for (i = 0; i < nr_unique_ids; i++) { if (unique_processor_ids[i] == proc_id) { duplicate_processor_ids[nr_duplicate_ids] = proc_id; nr_duplicate_ids++; return; } } /* * Lastly, the proc_id is a unique ID, put it in the unique IDs. */ unique_processor_ids[nr_unique_ids] = proc_id; nr_unique_ids++; } static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; acpi_object_type acpi_type; unsigned long long uid; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; status = acpi_get_type(handle, &acpi_type); if (ACPI_FAILURE(status)) return status; switch (acpi_type) { case ACPI_TYPE_PROCESSOR: status = acpi_evaluate_object(handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) goto err; uid = object.processor.proc_id; break; case ACPI_TYPE_DEVICE: status = acpi_evaluate_integer(handle, "_UID", NULL, &uid); if (ACPI_FAILURE(status)) goto err; break; default: goto err; } processor_validated_ids_update(uid); return AE_OK; err: /* Exit on error, but don't abort the namespace walk */ acpi_handle_info(handle, "Invalid processor object\n"); return AE_OK; }
static void acpi_bus_osc_support(void) { u32 capbuf[2]; struct acpi_osc_context context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; acpi_handle handle; capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; #endif #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; #endif #ifdef ACPI_HOTPLUG_OST capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; #endif if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { u32 *capbuf_ret = context.ret.pointer; if (context.ret.length > OSC_SUPPORT_DWORD) osc_sb_apei_support_acked = capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; kfree(context.ret.pointer); } /* do we need to check other returned cap? Sounds no */ } /* -------------------------------------------------------------------------- Notification Handling -------------------------------------------------------------------------- */ /** * acpi_bus_notify * --------------- * Callback for all 'system-level' device notifications (values 0x00-0x7F). */ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) { struct acpi_device *device = NULL; struct acpi_driver *driver; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", type, handle)); switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* TBD */ break; case ACPI_NOTIFY_DEVICE_CHECK: /* TBD */ break; case ACPI_NOTIFY_DEVICE_WAKE: /* TBD */ break; case ACPI_NOTIFY_EJECT_REQUEST: /* TBD */ break; case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: /* TBD: Exactly what does 'light' mean? */ break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: /* TBD */ break; case ACPI_NOTIFY_BUS_MODE_MISMATCH: /* TBD */ break; case ACPI_NOTIFY_POWER_FAULT: /* TBD */ break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n", type)); break; } acpi_bus_get_device(handle, &device); if (device) { driver = device->driver; if (driver && driver->ops.notify && (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) driver->ops.notify(device, type); } } /* -------------------------------------------------------------------------- Initialization/Cleanup -------------------------------------------------------------------------- */ static int __init acpi_bus_init_irq(void) { acpi_status status; char *message = NULL; /* * Let the system know what interrupt model we are using by * evaluating the \_PIC object, if exists. */ switch (acpi_irq_model) { case ACPI_IRQ_MODEL_PIC: message = "PIC"; break; case ACPI_IRQ_MODEL_IOAPIC: message = "IOAPIC"; break; case ACPI_IRQ_MODEL_IOSAPIC: message = "IOSAPIC"; break; case ACPI_IRQ_MODEL_PLATFORM: message = "platform specific model"; break; default: printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); return -ENODEV; } printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); return -ENODEV; } return 0; }