diff options
Diffstat (limited to 'drivers/acpi/processor_perflib.c')
| -rw-r--r-- | drivers/acpi/processor_perflib.c | 138 |
1 files changed, 75 insertions, 63 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 757a98f6d7a2..4265814c74f8 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -53,6 +53,8 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; unsigned long long ppc = 0; + s32 qos_value; + int index; int ret; if (!pr) @@ -72,17 +74,30 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) } } + index = ppc; + + if (pr->performance_platform_limit == index || + ppc >= pr->performance->state_count) + return 0; + pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, - (int)ppc, ppc ? "" : "not"); + index, index ? "is" : "is not"); - pr->performance_platform_limit = (int)ppc; + pr->performance_platform_limit = index; - if (ppc >= pr->performance->state_count || - unlikely(!freq_qos_request_active(&pr->perflib_req))) + if (unlikely(!freq_qos_request_active(&pr->perflib_req))) return 0; - ret = freq_qos_update_request(&pr->perflib_req, - pr->performance->states[ppc].core_frequency * 1000); + /* + * If _PPC returns 0, it means that all of the available states can be + * used ("no limit"). + */ + if (index == 0) + qos_value = FREQ_QOS_MAX_DEFAULT_VALUE; + else + qos_value = pr->performance->states[index].core_frequency * 1000; + + ret = freq_qos_update_request(&pr->perflib_req, qos_value); if (ret < 0) { pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", pr->id, ret); @@ -142,6 +157,7 @@ int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) pr = per_cpu(processors, cpu); if (!pr || !pr->performance || !pr->performance->state_count) return -ENODEV; + *limit = pr->performance->states[pr->performance_platform_limit]. core_frequency * 1000; return 0; @@ -165,9 +181,16 @@ void acpi_processor_ppc_init(struct cpufreq_policy *policy) if (!pr) continue; + /* + * Reset performance_platform_limit in case there is a stale + * value in it, so as to make it match the "no limit" QoS value + * below. + */ + pr->performance_platform_limit = 0; + ret = freq_qos_add_request(&policy->constraints, - &pr->perflib_req, - FREQ_QOS_MAX, INT_MAX); + &pr->perflib_req, FREQ_QOS_MAX, + FREQ_QOS_MAX_DEFAULT_VALUE); if (ret < 0) pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, ret); @@ -201,8 +224,7 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) } pct = (union acpi_object *)buffer.pointer; - if (!pct || (pct->type != ACPI_TYPE_PACKAGE) - || (pct->package.count != 2)) { + if (!pct || pct->type != ACPI_TYPE_PACKAGE || pct->package.count != 2) { pr_err("Invalid _PCT data\n"); result = -EFAULT; goto end; @@ -214,9 +236,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) obj = pct->package.elements[0]; - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { + if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER || + obj.buffer.length < sizeof(struct acpi_pct_register)) { pr_err("Invalid _PCT data (control_register)\n"); result = -EFAULT; goto end; @@ -230,9 +251,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) obj = pct->package.elements[1]; - if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { + if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER || + obj.buffer.length < sizeof(struct acpi_pct_register)) { pr_err("Invalid _PCT data (status_register)\n"); result = -EFAULT; goto end; @@ -260,8 +280,8 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return; - if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) - || boot_cpu_data.x86 == 0x11) { + if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || + boot_cpu_data.x86 == 0x11) { rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); /* * MSR C001_0064+: @@ -300,7 +320,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) } pss = buffer.pointer; - if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { + if (!pss || pss->type != ACPI_TYPE_PACKAGE) { pr_err("Invalid _PSS data\n"); result = -EFAULT; goto end; @@ -353,8 +373,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq */ if (!px->core_frequency || - ((u32)(px->core_frequency * 1000) != - (px->core_frequency * 1000))) { + (u32)(px->core_frequency * 1000) != px->core_frequency * 1000) { pr_err(FW_BUG "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n", pr->id, px->core_frequency); @@ -456,7 +475,7 @@ int acpi_processor_pstate_control(void) int acpi_processor_notify_smm(struct module *calling_module) { static int is_done; - int result; + int result = 0; if (!acpi_processor_cpufreq_init) return -EBUSY; @@ -464,42 +483,41 @@ int acpi_processor_notify_smm(struct module *calling_module) if (!try_module_get(calling_module)) return -EINVAL; - /* is_done is set to negative if an error occurred, - * and to postitive if _no_ error occurred, but SMM - * was already notified. This avoids double notification - * which might lead to unexpected results... + /* + * is_done is set to negative if an error occurs and to 1 if no error + * occurrs, but SMM has been notified already. This avoids repeated + * notification which might lead to unexpected results. */ - if (is_done > 0) { - module_put(calling_module); - return 0; - } else if (is_done < 0) { - module_put(calling_module); - return is_done; - } + if (is_done != 0) { + if (is_done < 0) + result = is_done; - is_done = -EIO; + goto out_put; + } result = acpi_processor_pstate_control(); - if (!result) { - pr_debug("No SMI port or pstate_control\n"); - module_put(calling_module); - return 0; - } - if (result < 0) { - module_put(calling_module); - return result; + if (result <= 0) { + if (result) { + is_done = result; + } else { + pr_debug("No SMI port or pstate_control\n"); + is_done = 1; + } + goto out_put; } - /* Success. If there's no _PPC, we need to fear nothing, so - * we can allow the cpufreq driver to be rmmod'ed. */ is_done = 1; + /* + * Success. If there _PPC, unloading the cpufreq driver would be risky, + * so disallow it in that case. + */ + if (acpi_processor_ppc_in_use) + return 0; - if (!acpi_processor_ppc_in_use) - module_put(calling_module); - - return 0; +out_put: + module_put(calling_module); + return result; } - EXPORT_SYMBOL(acpi_processor_notify_smm); int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) @@ -517,7 +535,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) } psd = buffer.pointer; - if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { + if (!psd || psd->type != ACPI_TYPE_PACKAGE) { pr_err("Invalid _PSD data\n"); result = -EFAULT; goto end; @@ -532,8 +550,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain) state.length = sizeof(struct acpi_psd_package); state.pointer = pdomain; - status = acpi_extract_package(&(psd->package.elements[0]), - &format, &state); + status = acpi_extract_package(&(psd->package.elements[0]), &format, &state); if (ACPI_FAILURE(status)) { pr_err("Invalid _PSD data\n"); result = -EFAULT; @@ -716,9 +733,8 @@ err_out: } EXPORT_SYMBOL(acpi_processor_preregister_performance); -int -acpi_processor_register_performance(struct acpi_processor_performance - *performance, unsigned int cpu) +int acpi_processor_register_performance(struct acpi_processor_performance + *performance, unsigned int cpu) { struct acpi_processor *pr; @@ -751,7 +767,6 @@ acpi_processor_register_performance(struct acpi_processor_performance mutex_unlock(&performance_mutex); return 0; } - EXPORT_SYMBOL(acpi_processor_register_performance); void acpi_processor_unregister_performance(unsigned int cpu) @@ -761,18 +776,15 @@ void acpi_processor_unregister_performance(unsigned int cpu) mutex_lock(&performance_mutex); pr = per_cpu(processors, cpu); - if (!pr) { - mutex_unlock(&performance_mutex); - return; - } + if (!pr) + goto unlock; if (pr->performance) kfree(pr->performance->states); + pr->performance = NULL; +unlock: mutex_unlock(&performance_mutex); - - return; } - EXPORT_SYMBOL(acpi_processor_unregister_performance); |