CPUFreq arm updates for 7.0

- Update cpufreq-dt-platdev list for tegra, qcom, TI (Aaron Kling,
   Dhruva Gole, and Konrad Dybcio).
 
 - Minor improvements to the cpufreq / cpumask rust implementation
   (Alexandre Courbot, Alice Ryhl, Tamir Duberstein, and Yilin Chen).
 
 - Add support for AM62L3 SoC to ti-cpufreq driver (Dhruva Gole).
 
 - Update FIE arch_freq_scale in ticks for non-PCC regs (Jie Zhan).
 
 - Other minor cleanups / improvements (Felix Gu, Juan Martinez, Luca
   Weiss, and Sergey Shtylyov).
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEx73Crsp7f6M6scA70rkcPK6BEhwFAml4YIcACgkQ0rkcPK6B
 Ehx6hQ//Y8GoICqNQe6IrVQ6b9eJLB/YOP7vPyZuwc0iqT9YWXrMou5xlnmNW/IY
 zj0Wo3l3fidp6eDOo7f21mXALF9yt8kElKq411Oqcg4WVWyAXc9p6ODpWZp/G2/h
 JcmusAkwFPul0XE0QJmlJ54KqtsyjoSWQHtrPzOO54mJEhOL4dWQwqhWP046ed7T
 FVkNRLb7ysY3+weNuAg45SbVJ3FT/a7f8XbdGd5DAz96efbqTyFt+znhfsd3Xti+
 sF75Mq1AEN0Vnfb8ZP4MZUCe7zeVdOVfLFqXXiW/qJOdbRgoD6k2uAOIt2NAcYU/
 sbv6UjaW0NE0oTvKbJ8CLE4IIJudjRgVNjyyGlKHdjBVgMQQk9vr7DIedGLghink
 VABcyerIqhPFGkBkY0IXkLSmhNtKWoLN9w7sMeCwhE34l63Bnie3Sg9JLikRxaXK
 6BAm3+8BiG30tg4WL1LX8UyssnMlUGvvOD9TCP4jOfLQeAk8wWgQ1D+CwWCB5o5j
 jtDwPTOCIN9UQT46lYS+kkqzwf4YTFVdA4c23Tod70gjrtm7Z1a7UzYNxoTGcGS3
 VtrgVnlgPh3/I/95Qpsgoy5D1oeIz9znFoVv6ETPBINy4A4rAsYMA4DEASfM7tIY
 pNhbSTcbtDbp6Eo79hkh5J2ZGoJyTSthrX+irqOz+IQFp8fP9s4=
 =Zz3B
 -----END PGP SIGNATURE-----

Merge tag 'cpufreq-arm-updates-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Pull CPUFreq Arm updates for 7.0 from Viresh Kumar:

"- Update cpufreq-dt-platdev list for tegra, qcom, TI (Aaron Kling,
   Dhruva Gole, and Konrad Dybcio).

 - Minor improvements to the cpufreq / cpumask rust implementation
   (Alexandre Courbot, Alice Ryhl, Tamir Duberstein, and Yilin Chen).

 - Add support for AM62L3 SoC to ti-cpufreq driver (Dhruva Gole).

 - Update FIE arch_freq_scale in ticks for non-PCC regs (Jie Zhan).

 - Other minor cleanups / improvements (Felix Gu, Juan Martinez, Luca
   Weiss, and Sergey Shtylyov)."

* tag 'cpufreq-arm-updates-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: scmi: Fix device_node reference leak in scmi_cpu_domain_id()
  cpufreq: ti-cpufreq: add support for AM62L3 SoC
  cpufreq: dt-platdev: Add ti,am62l3 to blocklist
  cpufreq/amd-pstate: Add comment explaining nominal_perf usage for performance policy
  cpufreq: scmi: correct SCMI explanation
  cpufreq: dt-platdev: Block the driver from probing on more QC platforms
  rust: cpumask: rename methods of Cpumask for clarity and consistency
  cpufreq: CPPC: Update FIE arch_freq_scale in ticks for non-PCC regs
  cpufreq: CPPC: Factor out cppc_fie_kworker_init()
  ACPI: CPPC: Factor out and export per-cpu cppc_perf_ctrs_in_pcc_cpu()
  rust: cpufreq: replace `kernel::c_str!` with C-Strings
  cpufreq: Add Tegra186 and Tegra194 to cpufreq-dt-platdev blocklist
  dt-bindings: cpufreq: qcom-hw: document Milos CPUFREQ Hardware
  rust: cpufreq: add __rust_helper to helpers
  rust: cpufreq: always inline functions using build_assert with arguments
This commit is contained in:
Rafael J. Wysocki 2026-01-27 14:46:28 +01:00
commit b753c3204d
12 changed files with 165 additions and 67 deletions

View file

@ -35,6 +35,7 @@ properties:
- description: v2 of CPUFREQ HW (EPSS)
items:
- enum:
- qcom,milos-cpufreq-epss
- qcom,qcs8300-cpufreq-epss
- qcom,qdu1000-cpufreq-epss
- qcom,sa8255p-cpufreq-epss
@ -169,6 +170,7 @@ allOf:
compatible:
contains:
enum:
- qcom,milos-cpufreq-epss
- qcom,qcs8300-cpufreq-epss
- qcom,sc7280-cpufreq-epss
- qcom,sm8250-cpufreq-epss

View file

@ -1423,6 +1423,32 @@ out_err:
}
EXPORT_SYMBOL_GPL(cppc_get_perf_caps);
/**
* cppc_perf_ctrs_in_pcc_cpu - Check if any perf counters of a CPU are in PCC.
* @cpu: CPU on which to check perf counters.
*
* Return: true if any of the counters are in PCC regions, false otherwise
*/
bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu)
{
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
struct cpc_register_resource *ref_perf_reg;
/*
* If reference perf register is not supported then we should use the
* nominal perf value
*/
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
if (!CPC_SUPPORTED(ref_perf_reg))
ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
return CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]) ||
CPC_IN_PCC(ref_perf_reg);
}
EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc_cpu);
/**
* cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region.
*
@ -1437,27 +1463,7 @@ bool cppc_perf_ctrs_in_pcc(void)
int cpu;
for_each_online_cpu(cpu) {
struct cpc_register_resource *ref_perf_reg;
struct cpc_desc *cpc_desc;
cpc_desc = per_cpu(cpc_desc_ptr, cpu);
if (CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]))
return true;
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
/*
* If reference perf register is not supported then we should
* use the nominal perf value
*/
if (!CPC_SUPPORTED(ref_perf_reg))
ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
if (CPC_IN_PCC(ref_perf_reg))
if (cppc_perf_ctrs_in_pcc_cpu(cpu))
return true;
}

View file

@ -636,6 +636,19 @@ static void amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
WRITE_ONCE(cpudata->max_limit_freq, policy->max);
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
/*
* For performance policy, set MinPerf to nominal_perf rather than
* highest_perf or lowest_nonlinear_perf.
*
* Per commit 0c411b39e4f4c, using highest_perf was observed
* to cause frequency throttling on power-limited platforms, leading to
* performance regressions. Using lowest_nonlinear_perf would limit
* performance too much for HPC workloads requiring high frequency
* operation and minimal wakeup latency from idle states.
*
* nominal_perf therefore provides a balance by avoiding throttling
* while still maintaining enough performance for HPC workloads.
*/
perf.min_limit_perf = min(perf.nominal_perf, perf.max_limit_perf);
WRITE_ONCE(cpudata->min_limit_freq, min(cpudata->nominal_freq, cpudata->max_limit_freq));
} else {

View file

@ -54,31 +54,24 @@ static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0,
struct cppc_perf_fb_ctrs *fb_ctrs_t1);
/**
* cppc_scale_freq_workfn - CPPC arch_freq_scale updater for frequency invariance
* @work: The work item.
* __cppc_scale_freq_tick - CPPC arch_freq_scale updater for frequency invariance
* @cppc_fi: per-cpu CPPC FIE data.
*
* The CPPC driver register itself with the topology core to provide its own
* The CPPC driver registers itself with the topology core to provide its own
* implementation (cppc_scale_freq_tick()) of topology_scale_freq_tick() which
* gets called by the scheduler on every tick.
*
* Note that the arch specific counters have higher priority than CPPC counters,
* if available, though the CPPC driver doesn't need to have any special
* handling for that.
*
* On an invocation of cppc_scale_freq_tick(), we schedule an irq work (since we
* reach here from hard-irq context), which then schedules a normal work item
* and cppc_scale_freq_workfn() updates the per_cpu arch_freq_scale variable
* based on the counter updates since the last tick.
*/
static void cppc_scale_freq_workfn(struct kthread_work *work)
static void __cppc_scale_freq_tick(struct cppc_freq_invariance *cppc_fi)
{
struct cppc_freq_invariance *cppc_fi;
struct cppc_perf_fb_ctrs fb_ctrs = {0};
struct cppc_cpudata *cpu_data;
unsigned long local_freq_scale;
u64 perf;
cppc_fi = container_of(work, struct cppc_freq_invariance, work);
cpu_data = cppc_fi->cpu_data;
if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) {
@ -102,6 +95,24 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
per_cpu(arch_freq_scale, cppc_fi->cpu) = local_freq_scale;
}
static void cppc_scale_freq_tick(void)
{
__cppc_scale_freq_tick(&per_cpu(cppc_freq_inv, smp_processor_id()));
}
static struct scale_freq_data cppc_sftd = {
.source = SCALE_FREQ_SOURCE_CPPC,
.set_freq_scale = cppc_scale_freq_tick,
};
static void cppc_scale_freq_workfn(struct kthread_work *work)
{
struct cppc_freq_invariance *cppc_fi;
cppc_fi = container_of(work, struct cppc_freq_invariance, work);
__cppc_scale_freq_tick(cppc_fi);
}
static void cppc_irq_work(struct irq_work *irq_work)
{
struct cppc_freq_invariance *cppc_fi;
@ -110,7 +121,14 @@ static void cppc_irq_work(struct irq_work *irq_work)
kthread_queue_work(kworker_fie, &cppc_fi->work);
}
static void cppc_scale_freq_tick(void)
/*
* Reading perf counters may sleep if the CPC regs are in PCC. Thus, we
* schedule an irq work in scale_freq_tick (since we reach here from hard-irq
* context), which then schedules a normal work item cppc_scale_freq_workfn()
* that updates the per_cpu arch_freq_scale variable based on the counter
* updates since the last tick.
*/
static void cppc_scale_freq_tick_pcc(void)
{
struct cppc_freq_invariance *cppc_fi = &per_cpu(cppc_freq_inv, smp_processor_id());
@ -121,13 +139,14 @@ static void cppc_scale_freq_tick(void)
irq_work_queue(&cppc_fi->irq_work);
}
static struct scale_freq_data cppc_sftd = {
static struct scale_freq_data cppc_sftd_pcc = {
.source = SCALE_FREQ_SOURCE_CPPC,
.set_freq_scale = cppc_scale_freq_tick,
.set_freq_scale = cppc_scale_freq_tick_pcc,
};
static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
{
struct scale_freq_data *sftd = &cppc_sftd;
struct cppc_freq_invariance *cppc_fi;
int cpu, ret;
@ -138,8 +157,11 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
cppc_fi = &per_cpu(cppc_freq_inv, cpu);
cppc_fi->cpu = cpu;
cppc_fi->cpu_data = policy->driver_data;
kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
if (cppc_perf_ctrs_in_pcc_cpu(cpu)) {
kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
sftd = &cppc_sftd_pcc;
}
ret = cppc_get_perf_ctrs(cpu, &cppc_fi->prev_perf_fb_ctrs);
@ -155,7 +177,7 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
}
/* Register for freq-invariance */
topology_set_scale_freq_source(&cppc_sftd, policy->cpus);
topology_set_scale_freq_source(sftd, policy->cpus);
}
/*
@ -178,13 +200,15 @@ static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy)
topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_CPPC, policy->related_cpus);
for_each_cpu(cpu, policy->related_cpus) {
if (!cppc_perf_ctrs_in_pcc_cpu(cpu))
continue;
cppc_fi = &per_cpu(cppc_freq_inv, cpu);
irq_work_sync(&cppc_fi->irq_work);
kthread_cancel_work_sync(&cppc_fi->work);
}
}
static void __init cppc_freq_invariance_init(void)
static void cppc_fie_kworker_init(void)
{
struct sched_attr attr = {
.size = sizeof(struct sched_attr),
@ -201,22 +225,12 @@ static void __init cppc_freq_invariance_init(void)
};
int ret;
if (fie_disabled != FIE_ENABLED && fie_disabled != FIE_DISABLED) {
fie_disabled = FIE_ENABLED;
if (cppc_perf_ctrs_in_pcc()) {
pr_info("FIE not enabled on systems with registers in PCC\n");
fie_disabled = FIE_DISABLED;
}
}
if (fie_disabled)
return;
kworker_fie = kthread_run_worker(0, "cppc_fie");
if (IS_ERR(kworker_fie)) {
pr_warn("%s: failed to create kworker_fie: %ld\n", __func__,
PTR_ERR(kworker_fie));
fie_disabled = FIE_DISABLED;
kworker_fie = NULL;
return;
}
@ -226,15 +240,33 @@ static void __init cppc_freq_invariance_init(void)
ret);
kthread_destroy_worker(kworker_fie);
fie_disabled = FIE_DISABLED;
kworker_fie = NULL;
}
}
static void __init cppc_freq_invariance_init(void)
{
bool perf_ctrs_in_pcc = cppc_perf_ctrs_in_pcc();
if (fie_disabled == FIE_UNSET) {
if (perf_ctrs_in_pcc) {
pr_info("FIE not enabled on systems with registers in PCC\n");
fie_disabled = FIE_DISABLED;
} else {
fie_disabled = FIE_ENABLED;
}
}
if (fie_disabled || !perf_ctrs_in_pcc)
return;
cppc_fie_kworker_init();
}
static void cppc_freq_invariance_exit(void)
{
if (fie_disabled)
return;
kthread_destroy_worker(kworker_fie);
if (kworker_fie)
kthread_destroy_worker(kworker_fie);
}
#else

View file

@ -147,6 +147,8 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "nvidia,tegra30", },
{ .compatible = "nvidia,tegra114", },
{ .compatible = "nvidia,tegra124", },
{ .compatible = "nvidia,tegra186", },
{ .compatible = "nvidia,tegra194", },
{ .compatible = "nvidia,tegra210", },
{ .compatible = "nvidia,tegra234", },
@ -169,8 +171,11 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "qcom,sdm845", },
{ .compatible = "qcom,sdx75", },
{ .compatible = "qcom,sm6115", },
{ .compatible = "qcom,sm6125", },
{ .compatible = "qcom,sm6150", },
{ .compatible = "qcom,sm6350", },
{ .compatible = "qcom,sm6375", },
{ .compatible = "qcom,sm7125", },
{ .compatible = "qcom,sm7225", },
{ .compatible = "qcom,sm7325", },
{ .compatible = "qcom,sm8150", },
@ -191,6 +196,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,am625", },
{ .compatible = "ti,am62a7", },
{ .compatible = "ti,am62d2", },
{ .compatible = "ti,am62l3", },
{ .compatible = "ti,am62p5", },
{ .compatible = "qcom,ipq5332", },

View file

@ -3,7 +3,6 @@
//! Rust based implementation of the cpufreq-dt driver.
use kernel::{
c_str,
clk::Clk,
cpu, cpufreq,
cpumask::CpumaskVar,
@ -52,7 +51,7 @@ impl opp::ConfigOps for CPUFreqDTDriver {}
#[vtable]
impl cpufreq::Driver for CPUFreqDTDriver {
const NAME: &'static CStr = c_str!("cpufreq-dt");
const NAME: &'static CStr = c"cpufreq-dt";
const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
const BOOST_ENABLED: bool = true;
@ -197,7 +196,7 @@ kernel::of_device_table!(
OF_TABLE,
MODULE_OF_TABLE,
<CPUFreqDTDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c_str!("operating-points-v2")), ())]
[(of::DeviceId::new(c"operating-points-v2"), ())]
);
impl platform::Driver for CPUFreqDTDriver {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* System Control and Power Interface (SCMI) based CPUFreq Interface driver
* System Control and Management Interface (SCMI) based CPUFreq Interface driver
*
* Copyright (C) 2018-2021 ARM Ltd.
* Sudeep Holla <sudeep.holla@arm.com>
@ -101,6 +101,7 @@ static int scmi_cpu_domain_id(struct device *cpu_dev)
return -EINVAL;
}
of_node_put(domain_id.np);
return domain_id.args[0];
}

View file

@ -70,6 +70,12 @@ enum {
#define AM62A7_SUPPORT_R_MPU_OPP BIT(1)
#define AM62A7_SUPPORT_V_MPU_OPP BIT(2)
#define AM62L3_EFUSE_E_MPU_OPP 5
#define AM62L3_EFUSE_O_MPU_OPP 15
#define AM62L3_SUPPORT_E_MPU_OPP BIT(0)
#define AM62L3_SUPPORT_O_MPU_OPP BIT(1)
#define AM62P5_EFUSE_O_MPU_OPP 15
#define AM62P5_EFUSE_S_MPU_OPP 19
#define AM62P5_EFUSE_T_MPU_OPP 20
@ -213,6 +219,22 @@ static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data,
return calculated_efuse;
}
static unsigned long am62l3_efuse_xlate(struct ti_cpufreq_data *opp_data,
unsigned long efuse)
{
unsigned long calculated_efuse = AM62L3_SUPPORT_E_MPU_OPP;
switch (efuse) {
case AM62L3_EFUSE_O_MPU_OPP:
calculated_efuse |= AM62L3_SUPPORT_O_MPU_OPP;
fallthrough;
case AM62L3_EFUSE_E_MPU_OPP:
calculated_efuse |= AM62L3_SUPPORT_E_MPU_OPP;
}
return calculated_efuse;
}
static struct ti_cpufreq_soc_data am3x_soc_data = {
.efuse_xlate = amx3_efuse_xlate,
.efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
@ -313,8 +335,9 @@ static struct ti_cpufreq_soc_data am3517_soc_data = {
static const struct soc_device_attribute k3_cpufreq_soc[] = {
{ .family = "AM62X", },
{ .family = "AM62AX", },
{ .family = "AM62PX", },
{ .family = "AM62DX", },
{ .family = "AM62LX", },
{ .family = "AM62PX", },
{ /* sentinel */ }
};
@ -335,6 +358,14 @@ static struct ti_cpufreq_soc_data am62a7_soc_data = {
.multi_regulator = false,
};
static struct ti_cpufreq_soc_data am62l3_soc_data = {
.efuse_xlate = am62l3_efuse_xlate,
.efuse_offset = 0x0,
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
};
static struct ti_cpufreq_soc_data am62p5_soc_data = {
.efuse_xlate = am62p5_efuse_xlate,
.efuse_offset = 0x0,
@ -463,6 +494,7 @@ static const struct of_device_id ti_cpufreq_of_match[] __maybe_unused = {
{ .compatible = "ti,am625", .data = &am625_soc_data, },
{ .compatible = "ti,am62a7", .data = &am62a7_soc_data, },
{ .compatible = "ti,am62d2", .data = &am62a7_soc_data, },
{ .compatible = "ti,am62l3", .data = &am62l3_soc_data, },
{ .compatible = "ti,am62p5", .data = &am62p5_soc_data, },
/* legacy */
{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },

View file

@ -154,6 +154,7 @@ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
extern int cppc_set_enable(int cpu, bool enable);
extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
extern bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu);
extern bool cppc_perf_ctrs_in_pcc(void);
extern unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf);
extern unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq);
@ -204,6 +205,10 @@ static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
{
return -EOPNOTSUPP;
}
static inline bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu)
{
return false;
}
static inline bool cppc_perf_ctrs_in_pcc(void)
{
return false;

View file

@ -3,7 +3,8 @@
#include <linux/cpufreq.h>
#ifdef CONFIG_CPU_FREQ
void rust_helper_cpufreq_register_em_with_opp(struct cpufreq_policy *policy)
__rust_helper void
rust_helper_cpufreq_register_em_with_opp(struct cpufreq_policy *policy)
{
cpufreq_register_em_with_opp(policy);
}

View file

@ -840,7 +840,6 @@ pub trait Driver {
/// ```
/// use kernel::{
/// cpufreq,
/// c_str,
/// device::{Core, Device},
/// macros::vtable,
/// of, platform,
@ -853,7 +852,7 @@ pub trait Driver {
///
/// #[vtable]
/// impl cpufreq::Driver for SampleDriver {
/// const NAME: &'static CStr = c_str!("cpufreq-sample");
/// const NAME: &'static CStr = c"cpufreq-sample";
/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
/// const BOOST_ENABLED: bool = true;
///
@ -1015,6 +1014,8 @@ impl<T: Driver> Registration<T> {
..pin_init::zeroed()
};
// Always inline to optimize out error path of `build_assert`.
#[inline(always)]
const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
let src = name.to_bytes_with_nul();
let mut dst = [0; CPUFREQ_NAME_LEN];

View file

@ -39,7 +39,7 @@ use core::ops::{Deref, DerefMut};
/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) {
/// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the
/// // returned reference.
/// let mask = unsafe { Cpumask::as_mut_ref(ptr) };
/// let mask = unsafe { Cpumask::from_raw_mut(ptr) };
///
/// mask.set(set_cpu);
/// mask.clear(clear_cpu);
@ -49,13 +49,13 @@ use core::ops::{Deref, DerefMut};
pub struct Cpumask(Opaque<bindings::cpumask>);
impl Cpumask {
/// Creates a mutable reference to an existing `struct cpumask` pointer.
/// Creates a mutable reference from an existing `struct cpumask` pointer.
///
/// # Safety
///
/// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
/// of the returned reference.
pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {
pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {
// SAFETY: Guaranteed by the safety requirements of the function.
//
// INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
@ -63,13 +63,13 @@ impl Cpumask {
unsafe { &mut *ptr.cast() }
}
/// Creates a reference to an existing `struct cpumask` pointer.
/// Creates a reference from an existing `struct cpumask` pointer.
///
/// # Safety
///
/// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
/// of the returned reference.
pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask) -> &'a Self {
pub unsafe fn from_raw<'a>(ptr: *const bindings::cpumask) -> &'a Self {
// SAFETY: Guaranteed by the safety requirements of the function.
//
// INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the