static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_processor *pr = (struct acpi_processor *)data; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_processor_notify"); if (!pr) return_VOID; if (acpi_bus_get_device(pr->handle, &device)) return_VOID; switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: acpi_processor_ppc_has_changed(pr); acpi_bus_generate_event(device, event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); acpi_bus_generate_event(device, event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
static void acpi_battery_notify ( acpi_handle handle, u32 event, void *data) { struct acpi_battery *battery = (struct acpi_battery *) data; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_battery_notify"); if (!battery) return_VOID; if (acpi_bus_get_device(handle, &device)) return_VOID; switch (event) { case ACPI_BATTERY_NOTIFY_STATUS: case ACPI_BATTERY_NOTIFY_INFO: acpi_battery_check(battery); acpi_bus_generate_event(device, event, battery->flags.present); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
static int acpi_thermal_hot ( struct acpi_thermal *tz) { int result = 0; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_thermal_hot"); if (!tz || !tz->trips.hot.flags.valid) return_VALUE(-EINVAL); if (tz->temperature >= tz->trips.hot.temperature) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n")); tz->trips.hot.flags.enabled = 1; } else if (tz->trips.hot.flags.enabled) tz->trips.hot.flags.enabled = 0; result = acpi_bus_get_device(tz->handle, &device); if (result) return_VALUE(result); acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); /* TBD: Call user-mode "sleep(S4)" function */ return_VALUE(0); }
static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) { struct acpi_battery *battery = (struct acpi_battery *)data; struct acpi_device *device = NULL; if (!battery) return; device = battery->device; switch (event) { case ACPI_BATTERY_NOTIFY_STATUS: case ACPI_BATTERY_NOTIFY_INFO: case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: acpi_battery_check(battery); acpi_bus_generate_event(device, event, battery->flags.present); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return; }
static int acpi_thermal_critical ( struct acpi_thermal *tz) { int result = 0; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_thermal_critical"); if (!tz || !tz->trips.critical.flags.valid) return_VALUE(-EINVAL); if (tz->temperature >= tz->trips.critical.temperature) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n")); tz->trips.critical.flags.enabled = 1; } else if (tz->trips.critical.flags.enabled) tz->trips.critical.flags.enabled = 0; result = acpi_bus_get_device(tz->handle, &device); if (result) return_VALUE(result); printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature)); acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF); return_VALUE(0); }
void acpi_button_notify ( acpi_handle handle, u32 event, void *data) { struct acpi_button *button = (struct acpi_button *) data; ACPI_FUNCTION_TRACE("acpi_button_notify"); if (!button || !button->device) return_VOID; switch (event) { case ACPI_BUTTON_NOTIFY_STATUS: acpi_bus_generate_event(button->device, event, ++button->pushed); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
void acpi_ac_notify ( acpi_handle handle, u32 event, void *data) { struct acpi_ac *ac = (struct acpi_ac *) data; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_ac_notify"); if (!ac) return; if (acpi_bus_get_device(ac->handle, &device)) return_VOID; switch (event) { case ACPI_AC_NOTIFY_STATUS: acpi_ac_get_state(ac); acpi_bus_generate_event(device, event, (u32) ac->state); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
static void acpi_thermal_notify ( acpi_handle handle, u32 event, void *data) { struct acpi_thermal *tz = (struct acpi_thermal *) data; struct acpi_device *device = NULL; ACPI_FUNCTION_TRACE("acpi_thermal_notify"); if (!tz) return_VOID; if (acpi_bus_get_device(tz->handle, &device)) return_VOID; switch (event) { case ACPI_THERMAL_NOTIFY_TEMPERATURE: acpi_thermal_check(tz); break; case ACPI_THERMAL_NOTIFY_THRESHOLDS: acpi_thermal_get_trip_points(tz); acpi_thermal_check(tz); acpi_bus_generate_event(device, event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: if (tz->flags.devices) acpi_thermal_get_devices(tz); acpi_bus_generate_event(device, event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return_VOID; }
static int acpi_processor_start(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_processor *pr; processor_extcntl_init(); pr = acpi_driver_data(device); result = acpi_processor_get_info(pr); if (result || ((pr->id == -1) && !processor_cntl_external())) { /* Processor is physically not present */ return 0; } BUG_ON(!processor_cntl_external() && ((pr->id >= NR_CPUS) || (pr->id < 0))); /* * Buggy BIOS check * ACPI id of processors can be reported wrongly by the BIOS. * Don't trust it blindly */ #ifdef CONFIG_XEN BUG_ON(pr->acpi_id >= NR_ACPI_CPUS); if (processor_device_array[pr->acpi_id] != NULL && processor_device_array[pr->acpi_id] != (void *)device) { #else if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != (void *)device) { #endif /* CONFIG_XEN */ printk(KERN_WARNING "BIOS reported wrong ACPI id" "for the processor\n"); return -ENODEV; } #ifdef CONFIG_XEN processor_device_array[pr->acpi_id] = (void *)device; if (pr->id != -1) processors[pr->id] = pr; #else processor_device_array[pr->id] = (void *)device; processors[pr->id] = pr; #endif /* CONFIG_XEN */ result = acpi_processor_add_fs(device); if (result) goto end; status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify, pr); /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); #if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) acpi_processor_ppc_has_changed(pr); #endif /* * pr->id may equal to -1 while processor_cntl_external enabled. * throttle and thermal module don't support this case. * Tx only works when dom0 vcpu == pcpu num by far, as we give * control to dom0. */ if (pr->id != -1) { acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); } acpi_processor_power_init(pr, device); result = processor_extcntl_prepare(pr); if (result) goto end; if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", acpi_device_name(device), acpi_device_bid(device)); printk(" %d throttling states", pr->throttling.state_count); printk(")\n"); } end: return result; } static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_processor *pr = (struct acpi_processor *)data; struct acpi_device *device = NULL; if (!pr) return; if (acpi_bus_get_device(pr->handle, &device)) return; switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: acpi_processor_ppc_has_changed(pr); acpi_bus_generate_event(device, event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); acpi_bus_generate_event(device, event, 0); break; case ACPI_PROCESSOR_NOTIFY_THROTTLING: acpi_processor_tstate_has_changed(pr); acpi_bus_generate_event(device, event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); break; } return; } static int acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; if (!device) return -EINVAL; pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) return -ENOMEM; memset(pr, 0, sizeof(struct acpi_processor)); pr->handle = device->handle; strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); acpi_driver_data(device) = pr; return 0; } static int acpi_processor_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; struct acpi_processor *pr = NULL; if (!device || !acpi_driver_data(device)) return -EINVAL; pr = (struct acpi_processor *)acpi_driver_data(device); if (!processor_cntl_external() && pr->id >= NR_CPUS) { kfree(pr); return 0; } if (type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } acpi_processor_power_exit(pr, device); status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify); acpi_processor_remove_fs(device); #ifdef CONFIG_XEN if (pr->id != -1) processors[pr->id] = NULL; #else processors[pr->id] = NULL; #endif /* CONFIG_XEN */ kfree(pr); return 0; }