^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Added processor hotplug support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <acpi/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cpufeature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PREFIX "ACPI: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define ACPI_PROCESSOR_CLASS "processor"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define _COMPONENT ACPI_PROCESSOR_COMPONENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ACPI_MODULE_NAME("processor_perflib");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static DEFINE_MUTEX(performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * _PPC support is implemented as a CPUfreq policy notifier:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * This means each time a CPUfreq driver registered also with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * the ACPI core is asked to change the speed policy, the maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * value is adjusted so that it is within the platform limit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * Also, when a new platform limit value is detected, the CPUfreq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * policy is adjusted accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* ignore_ppc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * ignore _PPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * 0 -> cpufreq low level drivers initialized -> consider _PPC values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * 1 -> ignore _PPC totally -> forced by user through boot param
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int ignore_ppc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param(ignore_ppc, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "limited by BIOS, this should help");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static bool acpi_processor_ppc_in_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) acpi_status status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long long ppc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * _PPC indicates the maximum state currently supported by the platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (status != AE_NOT_FOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) acpi_processor_ppc_in_use = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) (int)ppc, ppc ? "" : "not");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pr->performance_platform_limit = (int)ppc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (ppc >= pr->performance->state_count ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unlikely(!freq_qos_request_active(&pr->perflib_req)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ret = freq_qos_update_request(&pr->perflib_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pr->performance->states[ppc].core_frequency * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pr->id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @handle: ACPI processor handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @status: the status code of _PPC evaluation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * 0: success. OSPM is now using the performance state specificed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * 1: failure. OSPM has not changed the number of P-states in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void acpi_processor_ppc_ost(acpi_handle handle, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (acpi_has_method(handle, "_OST"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) acpi_evaluate_ost(handle, ACPI_PROCESSOR_NOTIFY_PERFORMANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) status, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (ignore_ppc || !pr->performance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Only when it is notification event, the _OST object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * will be evaluated. Otherwise it is skipped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (event_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) acpi_processor_ppc_ost(pr->handle, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ret = acpi_processor_get_platform_limit(pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Only when it is notification event, the _OST object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * will be evaluated. Otherwise it is skipped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (event_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) acpi_processor_ppc_ost(pr->handle, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) acpi_processor_ppc_ost(pr->handle, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cpufreq_update_limits(pr->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct acpi_processor *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr = per_cpu(processors, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!pr || !pr->performance || !pr->performance->state_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *limit = pr->performance->states[pr->performance_platform_limit].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) core_frequency * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) EXPORT_SYMBOL(acpi_processor_get_bios_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void acpi_processor_ignore_ppc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (ignore_ppc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ignore_ppc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) void acpi_processor_ppc_init(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) for_each_cpu(cpu, policy->related_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct acpi_processor *pr = per_cpu(processors, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = freq_qos_add_request(&policy->constraints,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) &pr->perflib_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) FREQ_QOS_MAX, INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pr_err("Failed to add freq constraint for CPU%d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) cpu, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) for_each_cpu(cpu, policy->related_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct acpi_processor *pr = per_cpu(processors, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) freq_qos_remove_request(&pr->perflib_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int acpi_processor_get_performance_control(struct acpi_processor *pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) acpi_status status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) union acpi_object *pct = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) union acpi_object obj = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pct = (union acpi_object *)buffer.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) || (pct->package.count != 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) printk(KERN_ERR PREFIX "Invalid _PCT data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * control_register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) obj = pct->package.elements[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if ((obj.type != ACPI_TYPE_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) || (obj.buffer.length < sizeof(struct acpi_pct_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) || (obj.buffer.pointer == NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) memcpy(&pr->performance->control_register, obj.buffer.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) sizeof(struct acpi_pct_register));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * status_register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) obj = pct->package.elements[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if ((obj.type != ACPI_TYPE_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) || (obj.buffer.length < sizeof(struct acpi_pct_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) || (obj.buffer.pointer == NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) memcpy(&pr->performance->status_register, obj.buffer.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sizeof(struct acpi_pct_register));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kfree(buffer.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * Some AMDs have 50MHz frequency multiples, but only provide 100MHz rounding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * in their ACPI data. Calculate the real values and fix up the _PSS data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u32 hi, lo, fid, did;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int index = px->control & 0x00000007;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) || boot_cpu_data.x86 == 0x11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * MSR C001_0064+:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!(hi & BIT(31)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) fid = lo & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) did = (lo >> 6) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (boot_cpu_data.x86 == 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) px->core_frequency = (100 * (fid + 0x10)) >> did;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) px->core_frequency = (100 * (fid + 8)) >> did;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int acpi_processor_get_performance_states(struct acpi_processor *pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct acpi_buffer state = { 0, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) union acpi_object *pss = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int last_invalid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pss = buffer.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) printk(KERN_ERR PREFIX "Invalid _PSS data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pss->package.count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pr->performance->state_count = pss->package.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pr->performance->states =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) kmalloc_array(pss->package.count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) sizeof(struct acpi_processor_px),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!pr->performance->states) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (i = 0; i < pr->performance->state_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct acpi_processor_px *px = &(pr->performance->states[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) state.length = sizeof(struct acpi_processor_px);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) state.pointer = px;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) status = acpi_extract_package(&(pss->package.elements[i]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) &format, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) kfree(pr->performance->states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) amd_fixup_frequency(px, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) (u32) px->core_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) (u32) px->power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) (u32) px->transition_latency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) (u32) px->bus_master_latency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) (u32) px->control, (u32) px->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (!px->core_frequency ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ((u32)(px->core_frequency * 1000) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) (px->core_frequency * 1000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) printk(KERN_ERR FW_BUG PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pr->id, px->core_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (last_invalid == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) last_invalid = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (last_invalid != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Copy this valid entry over last_invalid entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) memcpy(&(pr->performance->states[last_invalid]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) px, sizeof(struct acpi_processor_px));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ++last_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (last_invalid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) printk(KERN_ERR FW_BUG PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) "No valid BIOS _PSS frequency found for processor %d\n", pr->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) kfree(pr->performance->states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pr->performance->states = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (last_invalid > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pr->performance->state_count = last_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) kfree(buffer.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int acpi_processor_get_performance_info(struct acpi_processor *pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!pr || !pr->performance || !pr->handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!acpi_has_method(pr->handle, "_PCT")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) "ACPI-based processor performance control unavailable\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) result = acpi_processor_get_performance_control(pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto update_bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) result = acpi_processor_get_performance_states(pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto update_bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* We need to call _PPC once when cpufreq starts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ignore_ppc != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) result = acpi_processor_get_platform_limit(pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * the BIOS is older than the CPU and does not know its frequencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) update_bios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (acpi_has_method(pr->handle, "_PPC")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if(boot_cpu_has(X86_FEATURE_EST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) "frequency support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) int acpi_processor_pstate_control(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) (u32)acpi_gbl_FADT.pstate_control, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (ACPI_SUCCESS(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ACPI_EXCEPTION((AE_INFO, status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) "Failed to write pstate_control [0x%x] to smi_command [0x%x]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int acpi_processor_notify_smm(struct module *calling_module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static int is_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (!acpi_processor_cpufreq_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (!try_module_get(calling_module))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* is_done is set to negative if an error occurred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * and to postitive if _no_ error occurred, but SMM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * was already notified. This avoids double notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * which might lead to unexpected results...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (is_done > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) module_put(calling_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) } else if (is_done < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) module_put(calling_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return is_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) is_done = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) result = acpi_processor_pstate_control();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) module_put(calling_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) module_put(calling_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* Success. If there's no _PPC, we need to fear nothing, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * we can allow the cpufreq driver to be rmmod'ed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) is_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (!acpi_processor_ppc_in_use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) module_put(calling_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) EXPORT_SYMBOL(acpi_processor_notify_smm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct acpi_buffer state = {0, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) union acpi_object *psd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) status = acpi_evaluate_object(handle, "_PSD", NULL, &buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) psd = buffer.pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) printk(KERN_ERR PREFIX "Invalid _PSD data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (psd->package.count != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) printk(KERN_ERR PREFIX "Invalid _PSD data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) state.length = sizeof(struct acpi_psd_package);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) state.pointer = pdomain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) status = acpi_extract_package(&(psd->package.elements[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) &format, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) printk(KERN_ERR PREFIX "Invalid _PSD data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) printk(KERN_ERR PREFIX "Invalid _PSD:coord_type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) kfree(buffer.pointer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) EXPORT_SYMBOL(acpi_processor_get_psd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int acpi_processor_preregister_performance(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct acpi_processor_performance __percpu *performance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int count_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) cpumask_var_t covered_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct acpi_processor *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct acpi_psd_package *pdomain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct acpi_processor *match_pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct acpi_psd_package *match_pdomain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mutex_lock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * Check if another driver has already registered, and abort before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * changing pr->performance if it has. Check input data as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) for_each_possible_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pr = per_cpu(processors, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (!pr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Look only at processors in ACPI namespace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (pr->performance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) retval = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (!performance || !per_cpu_ptr(performance, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Call _PSD for all CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) for_each_possible_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) pr = per_cpu(processors, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (!pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) pr->performance = per_cpu_ptr(performance, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) cpumask_set_cpu(i, pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) pdomain = &(pr->performance->domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (acpi_processor_get_psd(pr->handle, pdomain)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) goto err_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * Now that we have _PSD data from all CPUs, lets setup P-state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * domain info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) for_each_possible_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) pr = per_cpu(processors, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (cpumask_test_cpu(i, covered_cpus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) pdomain = &(pr->performance->domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) cpumask_set_cpu(i, pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) cpumask_set_cpu(i, covered_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (pdomain->num_processors <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* Validate the Domain info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) count_target = pdomain->num_processors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for_each_possible_cpu(j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (i == j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) match_pr = per_cpu(processors, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!match_pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) match_pdomain = &(match_pr->performance->domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (match_pdomain->domain != pdomain->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* Here i and j are in the same domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (match_pdomain->num_processors != count_target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) goto err_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (pdomain->coord_type != match_pdomain->coord_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) goto err_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) cpumask_set_cpu(j, covered_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cpumask_set_cpu(j, pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) for_each_possible_cpu(j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (i == j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) match_pr = per_cpu(processors, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!match_pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) match_pdomain = &(match_pr->performance->domain_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (match_pdomain->domain != pdomain->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) match_pr->performance->shared_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) pr->performance->shared_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) cpumask_copy(match_pr->performance->shared_cpu_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) err_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) for_each_possible_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pr = per_cpu(processors, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!pr || !pr->performance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* Assume no coordination on any error parsing domain info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) cpumask_clear(pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) cpumask_set_cpu(i, pr->performance->shared_cpu_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) pr->performance = NULL; /* Will be set for real in register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) free_cpumask_var(covered_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) EXPORT_SYMBOL(acpi_processor_preregister_performance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) acpi_processor_register_performance(struct acpi_processor_performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *performance, unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct acpi_processor *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (!acpi_processor_cpufreq_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) mutex_lock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) pr = per_cpu(processors, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!pr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (pr->performance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) WARN_ON(!performance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) pr->performance = performance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (acpi_processor_get_performance_info(pr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) pr->performance = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) EXPORT_SYMBOL(acpi_processor_register_performance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) void acpi_processor_unregister_performance(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct acpi_processor *pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) mutex_lock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) pr = per_cpu(processors, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (!pr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (pr->performance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) kfree(pr->performance->states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pr->performance = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) mutex_unlock(&performance_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) EXPORT_SYMBOL(acpi_processor_unregister_performance);