mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:24:45 +01:00
Merge branches 'acpi-scan', 'acpi-processor' and 'acpi-sysfs'
Merge an ACPI device enumeration update, ACPI processor driver updates, and an ACPI sysfs-related code update for 6.18-rc1: - Add Intel CVS ACPI HIDs to acpi_ignore_dep_ids[] so it is not regarded as real dependency (Hans de Goede) - Use ACPI_FREE() for freeing an ACPI object in description_show() in the ACPI sysfs-related code (Kaushlendra Kumar) - Fix memory leak in the ACPI processor idle driver registration error code path and optimize ACPI idle driver registration (Huisong Li, Rafael Wysocki) - Add module import namespace to the ACPI processor idle driver (Rafael Wysocki) - Eliminate static variable flat_state_cnt from the ACPI processor idle driver (Rafael Wysocki) - Release cpufreq policy references using __free() in the ACPI processor thremal driver (Zihuan Zhang) - Remove unused empty stubs of some functions and rearrange function declarations in a header file in the ACPI processor driver (Huisong Li) - Redefine two functions as void in the ACPI processor driver (Rafael Wysocki) - Do not expose global variable acpi_idle_driver in the ACPI processor driver (Huisong Li) * acpi-scan: ACPI: scan: Add Intel CVS ACPI HIDs to acpi_ignore_dep_ids[] * acpi-processor: ACPI: processor: Do not expose global variable acpi_idle_driver ACPI: processor: idle: Redefine two functions as void ACPI: processor: Update cpuidle driver check in __acpi_processor_start() ACPI: processor: idle: Rearrange declarations in header file ACPI: processor: Remove unused empty stubs of some functions ACPI: processor: thermal: Release policy references using __free() ACPI: processor: idle: Fix function defined but not used warning ACPI: processor: idle: Eliminate static variable flat_state_cnt ACPI: processor: idle: Add module import namespace ACPI: processor: idle: Optimize ACPI idle driver registration ACPI: processor: idle: Fix memory leak when register cpuidle device failed * acpi-sysfs: ACPI: sysfs: Use ACPI_FREE() for freeing an ACPI object
This commit is contained in:
commit
be61a77818
7 changed files with 126 additions and 117 deletions
|
|
@ -815,7 +815,7 @@ bool acpi_processor_claim_cst_control(void)
|
|||
cst_control_claimed = true;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_claim_cst_control);
|
||||
EXPORT_SYMBOL_NS_GPL(acpi_processor_claim_cst_control, "ACPI_PROCESSOR_IDLE");
|
||||
|
||||
/**
|
||||
* acpi_processor_evaluate_cst - Evaluate the processor _CST control method.
|
||||
|
|
@ -994,5 +994,5 @@ end:
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_evaluate_cst);
|
||||
EXPORT_SYMBOL_NS_GPL(acpi_processor_evaluate_cst, "ACPI_PROCESSOR_IDLE");
|
||||
#endif /* CONFIG_ACPI_PROCESSOR_CSTATE */
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ static ssize_t description_show(struct device *dev,
|
|||
|
||||
buf[result++] = '\n';
|
||||
|
||||
kfree(str_obj);
|
||||
ACPI_FREE(str_obj);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,8 +166,7 @@ static int __acpi_processor_start(struct acpi_device *device)
|
|||
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
|
||||
dev_dbg(&device->dev, "CPPC data invalid or not present\n");
|
||||
|
||||
if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
|
||||
acpi_processor_power_init(pr);
|
||||
acpi_processor_power_init(pr);
|
||||
|
||||
acpi_pss_perf_init(pr);
|
||||
|
||||
|
|
@ -263,6 +262,8 @@ static int __init acpi_processor_driver_init(void)
|
|||
if (result < 0)
|
||||
return result;
|
||||
|
||||
acpi_processor_register_idle_driver();
|
||||
|
||||
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
||||
"acpi/cpu-drv:online",
|
||||
acpi_soft_cpu_online, NULL);
|
||||
|
|
@ -301,6 +302,7 @@ static void __exit acpi_processor_driver_exit(void)
|
|||
|
||||
cpuhp_remove_state_nocalls(hp_online);
|
||||
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
|
||||
acpi_processor_unregister_idle_driver();
|
||||
driver_unregister(&acpi_processor_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ module_param(latency_factor, uint, 0644);
|
|||
|
||||
static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
|
||||
|
||||
struct cpuidle_driver acpi_idle_driver = {
|
||||
static struct cpuidle_driver acpi_idle_driver = {
|
||||
.name = "acpi_idle",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
|
@ -998,11 +998,6 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* flat_state_cnt - the number of composite LPI states after the process of flattening
|
||||
*/
|
||||
static int flat_state_cnt;
|
||||
|
||||
/**
|
||||
* combine_lpi_states - combine local and parent LPI states to form a composite LPI state
|
||||
*
|
||||
|
|
@ -1045,9 +1040,10 @@ static void stash_composite_state(struct acpi_lpi_states_array *curr_level,
|
|||
curr_level->composite_states[curr_level->composite_states_size++] = t;
|
||||
}
|
||||
|
||||
static int flatten_lpi_states(struct acpi_processor *pr,
|
||||
struct acpi_lpi_states_array *curr_level,
|
||||
struct acpi_lpi_states_array *prev_level)
|
||||
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;
|
||||
|
|
@ -1087,7 +1083,7 @@ static int flatten_lpi_states(struct acpi_processor *pr,
|
|||
}
|
||||
|
||||
kfree(curr_level->entries);
|
||||
return 0;
|
||||
return flat_state_cnt;
|
||||
}
|
||||
|
||||
int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
|
||||
|
|
@ -1102,6 +1098,7 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
|
|||
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;
|
||||
|
||||
/* make sure our architecture has support */
|
||||
ret = acpi_processor_ffh_lpi_probe(pr->id);
|
||||
|
|
@ -1114,14 +1111,13 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
|
|||
if (!acpi_has_method(handle, "_LPI"))
|
||||
return -EINVAL;
|
||||
|
||||
flat_state_cnt = 0;
|
||||
prev = &info[0];
|
||||
curr = &info[1];
|
||||
handle = pr->handle;
|
||||
ret = acpi_processor_evaluate_lpi(handle, prev);
|
||||
if (ret)
|
||||
return ret;
|
||||
flatten_lpi_states(pr, prev, NULL);
|
||||
state_count = flatten_lpi_states(pr, 0, prev, NULL);
|
||||
|
||||
status = acpi_get_parent(handle, &pr_ahandle);
|
||||
while (ACPI_SUCCESS(status)) {
|
||||
|
|
@ -1143,18 +1139,19 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
|
|||
break;
|
||||
|
||||
/* flatten all the LPI states in this level of hierarchy */
|
||||
flatten_lpi_states(pr, curr, prev);
|
||||
state_count = flatten_lpi_states(pr, state_count, curr, prev);
|
||||
|
||||
tmp = prev, prev = curr, curr = tmp;
|
||||
|
||||
status = acpi_get_parent(handle, &pr_ahandle);
|
||||
}
|
||||
|
||||
pr->power.count = flat_state_cnt;
|
||||
/* reset the index after flattening */
|
||||
for (i = 0; i < pr->power.count; i++)
|
||||
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;
|
||||
pr->flags.power = 1;
|
||||
|
|
@ -1360,74 +1357,102 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_processor_registered;
|
||||
|
||||
int acpi_processor_power_init(struct acpi_processor *pr)
|
||||
void acpi_processor_register_idle_driver(void)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
int ret = -ENODEV;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* Acpi idle driver is used by all possible CPUs.
|
||||
* Install the idle handler by the processor power info of one in them.
|
||||
* Note that we use previously set idle handler will be used on
|
||||
* platforms that only support C1.
|
||||
*/
|
||||
for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) {
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
ret = acpi_processor_get_power_info(pr);
|
||||
if (!ret) {
|
||||
pr->flags.power_setup_done = 1;
|
||||
acpi_processor_setup_cpuidle_states(pr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
pr_debug("No ACPI power information from any CPUs.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (ret) {
|
||||
pr_debug("register %s failed.\n", acpi_idle_driver.name);
|
||||
return;
|
||||
}
|
||||
pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
|
||||
}
|
||||
|
||||
void acpi_processor_unregister_idle_driver(void)
|
||||
{
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
}
|
||||
|
||||
void acpi_processor_power_init(struct acpi_processor *pr)
|
||||
{
|
||||
int retval;
|
||||
struct cpuidle_device *dev;
|
||||
|
||||
/*
|
||||
* The code below only works if the current cpuidle driver is the ACPI
|
||||
* idle driver.
|
||||
*/
|
||||
if (cpuidle_get_driver() != &acpi_idle_driver)
|
||||
return;
|
||||
|
||||
if (disabled_by_idle_boot_param())
|
||||
return 0;
|
||||
return;
|
||||
|
||||
acpi_processor_cstate_first_run_checks();
|
||||
|
||||
if (!acpi_processor_get_power_info(pr))
|
||||
pr->flags.power_setup_done = 1;
|
||||
|
||||
if (!pr->flags.power)
|
||||
return;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = dev;
|
||||
|
||||
acpi_processor_setup_cpuidle_dev(pr, dev);
|
||||
|
||||
/*
|
||||
* Install the idle handler if processor power management is supported.
|
||||
* Note that we use previously set idle handler will be used on
|
||||
* platforms that only support C1.
|
||||
* Register a cpuidle device for this CPU. The cpuidle driver using
|
||||
* this device is expected to be registered.
|
||||
*/
|
||||
if (pr->flags.power) {
|
||||
/* Register acpi_idle_driver if not already registered */
|
||||
if (!acpi_processor_registered) {
|
||||
acpi_processor_setup_cpuidle_states(pr);
|
||||
retval = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (retval)
|
||||
return retval;
|
||||
pr_debug("%s registered with cpuidle\n",
|
||||
acpi_idle_driver.name);
|
||||
}
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = dev;
|
||||
|
||||
acpi_processor_setup_cpuidle_dev(pr, dev);
|
||||
|
||||
/* Register per-cpu cpuidle_device. Cpuidle driver
|
||||
* must already be registered before registering device
|
||||
*/
|
||||
retval = cpuidle_register_device(dev);
|
||||
if (retval) {
|
||||
if (acpi_processor_registered == 0)
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
return retval;
|
||||
}
|
||||
acpi_processor_registered++;
|
||||
if (cpuidle_register_device(dev)) {
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
|
||||
kfree(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
void acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
{
|
||||
struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
|
||||
|
||||
if (disabled_by_idle_boot_param())
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (pr->flags.power) {
|
||||
cpuidle_unregister_device(dev);
|
||||
acpi_processor_registered--;
|
||||
if (acpi_processor_registered == 0)
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
pr->flags.power_setup_done = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_IMPORT_NS("ACPI_PROCESSOR_IDLE");
|
||||
|
|
|
|||
|
|
@ -62,19 +62,14 @@ static int phys_package_first_cpu(int cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_has_cpufreq(unsigned int cpu)
|
||||
static bool cpu_has_cpufreq(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
if (!acpi_processor_cpufreq_init)
|
||||
return 0;
|
||||
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
if (policy) {
|
||||
cpufreq_cpu_put(policy);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
|
||||
|
||||
return policy != NULL;
|
||||
}
|
||||
|
||||
static int cpufreq_get_max_state(unsigned int cpu)
|
||||
|
|
@ -93,12 +88,31 @@ static int cpufreq_get_cur_state(unsigned int cpu)
|
|||
return reduction_step(cpu);
|
||||
}
|
||||
|
||||
static bool cpufreq_update_thermal_limit(unsigned int cpu, struct acpi_processor *pr)
|
||||
{
|
||||
unsigned long max_freq;
|
||||
int ret;
|
||||
|
||||
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
|
||||
if (!policy)
|
||||
return false;
|
||||
|
||||
max_freq = (policy->cpuinfo.max_freq *
|
||||
(100 - reduction_step(cpu) * cpufreq_thermal_reduction_pctg)) / 100;
|
||||
|
||||
ret = freq_qos_update_request(&pr->thermal_req, max_freq);
|
||||
if (ret < 0) {
|
||||
pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n",
|
||||
pr->id, ret);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cpufreq_set_cur_state(unsigned int cpu, int state)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
struct acpi_processor *pr;
|
||||
unsigned long max_freq;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
if (!cpu_has_cpufreq(cpu))
|
||||
return 0;
|
||||
|
|
@ -120,20 +134,8 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
|
|||
if (unlikely(!freq_qos_request_active(&pr->thermal_req)))
|
||||
continue;
|
||||
|
||||
policy = cpufreq_cpu_get(i);
|
||||
if (!policy)
|
||||
if (!cpufreq_update_thermal_limit(i, pr))
|
||||
return -EINVAL;
|
||||
|
||||
max_freq = (policy->cpuinfo.max_freq *
|
||||
(100 - reduction_step(i) * cpufreq_thermal_reduction_pctg)) / 100;
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
|
||||
ret = freq_qos_update_request(&pr->thermal_req, max_freq);
|
||||
if (ret < 0) {
|
||||
pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n",
|
||||
pr->id, ret);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -845,6 +845,8 @@ static bool acpi_info_matches_ids(struct acpi_device_info *info,
|
|||
static const char * const acpi_ignore_dep_ids[] = {
|
||||
"PNP0D80", /* Windows-compatible System Power Management Controller */
|
||||
"INT33BD", /* Intel Baytrail Mailbox Device */
|
||||
"INTC10DE", /* Intel CVS LNL */
|
||||
"INTC10E0", /* Intel CVS ARL */
|
||||
"LATT2021", /* Lattice FW Update Client Driver */
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -417,32 +417,15 @@ static inline void acpi_processor_throttling_init(void) {}
|
|||
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
|
||||
|
||||
/* in processor_idle.c */
|
||||
extern struct cpuidle_driver acpi_idle_driver;
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
||||
int acpi_processor_power_init(struct acpi_processor *pr);
|
||||
int acpi_processor_power_exit(struct acpi_processor *pr);
|
||||
void acpi_processor_power_init(struct acpi_processor *pr);
|
||||
void acpi_processor_power_exit(struct acpi_processor *pr);
|
||||
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
|
||||
int acpi_processor_hotplug(struct acpi_processor *pr);
|
||||
#else
|
||||
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_hotplug(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
void acpi_processor_register_idle_driver(void);
|
||||
void acpi_processor_unregister_idle_driver(void);
|
||||
int acpi_processor_ffh_lpi_probe(unsigned int cpu);
|
||||
int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
|
||||
#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
|
||||
|
||||
/* in processor_thermal.c */
|
||||
|
|
@ -465,11 +448,6 @@ static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
|
|||
}
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
||||
extern int acpi_processor_ffh_lpi_probe(unsigned int cpu);
|
||||
extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
|
||||
#endif
|
||||
|
||||
void acpi_processor_init_invariance_cppc(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue