summaryrefslogtreecommitdiff
path: root/drivers/acpi/processor_idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r--drivers/acpi/processor_idle.c269
1 files changed, 2 insertions, 267 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 4482cf28f56a..e113bcbbb882 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -853,223 +853,6 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
#endif /* CONFIG_ACPI_PROCESSOR_CSTATE */
-struct acpi_lpi_states_array {
- unsigned int size;
- unsigned int composite_states_size;
- struct acpi_lpi_state *entries;
- struct acpi_lpi_state *composite_states[ACPI_PROCESSOR_MAX_POWER];
-};
-
-static int obj_get_integer(union acpi_object *obj, u32 *value)
-{
- if (obj->type != ACPI_TYPE_INTEGER)
- return -EINVAL;
-
- *value = obj->integer.value;
- return 0;
-}
-
-static int acpi_processor_evaluate_lpi(acpi_handle handle,
- struct acpi_lpi_states_array *info)
-{
- acpi_status status;
- int ret = 0;
- int pkg_count, state_idx = 1, loop;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *lpi_data;
- struct acpi_lpi_state *lpi_state;
-
- status = acpi_evaluate_object(handle, "_LPI", NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_handle_debug(handle, "No _LPI, giving up\n");
- return -ENODEV;
- }
-
- lpi_data = buffer.pointer;
-
- /* There must be at least 4 elements = 3 elements + 1 package */
- if (!lpi_data || lpi_data->type != ACPI_TYPE_PACKAGE ||
- lpi_data->package.count < 4) {
- pr_debug("not enough elements in _LPI\n");
- ret = -ENODATA;
- goto end;
- }
-
- pkg_count = lpi_data->package.elements[2].integer.value;
-
- /* Validate number of power states. */
- if (pkg_count < 1 || pkg_count != lpi_data->package.count - 3) {
- pr_debug("count given by _LPI is not valid\n");
- ret = -ENODATA;
- goto end;
- }
-
- lpi_state = kzalloc_objs(*lpi_state, pkg_count);
- if (!lpi_state) {
- ret = -ENOMEM;
- goto end;
- }
-
- info->size = pkg_count;
- info->entries = lpi_state;
-
- /* LPI States start at index 3 */
- for (loop = 3; state_idx <= pkg_count; loop++, state_idx++, lpi_state++) {
- union acpi_object *element, *pkg_elem, *obj;
-
- element = &lpi_data->package.elements[loop];
- if (element->type != ACPI_TYPE_PACKAGE || element->package.count < 7)
- continue;
-
- pkg_elem = element->package.elements;
-
- obj = pkg_elem + 6;
- if (obj->type == ACPI_TYPE_BUFFER) {
- struct acpi_power_register *reg;
-
- reg = (struct acpi_power_register *)obj->buffer.pointer;
- if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
- reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)
- continue;
-
- lpi_state->address = reg->address;
- lpi_state->entry_method =
- reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE ?
- ACPI_CSTATE_FFH : ACPI_CSTATE_SYSTEMIO;
- } else if (obj->type == ACPI_TYPE_INTEGER) {
- lpi_state->entry_method = ACPI_CSTATE_INTEGER;
- lpi_state->address = obj->integer.value;
- } else {
- pr_debug("Entry method of state-%d is invalid, disable it.\n",
- state_idx);
- continue;
- }
-
- /* elements[7,8] skipped for now i.e. Residency/Usage counter*/
-
- obj = pkg_elem + 9;
- if (obj->type == ACPI_TYPE_STRING)
- strscpy(lpi_state->desc, obj->string.pointer,
- ACPI_CX_DESC_LEN);
-
- lpi_state->index = state_idx;
- if (obj_get_integer(pkg_elem + 0, &lpi_state->min_residency)) {
- pr_debug("No min. residency found, assuming 10 us\n");
- lpi_state->min_residency = 10;
- }
-
- if (obj_get_integer(pkg_elem + 1, &lpi_state->wake_latency)) {
- pr_debug("No wakeup residency found, assuming 10 us\n");
- lpi_state->wake_latency = 10;
- }
-
- if (obj_get_integer(pkg_elem + 2, &lpi_state->flags))
- lpi_state->flags = 0;
-
- if (obj_get_integer(pkg_elem + 3, &lpi_state->arch_flags))
- lpi_state->arch_flags = 0;
-
- if (obj_get_integer(pkg_elem + 4, &lpi_state->res_cnt_freq))
- lpi_state->res_cnt_freq = 1;
-
- if (obj_get_integer(pkg_elem + 5, &lpi_state->enable_parent_state))
- lpi_state->enable_parent_state = 0;
- }
-
- acpi_handle_debug(handle, "Found %d power states\n", state_idx);
-end:
- kfree(buffer.pointer);
- return ret;
-}
-
-/**
- * combine_lpi_states - combine local and parent LPI states to form a composite LPI state
- *
- * @local: local LPI state
- * @parent: parent LPI state
- * @result: composite LPI state
- */
-static bool combine_lpi_states(struct acpi_lpi_state *local,
- struct acpi_lpi_state *parent,
- struct acpi_lpi_state *result)
-{
- if (parent->entry_method == ACPI_CSTATE_INTEGER) {
- if (!parent->address) /* 0 means autopromotable */
- return false;
- result->address = local->address + parent->address;
- } else {
- result->address = parent->address;
- }
-
- result->min_residency = max(local->min_residency, parent->min_residency);
- result->wake_latency = local->wake_latency + parent->wake_latency;
- result->enable_parent_state = parent->enable_parent_state;
- result->entry_method = local->entry_method;
-
- result->flags = parent->flags;
- result->arch_flags = parent->arch_flags;
- result->index = parent->index;
-
- scnprintf(result->desc, ACPI_CX_DESC_LEN, "%s+%s", local->desc, parent->desc);
- return true;
-}
-
-#define ACPI_LPI_STATE_FLAGS_ENABLED BIT(0)
-
-static void stash_composite_state(struct acpi_lpi_states_array *curr_level,
- struct acpi_lpi_state *t)
-{
- curr_level->composite_states[curr_level->composite_states_size++] = t;
-}
-
-static unsigned int flatten_lpi_states(struct acpi_processor *pr,
- unsigned int flat_state_cnt,
- struct acpi_lpi_states_array *curr_level,
- struct acpi_lpi_states_array *prev_level)
-{
- int i, j, state_count = curr_level->size;
- struct acpi_lpi_state *p, *t = curr_level->entries;
-
- curr_level->composite_states_size = 0;
- for (j = 0; j < state_count; j++, t++) {
- struct acpi_lpi_state *flpi;
-
- if (!(t->flags & ACPI_LPI_STATE_FLAGS_ENABLED))
- continue;
-
- if (flat_state_cnt >= ACPI_PROCESSOR_MAX_POWER) {
- pr_warn("Limiting number of LPI states to max (%d)\n",
- ACPI_PROCESSOR_MAX_POWER);
- pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
- break;
- }
-
- flpi = &pr->power.lpi_states[flat_state_cnt];
-
- if (!prev_level) { /* leaf/processor node */
- memcpy(flpi, t, sizeof(*t));
- stash_composite_state(curr_level, flpi);
- flat_state_cnt++;
- continue;
- }
-
- for (i = 0; i < prev_level->composite_states_size; i++) {
- p = prev_level->composite_states[i];
- if (t->index <= p->enable_parent_state &&
- combine_lpi_states(p, t, flpi)) {
- stash_composite_state(curr_level, flpi);
- flat_state_cnt++;
- flpi++;
- if (flat_state_cnt >= ACPI_PROCESSOR_MAX_POWER)
- break;
- }
- }
- }
-
- kfree(curr_level->entries);
- return flat_state_cnt;
-}
-
int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
{
return -EOPNOTSUPP;
@@ -1077,64 +860,16 @@ int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
{
- int ret, i;
- acpi_status status;
- acpi_handle handle = pr->handle, pr_ahandle;
- struct acpi_device *d = NULL;
- struct acpi_lpi_states_array info[2], *tmp, *prev, *curr;
- unsigned int state_count;
+ int ret;
/* make sure our architecture has support */
ret = acpi_processor_ffh_lpi_probe(pr->id);
if (ret == -EOPNOTSUPP)
return ret;
- if (!osc_pc_lpi_support_confirmed)
- return -EOPNOTSUPP;
-
- if (!acpi_has_method(handle, "_LPI"))
- return -EINVAL;
-
- prev = &info[0];
- curr = &info[1];
- handle = pr->handle;
- ret = acpi_processor_evaluate_lpi(handle, prev);
+ ret = acpi_processor_extract_lpi_info(pr->handle, &pr->power, false);
if (ret)
return ret;
- state_count = flatten_lpi_states(pr, 0, prev, NULL);
-
- status = acpi_get_parent(handle, &pr_ahandle);
- while (ACPI_SUCCESS(status)) {
- d = acpi_fetch_acpi_dev(pr_ahandle);
- if (!d)
- break;
-
- handle = pr_ahandle;
-
- if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID))
- break;
-
- /* can be optional ? */
- if (!acpi_has_method(handle, "_LPI"))
- break;
-
- ret = acpi_processor_evaluate_lpi(handle, curr);
- if (ret)
- break;
-
- /* flatten all the LPI states in this level of hierarchy */
- state_count = flatten_lpi_states(pr, state_count, curr, prev);
-
- tmp = prev, prev = curr, curr = tmp;
-
- status = acpi_get_parent(handle, &pr_ahandle);
- }
-
- /* reset the index after flattening */
- for (i = 0; i < state_count; i++)
- pr->power.lpi_states[i].index = i;
-
- pr->power.count = state_count;
/* Tell driver that _LPI is supported. */
pr->flags.has_lpi = 1;