Commit be61a778 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,

	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 */
+1 −1
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ static ssize_t description_show(struct device *dev,

	buf[result++] = '\n';

	kfree(str_obj);
	ACPI_FREE(str_obj);

	return result;
}
+4 −2
Original line number Diff line number Diff line
@@ -166,7 +166,6 @@ 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_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);
}

+82 −57
Original line number Diff line number Diff line
@@ -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 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle,
	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,7 +1040,8 @@ 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,
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)
{
@@ -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;
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;
	}

int acpi_processor_power_init(struct acpi_processor *pr)
	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;

	/*
	 * 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.
	 */
	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);
		}
	if (!pr->flags.power)
		return;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
			return -ENOMEM;
		return;

	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
	/*
	 * Register a cpuidle device for this CPU.  The cpuidle driver using
	 * this device is expected to be registered.
	 */
		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");
+27 −25
Original line number Diff line number Diff line
@@ -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;
}
Loading