Loading drivers/acpi/bus.c +81 −72 Original line number Diff line number Diff line Loading @@ -52,22 +52,6 @@ EXPORT_SYMBOL(acpi_root_dir); #define STRUCT_TO_INT(s) (*((int*)&s)) static int set_power_nocheck(const struct dmi_system_id *id) { printk(KERN_NOTICE PREFIX "%s detected - " "disable power check in power transition\n", id->ident); acpi_power_nocheck = 1; return 0; } static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { { set_power_nocheck, "HP Pavilion 05", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"), DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL}, {}, }; #ifdef CONFIG_X86 static int set_copy_dsdt(const struct dmi_system_id *id) Loading Loading @@ -196,33 +180,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); Power Management -------------------------------------------------------------------------- */ int acpi_bus_get_power(acpi_handle handle, int *state) static int __acpi_bus_get_power(struct acpi_device *device, int *state) { int result = 0; acpi_status status = 0; struct acpi_device *device = NULL; unsigned long long psc = 0; result = acpi_bus_get_device(handle, &device); if (result) return result; if (!device || !state) return -EINVAL; *state = ACPI_STATE_UNKNOWN; if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy */ if (device->parent) *state = device->parent->power.state; else *state = ACPI_STATE_D0; } else { if (device->flags.power_manageable) { /* * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.power_resources) { result = acpi_power_get_inferred_state(device); result = acpi_power_get_inferred_state(device, state); if (result) return result; } else if (device->power.flags.explicit_get) { Loading @@ -230,59 +205,33 @@ int acpi_bus_get_power(acpi_handle handle, int *state) NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; device->power.state = (int)psc; *state = (int)psc; } *state = device->power.state; } else { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", device->pnp.bus_id, device->power.state)); device->pnp.bus_id, *state)); return 0; } EXPORT_SYMBOL(acpi_bus_get_power); int acpi_bus_set_power(acpi_handle handle, int state) static int __acpi_bus_set_power(struct acpi_device *device, int state) { int result = 0; acpi_status status = AE_OK; struct acpi_device *device = NULL; char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; result = acpi_bus_get_device(handle, &device); if (result) return result; if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) return -EINVAL; /* Make sure this is a valid target state */ if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", kobject_name(&device->dev.kobj))); return -ENODEV; } /* * Get device's current power state */ if (!acpi_power_nocheck) { /* * Maybe the incorrect power state is returned on the bogus * bios, which is different with the real power state. * For example: the bios returns D0 state and the real power * state is D3. OS expects to set the device to D0 state. In * such case if OS uses the power state returned by the BIOS, * the device can't be transisted to the correct power state. * So if the acpi_power_nocheck is set, it is unnecessary to * get the power state by calling acpi_bus_get_power. */ acpi_bus_get_power(device->handle, &device->power.state); } if ((state == device->power.state) && !device->flags.force_power_state) { if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return 0; Loading Loading @@ -351,8 +300,75 @@ int acpi_bus_set_power(acpi_handle handle, int state) return result; } int acpi_bus_set_power(acpi_handle handle, int state) { struct acpi_device *device; int result; result = acpi_bus_get_device(handle, &device); if (result) return result; if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] is not power manageable\n", dev_name(&device->dev))); return -ENODEV; } return __acpi_bus_set_power(device, state); } EXPORT_SYMBOL(acpi_bus_set_power); int acpi_bus_init_power(struct acpi_device *device) { int state; int result; if (!device) return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; result = __acpi_bus_get_power(device, &state); if (result) return result; if (device->power.flags.power_resources) result = acpi_power_on_resources(device, state); if (!result) device->power.state = state; return result; } int acpi_bus_update_power(acpi_handle handle, int *state_p) { struct acpi_device *device; int state; int result; result = acpi_bus_get_device(handle, &device); if (result) return result; result = __acpi_bus_get_power(device, &state); if (result) return result; result = __acpi_bus_set_power(device, state); if (!result && state_p) *state_p = state; return result; } EXPORT_SYMBOL_GPL(acpi_bus_update_power); bool acpi_bus_power_manageable(acpi_handle handle) { struct acpi_device *device; Loading Loading @@ -1023,15 +1039,8 @@ static int __init acpi_init(void) if (acpi_disabled) return result; /* * If the laptop falls into the DMI check table, the power state check * will be disabled in the course of device power transition. */ dmi_check_system(power_nocheck_dmi_table); acpi_scan_init(); acpi_ec_init(); acpi_power_init(); acpi_debugfs_init(); acpi_sleep_proc_init(); acpi_wakeup_device_init(); Loading drivers/acpi/fan.c +7 −20 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long if (!device) return -EINVAL; result = acpi_bus_get_power(device->handle, &acpi_state); result = acpi_bus_update_power(device->handle, &acpi_state); if (result) return result; Loading Loading @@ -123,7 +123,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = { static int acpi_fan_add(struct acpi_device *device) { int result = 0; int state = 0; struct thermal_cooling_device *cdev; if (!device) Loading @@ -132,16 +131,12 @@ static int acpi_fan_add(struct acpi_device *device) strcpy(acpi_device_name(device), "Fan"); strcpy(acpi_device_class(device), ACPI_FAN_CLASS); result = acpi_bus_get_power(device->handle, &state); result = acpi_bus_update_power(device->handle, NULL); if (result) { printk(KERN_ERR PREFIX "Reading power state\n"); printk(KERN_ERR PREFIX "Setting initial power state\n"); goto end; } device->flags.force_power_state = 1; acpi_bus_set_power(device->handle, state); device->flags.force_power_state = 0; cdev = thermal_cooling_device_register("Fan", device, &fan_cooling_ops); if (IS_ERR(cdev)) { Loading Loading @@ -200,22 +195,14 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) static int acpi_fan_resume(struct acpi_device *device) { int result = 0; int power_state = 0; int result; if (!device) return -EINVAL; result = acpi_bus_get_power(device->handle, &power_state); if (result) { printk(KERN_ERR PREFIX "Error reading fan power state\n"); return result; } device->flags.force_power_state = 1; acpi_bus_set_power(device->handle, power_state); device->flags.force_power_state = 0; result = acpi_bus_update_power(device->handle, NULL); if (result) printk(KERN_ERR PREFIX "Error updating fan power state\n"); return result; } Loading drivers/acpi/internal.h +3 −2 Original line number Diff line number Diff line Loading @@ -41,9 +41,10 @@ static inline int acpi_debugfs_init(void) { return 0; } int acpi_power_init(void); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_power_get_inferred_state(struct acpi_device *device); int acpi_power_get_inferred_state(struct acpi_device *device, int *state); int acpi_power_on_resources(struct acpi_device *device, int state); int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; int acpi_bus_init_power(struct acpi_device *device); int acpi_wakeup_device_init(void); void acpi_early_processor_set_pdc(void); Loading drivers/acpi/power.c +50 −40 Original line number Diff line number Diff line Loading @@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF int acpi_power_nocheck; module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); static int acpi_power_add(struct acpi_device *device); static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); Loading Loading @@ -266,6 +263,35 @@ static int acpi_power_off_device(acpi_handle handle) return result; } static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) { int i; for (i = num_res - 1; i >= 0 ; i--) acpi_power_off_device(list->handles[i]); } static void acpi_power_off_list(struct acpi_handle_list *list) { __acpi_power_off_list(list, list->count); } static int acpi_power_on_list(struct acpi_handle_list *list) { int result = 0; int i; for (i = 0; i < list->count; i++) { result = acpi_power_on(list->handles[i]); if (result) { __acpi_power_off_list(list, i); break; } } return result; } /** * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in * ACPI 3.0) _PSW (Power State Wake) Loading Loading @@ -423,19 +449,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) Device Power Management -------------------------------------------------------------------------- */ int acpi_power_get_inferred_state(struct acpi_device *device) int acpi_power_get_inferred_state(struct acpi_device *device, int *state) { int result = 0; struct acpi_handle_list *list = NULL; int list_state = 0; int i = 0; if (!device) if (!device || !state) return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; /* * We know a device's inferred power state when all the resources * required for a given D-state are 'on'. Loading @@ -450,22 +473,26 @@ int acpi_power_get_inferred_state(struct acpi_device *device) return result; if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { device->power.state = i; *state = i; return 0; } } device->power.state = ACPI_STATE_D3; *state = ACPI_STATE_D3; return 0; } int acpi_power_on_resources(struct acpi_device *device, int state) { if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) return -EINVAL; return acpi_power_on_list(&device->power.states[state].resources); } int acpi_power_transition(struct acpi_device *device, int state) { int result = 0; struct acpi_handle_list *cl = NULL; /* Current Resources */ struct acpi_handle_list *tl = NULL; /* Target Resources */ int i = 0; int result; if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) return -EINVAL; Loading @@ -477,37 +504,20 @@ int acpi_power_transition(struct acpi_device *device, int state) || (device->power.state > ACPI_STATE_D3)) return -ENODEV; cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; /* TBD: Resources must be ordered. */ /* * First we reference all power resources required in the target list * (e.g. so the device doesn't lose power while transitioning). * (e.g. so the device doesn't lose power while transitioning). Then, * we dereference all power resources used in the current list. */ for (i = 0; i < tl->count; i++) { result = acpi_power_on(tl->handles[i]); if (result) goto end; } result = acpi_power_on_list(&device->power.states[state].resources); if (!result) acpi_power_off_list( &device->power.states[device->power.state].resources); /* * Then we dereference all power resources used in the current list. */ for (i = 0; i < cl->count; i++) { result = acpi_power_off_device(cl->handles[i]); if (result) goto end; } end: if (result) device->power.state = ACPI_STATE_UNKNOWN; else { /* We shouldn't change the state till all above operations succeed */ device->power.state = state; } /* We shouldn't change the state unless the above operations succeed. */ device->power.state = result ? ACPI_STATE_UNKNOWN : state; return result; } Loading drivers/acpi/scan.c +23 −4 Original line number Diff line number Diff line Loading @@ -847,6 +847,8 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) return 0; } static void acpi_bus_add_power_resource(acpi_handle handle); static int acpi_bus_get_power_flags(struct acpi_device *device) { acpi_status status = 0; Loading Loading @@ -875,8 +877,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) acpi_evaluate_reference(device->handle, object_name, NULL, &ps->resources); if (ps->resources.count) { int j; device->power.flags.power_resources = 1; ps->flags.valid = 1; for (j = 0; j < ps->resources.count; j++) acpi_bus_add_power_resource(ps->resources.handles[j]); } /* Evaluate "_PSx" to see if we can do explicit sets */ Loading @@ -901,10 +907,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) device->power.states[ACPI_STATE_D3].flags.valid = 1; device->power.states[ACPI_STATE_D3].power = 0; /* TBD: System wake support and resource requirements. */ device->power.state = ACPI_STATE_UNKNOWN; acpi_bus_get_power(device->handle, &(device->power.state)); acpi_bus_init_power(device); return 0; } Loading Loading @@ -1326,6 +1329,20 @@ static int acpi_add_single_object(struct acpi_device **child, #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, ACPI_STA_DEFAULT, &ops); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, unsigned long long *sta) { Loading Loading @@ -1573,6 +1590,8 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } acpi_power_init(); /* * Enumerate devices in the ACPI namespace. */ Loading Loading
drivers/acpi/bus.c +81 −72 Original line number Diff line number Diff line Loading @@ -52,22 +52,6 @@ EXPORT_SYMBOL(acpi_root_dir); #define STRUCT_TO_INT(s) (*((int*)&s)) static int set_power_nocheck(const struct dmi_system_id *id) { printk(KERN_NOTICE PREFIX "%s detected - " "disable power check in power transition\n", id->ident); acpi_power_nocheck = 1; return 0; } static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { { set_power_nocheck, "HP Pavilion 05", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_SYS_VENDOR, "HP Pavilion 05"), DMI_MATCH(DMI_PRODUCT_VERSION, "2001211RE101GLEND") }, NULL}, {}, }; #ifdef CONFIG_X86 static int set_copy_dsdt(const struct dmi_system_id *id) Loading Loading @@ -196,33 +180,24 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); Power Management -------------------------------------------------------------------------- */ int acpi_bus_get_power(acpi_handle handle, int *state) static int __acpi_bus_get_power(struct acpi_device *device, int *state) { int result = 0; acpi_status status = 0; struct acpi_device *device = NULL; unsigned long long psc = 0; result = acpi_bus_get_device(handle, &device); if (result) return result; if (!device || !state) return -EINVAL; *state = ACPI_STATE_UNKNOWN; if (!device->flags.power_manageable) { /* TBD: Non-recursive algorithm for walking up hierarchy */ if (device->parent) *state = device->parent->power.state; else *state = ACPI_STATE_D0; } else { if (device->flags.power_manageable) { /* * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ if (device->power.flags.power_resources) { result = acpi_power_get_inferred_state(device); result = acpi_power_get_inferred_state(device, state); if (result) return result; } else if (device->power.flags.explicit_get) { Loading @@ -230,59 +205,33 @@ int acpi_bus_get_power(acpi_handle handle, int *state) NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; device->power.state = (int)psc; *state = (int)psc; } *state = device->power.state; } else { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", device->pnp.bus_id, device->power.state)); device->pnp.bus_id, *state)); return 0; } EXPORT_SYMBOL(acpi_bus_get_power); int acpi_bus_set_power(acpi_handle handle, int state) static int __acpi_bus_set_power(struct acpi_device *device, int state) { int result = 0; acpi_status status = AE_OK; struct acpi_device *device = NULL; char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; result = acpi_bus_get_device(handle, &device); if (result) return result; if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) return -EINVAL; /* Make sure this is a valid target state */ if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", kobject_name(&device->dev.kobj))); return -ENODEV; } /* * Get device's current power state */ if (!acpi_power_nocheck) { /* * Maybe the incorrect power state is returned on the bogus * bios, which is different with the real power state. * For example: the bios returns D0 state and the real power * state is D3. OS expects to set the device to D0 state. In * such case if OS uses the power state returned by the BIOS, * the device can't be transisted to the correct power state. * So if the acpi_power_nocheck is set, it is unnecessary to * get the power state by calling acpi_bus_get_power. */ acpi_bus_get_power(device->handle, &device->power.state); } if ((state == device->power.state) && !device->flags.force_power_state) { if (state == device->power.state) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); return 0; Loading Loading @@ -351,8 +300,75 @@ int acpi_bus_set_power(acpi_handle handle, int state) return result; } int acpi_bus_set_power(acpi_handle handle, int state) { struct acpi_device *device; int result; result = acpi_bus_get_device(handle, &device); if (result) return result; if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] is not power manageable\n", dev_name(&device->dev))); return -ENODEV; } return __acpi_bus_set_power(device, state); } EXPORT_SYMBOL(acpi_bus_set_power); int acpi_bus_init_power(struct acpi_device *device) { int state; int result; if (!device) return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; result = __acpi_bus_get_power(device, &state); if (result) return result; if (device->power.flags.power_resources) result = acpi_power_on_resources(device, state); if (!result) device->power.state = state; return result; } int acpi_bus_update_power(acpi_handle handle, int *state_p) { struct acpi_device *device; int state; int result; result = acpi_bus_get_device(handle, &device); if (result) return result; result = __acpi_bus_get_power(device, &state); if (result) return result; result = __acpi_bus_set_power(device, state); if (!result && state_p) *state_p = state; return result; } EXPORT_SYMBOL_GPL(acpi_bus_update_power); bool acpi_bus_power_manageable(acpi_handle handle) { struct acpi_device *device; Loading Loading @@ -1023,15 +1039,8 @@ static int __init acpi_init(void) if (acpi_disabled) return result; /* * If the laptop falls into the DMI check table, the power state check * will be disabled in the course of device power transition. */ dmi_check_system(power_nocheck_dmi_table); acpi_scan_init(); acpi_ec_init(); acpi_power_init(); acpi_debugfs_init(); acpi_sleep_proc_init(); acpi_wakeup_device_init(); Loading
drivers/acpi/fan.c +7 −20 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long if (!device) return -EINVAL; result = acpi_bus_get_power(device->handle, &acpi_state); result = acpi_bus_update_power(device->handle, &acpi_state); if (result) return result; Loading Loading @@ -123,7 +123,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = { static int acpi_fan_add(struct acpi_device *device) { int result = 0; int state = 0; struct thermal_cooling_device *cdev; if (!device) Loading @@ -132,16 +131,12 @@ static int acpi_fan_add(struct acpi_device *device) strcpy(acpi_device_name(device), "Fan"); strcpy(acpi_device_class(device), ACPI_FAN_CLASS); result = acpi_bus_get_power(device->handle, &state); result = acpi_bus_update_power(device->handle, NULL); if (result) { printk(KERN_ERR PREFIX "Reading power state\n"); printk(KERN_ERR PREFIX "Setting initial power state\n"); goto end; } device->flags.force_power_state = 1; acpi_bus_set_power(device->handle, state); device->flags.force_power_state = 0; cdev = thermal_cooling_device_register("Fan", device, &fan_cooling_ops); if (IS_ERR(cdev)) { Loading Loading @@ -200,22 +195,14 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) static int acpi_fan_resume(struct acpi_device *device) { int result = 0; int power_state = 0; int result; if (!device) return -EINVAL; result = acpi_bus_get_power(device->handle, &power_state); if (result) { printk(KERN_ERR PREFIX "Error reading fan power state\n"); return result; } device->flags.force_power_state = 1; acpi_bus_set_power(device->handle, power_state); device->flags.force_power_state = 0; result = acpi_bus_update_power(device->handle, NULL); if (result) printk(KERN_ERR PREFIX "Error updating fan power state\n"); return result; } Loading
drivers/acpi/internal.h +3 −2 Original line number Diff line number Diff line Loading @@ -41,9 +41,10 @@ static inline int acpi_debugfs_init(void) { return 0; } int acpi_power_init(void); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_power_get_inferred_state(struct acpi_device *device); int acpi_power_get_inferred_state(struct acpi_device *device, int *state); int acpi_power_on_resources(struct acpi_device *device, int state); int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; int acpi_bus_init_power(struct acpi_device *device); int acpi_wakeup_device_init(void); void acpi_early_processor_set_pdc(void); Loading
drivers/acpi/power.c +50 −40 Original line number Diff line number Diff line Loading @@ -56,9 +56,6 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF int acpi_power_nocheck; module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); static int acpi_power_add(struct acpi_device *device); static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); Loading Loading @@ -266,6 +263,35 @@ static int acpi_power_off_device(acpi_handle handle) return result; } static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) { int i; for (i = num_res - 1; i >= 0 ; i--) acpi_power_off_device(list->handles[i]); } static void acpi_power_off_list(struct acpi_handle_list *list) { __acpi_power_off_list(list, list->count); } static int acpi_power_on_list(struct acpi_handle_list *list) { int result = 0; int i; for (i = 0; i < list->count; i++) { result = acpi_power_on(list->handles[i]); if (result) { __acpi_power_off_list(list, i); break; } } return result; } /** * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in * ACPI 3.0) _PSW (Power State Wake) Loading Loading @@ -423,19 +449,16 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) Device Power Management -------------------------------------------------------------------------- */ int acpi_power_get_inferred_state(struct acpi_device *device) int acpi_power_get_inferred_state(struct acpi_device *device, int *state) { int result = 0; struct acpi_handle_list *list = NULL; int list_state = 0; int i = 0; if (!device) if (!device || !state) return -EINVAL; device->power.state = ACPI_STATE_UNKNOWN; /* * We know a device's inferred power state when all the resources * required for a given D-state are 'on'. Loading @@ -450,22 +473,26 @@ int acpi_power_get_inferred_state(struct acpi_device *device) return result; if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { device->power.state = i; *state = i; return 0; } } device->power.state = ACPI_STATE_D3; *state = ACPI_STATE_D3; return 0; } int acpi_power_on_resources(struct acpi_device *device, int state) { if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) return -EINVAL; return acpi_power_on_list(&device->power.states[state].resources); } int acpi_power_transition(struct acpi_device *device, int state) { int result = 0; struct acpi_handle_list *cl = NULL; /* Current Resources */ struct acpi_handle_list *tl = NULL; /* Target Resources */ int i = 0; int result; if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) return -EINVAL; Loading @@ -477,37 +504,20 @@ int acpi_power_transition(struct acpi_device *device, int state) || (device->power.state > ACPI_STATE_D3)) return -ENODEV; cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; /* TBD: Resources must be ordered. */ /* * First we reference all power resources required in the target list * (e.g. so the device doesn't lose power while transitioning). * (e.g. so the device doesn't lose power while transitioning). Then, * we dereference all power resources used in the current list. */ for (i = 0; i < tl->count; i++) { result = acpi_power_on(tl->handles[i]); if (result) goto end; } result = acpi_power_on_list(&device->power.states[state].resources); if (!result) acpi_power_off_list( &device->power.states[device->power.state].resources); /* * Then we dereference all power resources used in the current list. */ for (i = 0; i < cl->count; i++) { result = acpi_power_off_device(cl->handles[i]); if (result) goto end; } end: if (result) device->power.state = ACPI_STATE_UNKNOWN; else { /* We shouldn't change the state till all above operations succeed */ device->power.state = state; } /* We shouldn't change the state unless the above operations succeed. */ device->power.state = result ? ACPI_STATE_UNKNOWN : state; return result; } Loading
drivers/acpi/scan.c +23 −4 Original line number Diff line number Diff line Loading @@ -847,6 +847,8 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) return 0; } static void acpi_bus_add_power_resource(acpi_handle handle); static int acpi_bus_get_power_flags(struct acpi_device *device) { acpi_status status = 0; Loading Loading @@ -875,8 +877,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) acpi_evaluate_reference(device->handle, object_name, NULL, &ps->resources); if (ps->resources.count) { int j; device->power.flags.power_resources = 1; ps->flags.valid = 1; for (j = 0; j < ps->resources.count; j++) acpi_bus_add_power_resource(ps->resources.handles[j]); } /* Evaluate "_PSx" to see if we can do explicit sets */ Loading @@ -901,10 +907,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) device->power.states[ACPI_STATE_D3].flags.valid = 1; device->power.states[ACPI_STATE_D3].power = 0; /* TBD: System wake support and resource requirements. */ device->power.state = ACPI_STATE_UNKNOWN; acpi_bus_get_power(device->handle, &(device->power.state)); acpi_bus_init_power(device); return 0; } Loading Loading @@ -1326,6 +1329,20 @@ static int acpi_add_single_object(struct acpi_device **child, #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, ACPI_STA_DEFAULT, &ops); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, unsigned long long *sta) { Loading Loading @@ -1573,6 +1590,8 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } acpi_power_init(); /* * Enumerate devices in the ACPI namespace. */ Loading