Merge branch 'pm-cpufreq'
Merge cpufreq updates for 6.17-rc1: - Fix two initialization ordering issues in the cpufreq core and a governor initialization error path in it, and clean it up (Lifeng Zheng) - Add Granite Rapids support in no-HWP mode to the intel_pstate cpufreq driver (Li RongQing) - Make intel_pstate always use HWP_DESIRED_PERF in passive mode (Rafael Wysocki) - Allow building the tegra124 cpufreq driver as a module (Aaron Kling) - Do minor cleanups for Rust cpufreq and cpumask APIs and fix MAINTAINERS entry for cpu.rs (Abhinav Ananthu, Ritvik Gupta, Lukas Bulwahn) - Clean up assorted cpufreq drivers (Arnd Bergmann, Dan Carpenter, Krzysztof Kozlowski, Sven Peter, Svyatoslav Ryhel, Lifeng Zheng) - Add the NEED_UPDATE_LIMITS flag to the CPPC cpufreq driver (Prashant Malani) - Fix minimum performance state label error in the amd-pstate driver documentation (Shouye Liu) - Add the CPUFREQ_GOV_STRICT_TARGET flag to the userspace cpufreq governor and explain HW coordination influence on it in the documentation (Shashank Balaji) * pm-cpufreq: (27 commits) cpufreq: CPPC: Mark driver with NEED_UPDATE_LIMITS flag Documentation: amd-pstate:fix minimum performance state label error drivers: cpufreq: add Tegra114 support rust: cpumask: Replace `MaybeUninit` and `mem::zeroed` with `Opaque` APIs cpufreq: Exit governor when failed to start old governor cpufreq: Move the check of cpufreq_driver->get into cpufreq_verify_current_freq() cpufreq: Init policy->rwsem before it may be possibly used cpufreq: Initialize cpufreq-based frequency-invariance later cpufreq: Remove duplicate check in __cpufreq_offline() cpufreq: Contain scaling_cur_freq.attr in cpufreq_attrs cpufreq: intel_pstate: Add Granite Rapids support in no-HWP mode cpufreq: intel_pstate: Always use HWP_DESIRED_PERF in passive mode cpufreq: tegra124: Allow building as a module cpufreq: dt: Add register helper cpufreq: Export disable_cpufreq() cpufreq: armada-8k: Fix off by one in armada_8k_cpufreq_free_table() cpufreq: armada-8k: make both cpu masks static rust: cpufreq: use c_ types from kernel prelude rust: cpufreq: Ensure C ABI compatibility in all unsafe cpufreq: brcmstb-avs: Fully open-code compatible for grepping ...
This commit is contained in:
@@ -72,7 +72,7 @@ to manage each performance update behavior. ::
|
||||
Lowest non- | | | |
|
||||
linear perf ------>+-----------------------+ +-----------------------+
|
||||
| | | |
|
||||
| | Lowest perf ---->| |
|
||||
| | Min perf ---->| |
|
||||
| | | |
|
||||
Lowest perf ------>+-----------------------+ +-----------------------+
|
||||
| | | |
|
||||
|
||||
@@ -398,7 +398,9 @@ policy limits change after that.
|
||||
|
||||
This governor does not do anything by itself. Instead, it allows user space
|
||||
to set the CPU frequency for the policy it is attached to by writing to the
|
||||
``scaling_setspeed`` attribute of that policy.
|
||||
``scaling_setspeed`` attribute of that policy. Though the intention may be to
|
||||
set an exact frequency for the policy, the actual frequency may vary depending
|
||||
on hardware coordination, thermal and power limits, and other factors.
|
||||
|
||||
``schedutil``
|
||||
-------------
|
||||
|
||||
@@ -6256,7 +6256,7 @@ F: include/linux/cpuhotplug.h
|
||||
F: include/linux/smpboot.h
|
||||
F: kernel/cpu.c
|
||||
F: kernel/smpboot.*
|
||||
F: rust/helper/cpu.c
|
||||
F: rust/helpers/cpu.c
|
||||
F: rust/kernel/cpu.rs
|
||||
|
||||
CPU IDLE TIME MANAGEMENT FRAMEWORK
|
||||
|
||||
@@ -28,7 +28,6 @@ config ARM_APPLE_SOC_CPUFREQ
|
||||
tristate "Apple Silicon SoC CPUFreq support"
|
||||
depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
|
||||
select PM_OPP
|
||||
default ARCH_APPLE
|
||||
help
|
||||
This adds the CPUFreq driver for Apple Silicon machines
|
||||
(e.g. Apple M1).
|
||||
@@ -238,7 +237,7 @@ config ARM_TEGRA20_CPUFREQ
|
||||
This adds the CPUFreq driver support for Tegra20/30 SOCs.
|
||||
|
||||
config ARM_TEGRA124_CPUFREQ
|
||||
bool "Tegra124 CPUFreq support"
|
||||
tristate "Tegra124 CPUFreq support"
|
||||
depends on ARCH_TEGRA || COMPILE_TEST
|
||||
depends on CPUFREQ_DT
|
||||
default ARCH_TEGRA
|
||||
|
||||
@@ -103,7 +103,7 @@ static void armada_8k_cpufreq_free_table(struct freq_table *freq_tables)
|
||||
{
|
||||
int opps_index, nb_cpus = num_possible_cpus();
|
||||
|
||||
for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) {
|
||||
for (opps_index = 0 ; opps_index < nb_cpus; opps_index++) {
|
||||
int i;
|
||||
|
||||
/* If cpu_dev is NULL then we reached the end of the array */
|
||||
@@ -132,7 +132,7 @@ static int __init armada_8k_cpufreq_init(void)
|
||||
int ret = 0, opps_index = 0, cpu, nb_cpus;
|
||||
struct freq_table *freq_tables;
|
||||
struct device_node *node;
|
||||
static struct cpumask cpus;
|
||||
static struct cpumask cpus, shared_cpus;
|
||||
|
||||
node = of_find_matching_node_and_match(NULL, armada_8k_cpufreq_of_match,
|
||||
NULL);
|
||||
@@ -154,7 +154,6 @@ static int __init armada_8k_cpufreq_init(void)
|
||||
* divisions of it).
|
||||
*/
|
||||
for_each_cpu(cpu, &cpus) {
|
||||
struct cpumask shared_cpus;
|
||||
struct device *cpu_dev;
|
||||
struct clk *clk;
|
||||
|
||||
|
||||
@@ -765,7 +765,7 @@ static void brcm_avs_cpufreq_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id brcm_avs_cpufreq_match[] = {
|
||||
{ .compatible = BRCM_AVS_CPU_DATA },
|
||||
{ .compatible = "brcm,avs-cpu-data-mem" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, brcm_avs_cpufreq_match);
|
||||
|
||||
@@ -26,14 +26,6 @@
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
|
||||
/*
|
||||
* This list contains information parsed from per CPU ACPI _CPC and _PSD
|
||||
* structures: e.g. the highest and lowest supported performance, capabilities,
|
||||
* desired performance, level requested etc. Depending on the share_type, not
|
||||
* all CPUs will have an entry in the list.
|
||||
*/
|
||||
static LIST_HEAD(cpu_data_list);
|
||||
|
||||
static struct cpufreq_driver cppc_cpufreq_driver;
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
|
||||
@@ -352,7 +344,6 @@ static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu)
|
||||
#if defined(CONFIG_ARM64) && defined(CONFIG_ENERGY_MODEL)
|
||||
|
||||
static DEFINE_PER_CPU(unsigned int, efficiency_class);
|
||||
static void cppc_cpufreq_register_em(struct cpufreq_policy *policy);
|
||||
|
||||
/* Create an artificial performance state every CPPC_EM_CAP_STEP capacity unit. */
|
||||
#define CPPC_EM_CAP_STEP (20)
|
||||
@@ -488,7 +479,19 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int populate_efficiency_class(void)
|
||||
static void cppc_cpufreq_register_em(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cppc_cpudata *cpu_data;
|
||||
struct em_data_callback em_cb =
|
||||
EM_ADV_DATA_CB(cppc_get_cpu_power, cppc_get_cpu_cost);
|
||||
|
||||
cpu_data = policy->driver_data;
|
||||
em_dev_register_perf_domain(get_cpu_device(policy->cpu),
|
||||
get_perf_level_count(policy), &em_cb,
|
||||
cpu_data->shared_cpu_map, 0);
|
||||
}
|
||||
|
||||
static void populate_efficiency_class(void)
|
||||
{
|
||||
struct acpi_madt_generic_interrupt *gicc;
|
||||
DECLARE_BITMAP(used_classes, 256) = {};
|
||||
@@ -503,7 +506,7 @@ static int populate_efficiency_class(void)
|
||||
if (bitmap_weight(used_classes, 256) <= 1) {
|
||||
pr_debug("Efficiency classes are all equal (=%d). "
|
||||
"No EM registered", class);
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -520,26 +523,11 @@ static int populate_efficiency_class(void)
|
||||
index++;
|
||||
}
|
||||
cppc_cpufreq_driver.register_em = cppc_cpufreq_register_em;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cppc_cpufreq_register_em(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cppc_cpudata *cpu_data;
|
||||
struct em_data_callback em_cb =
|
||||
EM_ADV_DATA_CB(cppc_get_cpu_power, cppc_get_cpu_cost);
|
||||
|
||||
cpu_data = policy->driver_data;
|
||||
em_dev_register_perf_domain(get_cpu_device(policy->cpu),
|
||||
get_perf_level_count(policy), &em_cb,
|
||||
cpu_data->shared_cpu_map, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
static int populate_efficiency_class(void)
|
||||
static void populate_efficiency_class(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -567,8 +555,6 @@ static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu)
|
||||
goto free_mask;
|
||||
}
|
||||
|
||||
list_add(&cpu_data->node, &cpu_data_list);
|
||||
|
||||
return cpu_data;
|
||||
|
||||
free_mask:
|
||||
@@ -583,7 +569,6 @@ static void cppc_cpufreq_put_cpu_data(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cppc_cpudata *cpu_data = policy->driver_data;
|
||||
|
||||
list_del(&cpu_data->node);
|
||||
free_cpumask_var(cpu_data->shared_cpu_map);
|
||||
kfree(cpu_data);
|
||||
policy->driver_data = NULL;
|
||||
@@ -925,7 +910,7 @@ static struct freq_attr *cppc_cpufreq_attr[] = {
|
||||
};
|
||||
|
||||
static struct cpufreq_driver cppc_cpufreq_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS,
|
||||
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
|
||||
.verify = cppc_verify_policy,
|
||||
.target = cppc_cpufreq_set_target,
|
||||
.get = cppc_cpufreq_get_rate,
|
||||
@@ -954,24 +939,10 @@ static int __init cppc_cpufreq_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void free_cpu_data(void)
|
||||
{
|
||||
struct cppc_cpudata *iter, *tmp;
|
||||
|
||||
list_for_each_entry_safe(iter, tmp, &cpu_data_list, node) {
|
||||
free_cpumask_var(iter->shared_cpu_map);
|
||||
list_del(&iter->node);
|
||||
kfree(iter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void __exit cppc_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cppc_cpufreq_driver);
|
||||
cppc_freq_invariance_exit();
|
||||
|
||||
free_cpu_data();
|
||||
}
|
||||
|
||||
module_exit(cppc_cpufreq_exit);
|
||||
|
||||
@@ -143,6 +143,7 @@ static const struct of_device_id blocklist[] __initconst = {
|
||||
|
||||
{ .compatible = "nvidia,tegra20", },
|
||||
{ .compatible = "nvidia,tegra30", },
|
||||
{ .compatible = "nvidia,tegra114", },
|
||||
{ .compatible = "nvidia,tegra124", },
|
||||
{ .compatible = "nvidia,tegra210", },
|
||||
{ .compatible = "nvidia,tegra234", },
|
||||
|
||||
@@ -329,6 +329,17 @@ static struct platform_driver dt_cpufreq_platdrv = {
|
||||
};
|
||||
module_platform_driver(dt_cpufreq_platdrv);
|
||||
|
||||
struct platform_device *cpufreq_dt_pdev_register(struct device *dev)
|
||||
{
|
||||
struct platform_device_info cpufreq_dt_devinfo = {};
|
||||
|
||||
cpufreq_dt_devinfo.name = "cpufreq-dt";
|
||||
cpufreq_dt_devinfo.parent = dev;
|
||||
|
||||
return platform_device_register_full(&cpufreq_dt_devinfo);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dt_pdev_register);
|
||||
|
||||
MODULE_ALIAS("platform:cpufreq-dt");
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
||||
MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
|
||||
|
||||
@@ -22,4 +22,6 @@ struct cpufreq_dt_platform_data {
|
||||
int (*resume)(struct cpufreq_policy *policy);
|
||||
};
|
||||
|
||||
struct platform_device *cpufreq_dt_pdev_register(struct device *dev);
|
||||
|
||||
#endif /* __CPUFREQ_DT_H__ */
|
||||
|
||||
@@ -109,6 +109,8 @@ void disable_cpufreq(void)
|
||||
{
|
||||
off = 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(disable_cpufreq);
|
||||
|
||||
static DEFINE_MUTEX(cpufreq_governor_mutex);
|
||||
|
||||
bool have_governor_per_policy(void)
|
||||
@@ -967,6 +969,7 @@ static struct attribute *cpufreq_attrs[] = {
|
||||
&cpuinfo_min_freq.attr,
|
||||
&cpuinfo_max_freq.attr,
|
||||
&cpuinfo_transition_latency.attr,
|
||||
&scaling_cur_freq.attr,
|
||||
&scaling_min_freq.attr,
|
||||
&scaling_max_freq.attr,
|
||||
&affected_cpus.attr,
|
||||
@@ -1095,10 +1098,6 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cpufreq_driver->bios_limit) {
|
||||
ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
|
||||
if (ret)
|
||||
@@ -1284,6 +1283,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
|
||||
goto err_free_real_cpus;
|
||||
}
|
||||
|
||||
init_rwsem(&policy->rwsem);
|
||||
|
||||
freq_constraints_init(&policy->constraints);
|
||||
|
||||
policy->nb_min.notifier_call = cpufreq_notifier_min;
|
||||
@@ -1306,7 +1307,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&policy->policy_list);
|
||||
init_rwsem(&policy->rwsem);
|
||||
spin_lock_init(&policy->transition_lock);
|
||||
init_waitqueue_head(&policy->transition_wait);
|
||||
INIT_WORK(&policy->update, handle_update);
|
||||
@@ -1694,14 +1694,13 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_target())
|
||||
if (has_target()) {
|
||||
strscpy(policy->last_governor, policy->governor->name,
|
||||
CPUFREQ_NAME_LEN);
|
||||
else
|
||||
policy->last_policy = policy->policy;
|
||||
|
||||
if (has_target())
|
||||
cpufreq_exit_governor(policy);
|
||||
} else {
|
||||
policy->last_policy = policy->policy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the ->offline() during light-weight tear-down, as
|
||||
@@ -1803,6 +1802,9 @@ static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, b
|
||||
{
|
||||
unsigned int new_freq;
|
||||
|
||||
if (!cpufreq_driver->get)
|
||||
return 0;
|
||||
|
||||
new_freq = cpufreq_driver->get(policy->cpu);
|
||||
if (!new_freq)
|
||||
return 0;
|
||||
@@ -1925,10 +1927,7 @@ unsigned int cpufreq_get(unsigned int cpu)
|
||||
|
||||
guard(cpufreq_policy_read)(policy);
|
||||
|
||||
if (cpufreq_driver->get)
|
||||
return __cpufreq_get(policy);
|
||||
|
||||
return 0;
|
||||
return __cpufreq_get(policy);
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_get);
|
||||
|
||||
@@ -2482,8 +2481,7 @@ int cpufreq_start_governor(struct cpufreq_policy *policy)
|
||||
|
||||
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
|
||||
|
||||
if (cpufreq_driver->get)
|
||||
cpufreq_verify_current_freq(policy, false);
|
||||
cpufreq_verify_current_freq(policy, false);
|
||||
|
||||
if (policy->governor->start) {
|
||||
ret = policy->governor->start(policy);
|
||||
@@ -2715,10 +2713,12 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
|
||||
pr_debug("starting governor %s failed\n", policy->governor->name);
|
||||
if (old_gov) {
|
||||
policy->governor = old_gov;
|
||||
if (cpufreq_init_governor(policy))
|
||||
if (cpufreq_init_governor(policy)) {
|
||||
policy->governor = NULL;
|
||||
else
|
||||
cpufreq_start_governor(policy);
|
||||
} else if (cpufreq_start_governor(policy)) {
|
||||
cpufreq_exit_governor(policy);
|
||||
policy->governor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2944,15 +2944,6 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
|
||||
cpufreq_driver = driver_data;
|
||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||
|
||||
/*
|
||||
* Mark support for the scheduler's frequency invariance engine for
|
||||
* drivers that implement target(), target_index() or fast_switch().
|
||||
*/
|
||||
if (!cpufreq_driver->setpolicy) {
|
||||
static_branch_enable_cpuslocked(&cpufreq_freq_invariance);
|
||||
pr_debug("supports frequency invariance");
|
||||
}
|
||||
|
||||
if (driver_data->setpolicy)
|
||||
driver_data->flags |= CPUFREQ_CONST_LOOPS;
|
||||
|
||||
@@ -2983,6 +2974,15 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
|
||||
hp_online = ret;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Mark support for the scheduler's frequency invariance engine for
|
||||
* drivers that implement target(), target_index() or fast_switch().
|
||||
*/
|
||||
if (!cpufreq_driver->setpolicy) {
|
||||
static_branch_enable_cpuslocked(&cpufreq_freq_invariance);
|
||||
pr_debug("supports frequency invariance");
|
||||
}
|
||||
|
||||
pr_debug("driver %s up and running\n", driver_data->name);
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ static struct cpufreq_governor cpufreq_gov_userspace = {
|
||||
.store_setspeed = cpufreq_set,
|
||||
.show_setspeed = show_speed,
|
||||
.owner = THIS_MODULE,
|
||||
.flags = CPUFREQ_GOV_STRICT_TARGET,
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
|
||||
|
||||
@@ -2775,6 +2775,8 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
||||
X86_MATCH(INTEL_TIGERLAKE, core_funcs),
|
||||
X86_MATCH(INTEL_SAPPHIRERAPIDS_X, core_funcs),
|
||||
X86_MATCH(INTEL_EMERALDRAPIDS_X, core_funcs),
|
||||
X86_MATCH(INTEL_GRANITERAPIDS_D, core_funcs),
|
||||
X86_MATCH(INTEL_GRANITERAPIDS_X, core_funcs),
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
|
||||
@@ -3249,8 +3251,8 @@ static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy,
|
||||
int max_pstate = policy->strict_target ?
|
||||
target_pstate : cpu->max_perf_ratio;
|
||||
|
||||
intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate, 0,
|
||||
fast_switch);
|
||||
intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate,
|
||||
target_pstate, fast_switch);
|
||||
} else if (target_pstate != old_pstate) {
|
||||
intel_cpufreq_perf_ctl_update(cpu, target_pstate, fast_switch);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "cpufreq-dt.h"
|
||||
|
||||
static struct platform_device *tegra124_cpufreq_pdev;
|
||||
|
||||
struct tegra124_cpufreq_priv {
|
||||
struct clk *cpu_clk;
|
||||
struct clk *pllp_clk;
|
||||
@@ -55,7 +59,6 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
|
||||
struct device_node *np __free(device_node) = of_cpu_device_node_get(0);
|
||||
struct tegra124_cpufreq_priv *priv;
|
||||
struct device *cpu_dev;
|
||||
struct platform_device_info cpufreq_dt_devinfo = {};
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
@@ -95,11 +98,7 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto out_put_pllp_clk;
|
||||
|
||||
cpufreq_dt_devinfo.name = "cpufreq-dt";
|
||||
cpufreq_dt_devinfo.parent = &pdev->dev;
|
||||
|
||||
priv->cpufreq_dt_pdev =
|
||||
platform_device_register_full(&cpufreq_dt_devinfo);
|
||||
priv->cpufreq_dt_pdev = cpufreq_dt_pdev_register(&pdev->dev);
|
||||
if (IS_ERR(priv->cpufreq_dt_pdev)) {
|
||||
ret = PTR_ERR(priv->cpufreq_dt_pdev);
|
||||
goto out_put_pllp_clk;
|
||||
@@ -173,6 +172,21 @@ disable_cpufreq:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra124_cpufreq_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra124_cpufreq_priv *priv = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (!IS_ERR(priv->cpufreq_dt_pdev)) {
|
||||
platform_device_unregister(priv->cpufreq_dt_pdev);
|
||||
priv->cpufreq_dt_pdev = ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
clk_put(priv->pllp_clk);
|
||||
clk_put(priv->pllx_clk);
|
||||
clk_put(priv->dfll_clk);
|
||||
clk_put(priv->cpu_clk);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra124_cpufreq_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(tegra124_cpufreq_suspend,
|
||||
tegra124_cpufreq_resume)
|
||||
@@ -182,15 +196,16 @@ static struct platform_driver tegra124_cpufreq_platdrv = {
|
||||
.driver.name = "cpufreq-tegra124",
|
||||
.driver.pm = &tegra124_cpufreq_pm_ops,
|
||||
.probe = tegra124_cpufreq_probe,
|
||||
.remove = tegra124_cpufreq_remove,
|
||||
};
|
||||
|
||||
static int __init tegra_cpufreq_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (!(of_machine_is_compatible("nvidia,tegra124") ||
|
||||
of_machine_is_compatible("nvidia,tegra210")))
|
||||
if (!(of_machine_is_compatible("nvidia,tegra114") ||
|
||||
of_machine_is_compatible("nvidia,tegra124") ||
|
||||
of_machine_is_compatible("nvidia,tegra210")))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
@@ -201,15 +216,25 @@ static int __init tegra_cpufreq_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pdev = platform_device_register_simple("cpufreq-tegra124", -1, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
tegra124_cpufreq_pdev = platform_device_register_simple("cpufreq-tegra124", -1, NULL, 0);
|
||||
if (IS_ERR(tegra124_cpufreq_pdev)) {
|
||||
platform_driver_unregister(&tegra124_cpufreq_platdrv);
|
||||
return PTR_ERR(pdev);
|
||||
return PTR_ERR(tegra124_cpufreq_pdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(tegra_cpufreq_init);
|
||||
|
||||
static void __exit tegra_cpufreq_module_exit(void)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(tegra124_cpufreq_pdev))
|
||||
platform_device_unregister(tegra124_cpufreq_pdev);
|
||||
|
||||
platform_driver_unregister(&tegra124_cpufreq_platdrv);
|
||||
}
|
||||
module_exit(tegra_cpufreq_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Tuomas Tynkkynen <ttynkkynen@nvidia.com>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for NVIDIA Tegra124");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -139,7 +139,6 @@ struct cppc_perf_fb_ctrs {
|
||||
|
||||
/* Per CPU container for runtime CPPC management. */
|
||||
struct cppc_cpudata {
|
||||
struct list_head node;
|
||||
struct cppc_perf_caps perf_caps;
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
struct cppc_perf_fb_ctrs perf_fb_ctrs;
|
||||
|
||||
@@ -1061,7 +1061,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1094,7 +1094,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1109,9 +1109,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn offline_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1126,9 +1124,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn suspend_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1143,7 +1139,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1171,9 +1167,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn verify_callback(
|
||||
ptr: *mut bindings::cpufreq_policy_data,
|
||||
) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1188,9 +1182,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn setpolicy_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1207,9 +1199,9 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn target_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
target_freq: u32,
|
||||
relation: u32,
|
||||
) -> kernel::ffi::c_int {
|
||||
target_freq: c_uint,
|
||||
relation: c_uint,
|
||||
) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1226,8 +1218,8 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn target_index_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
index: u32,
|
||||
) -> kernel::ffi::c_int {
|
||||
index: c_uint,
|
||||
) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1249,8 +1241,8 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn fast_switch_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
target_freq: u32,
|
||||
) -> kernel::ffi::c_uint {
|
||||
target_freq: c_uint,
|
||||
) -> c_uint {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
let policy = unsafe { Policy::from_raw_mut(ptr) };
|
||||
@@ -1263,10 +1255,10 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
unsafe extern "C" fn adjust_perf_callback(
|
||||
cpu: u32,
|
||||
min_perf: usize,
|
||||
target_perf: usize,
|
||||
capacity: usize,
|
||||
cpu: c_uint,
|
||||
min_perf: c_ulong,
|
||||
target_perf: c_ulong,
|
||||
capacity: c_ulong,
|
||||
) {
|
||||
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
|
||||
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
|
||||
@@ -1284,8 +1276,8 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn get_intermediate_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
index: u32,
|
||||
) -> kernel::ffi::c_uint {
|
||||
index: c_uint,
|
||||
) -> c_uint {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
let policy = unsafe { Policy::from_raw_mut(ptr) };
|
||||
@@ -1305,8 +1297,8 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn target_intermediate_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
index: u32,
|
||||
) -> kernel::ffi::c_int {
|
||||
index: c_uint,
|
||||
) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
@@ -1325,7 +1317,7 @@ impl<T: Driver> Registration<T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
|
||||
unsafe extern "C" fn get_callback(cpu: c_uint) -> c_uint {
|
||||
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
|
||||
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
|
||||
|
||||
@@ -1351,7 +1343,7 @@ impl<T: Driver> Registration<T> {
|
||||
///
|
||||
/// - This function may only be called from the cpufreq C infrastructure.
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
|
||||
unsafe extern "C" fn bios_limit_callback(cpu: c_int, limit: *mut c_uint) -> c_int {
|
||||
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
|
||||
let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
|
||||
|
||||
@@ -1371,8 +1363,8 @@ impl<T: Driver> Registration<T> {
|
||||
/// - The pointer arguments must be valid pointers.
|
||||
unsafe extern "C" fn set_boost_callback(
|
||||
ptr: *mut bindings::cpufreq_policy,
|
||||
state: i32,
|
||||
) -> kernel::ffi::c_int {
|
||||
state: c_int,
|
||||
) -> c_int {
|
||||
from_result(|| {
|
||||
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
|
||||
// lifetime of `policy`.
|
||||
|
||||
@@ -14,9 +14,6 @@ use crate::{
|
||||
#[cfg(CONFIG_CPUMASK_OFFSTACK)]
|
||||
use core::ptr::{self, NonNull};
|
||||
|
||||
#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
/// A CPU Mask.
|
||||
@@ -239,10 +236,7 @@ impl CpumaskVar {
|
||||
},
|
||||
|
||||
#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
|
||||
// SAFETY: FFI type is valid to be zero-initialized.
|
||||
//
|
||||
// INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
|
||||
mask: unsafe { core::mem::zeroed() },
|
||||
mask: Cpumask(Opaque::zeroed()),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -266,10 +260,7 @@ impl CpumaskVar {
|
||||
NonNull::new(ptr.cast()).ok_or(AllocError)?
|
||||
},
|
||||
#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
|
||||
// SAFETY: Guaranteed by the safety requirements of the function.
|
||||
//
|
||||
// INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
|
||||
mask: unsafe { MaybeUninit::uninit().assume_init() },
|
||||
mask: Cpumask(Opaque::uninit()),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user