drivers/cpufreq/cppc_cpufreq.c
Source file repositories/reference/linux-study-clean/drivers/cpufreq/cppc_cpufreq.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/cpufreq/cppc_cpufreq.c- Extension
.c- Size
- 28115 bytes
- Lines
- 1078
- Domain
- Driver Families
- Bucket
- drivers/cpufreq
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/arch_topology.hlinux/kernel.hlinux/module.hlinux/delay.hlinux/cpu.hlinux/cpufreq.hlinux/irq_work.hlinux/kthread.hlinux/time.hlinux/vmalloc.huapi/linux/sched/types.hlinux/unaligned.hacpi/cppc_acpi.hasm/cputype.h
Detected Declarations
struct cppc_freq_invariancefunction implementationfunction cppc_scale_freq_tickfunction cppc_scale_freq_workfnfunction cppc_irq_workfunction scale_freq_tickfunction cppc_cpufreq_cpu_fie_initfunction for_each_cpufunction cppc_cpufreq_cpu_fie_exitfunction for_each_cpufunction cppc_fie_kworker_initfunction cppc_freq_invariance_initfunction cppc_freq_invariance_exitfunction cppc_cpufreq_cpu_fie_initfunction cppc_cpufreq_set_targetfunction cppc_cpufreq_fast_switchfunction cppc_verify_policyfunction __cppc_cpufreq_get_transition_delay_usfunction channelfunction cppc_cpufreq_get_transition_delay_usfunction get_perf_level_countfunction compute_costfunction cppc_get_cpu_powerfunction cppc_get_cpu_costfunction cppc_cpufreq_register_emfunction populate_efficiency_classfunction for_each_possible_cpufunction for_each_possible_cpufunction populate_efficiency_classfunction cppc_cpufreq_put_cpu_datafunction cppc_cpufreq_cpu_initfunction cppc_cpufreq_cpu_exitfunction get_deltafunction cppc_perf_from_fbctrsfunction cppc_get_perf_ctrs_samplefunction cppc_cpufreq_get_ratefunction cppc_cpufreq_set_boostfunction show_freqdomain_cpusfunction show_auto_selectfunction store_auto_selectfunction cppc_cpufreq_sysfs_show_u64function cppc_cpufreq_sysfs_store_u64function show_energy_performance_preference_valfunction store_energy_performance_preference_valfunction cppc_get_perf_limited_filteredfunction cppc_cpufreq_initfunction cppc_cpufreq_exit
Annotated Snippet
struct cppc_freq_invariance {
int cpu;
struct irq_work irq_work;
struct kthread_work work;
struct cppc_perf_fb_ctrs prev_perf_fb_ctrs;
struct cppc_cpudata *cpu_data;
};
static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv);
static struct kthread_worker *kworker_fie;
static int cppc_perf_from_fbctrs(u64 reference_perf,
struct cppc_perf_fb_ctrs *fb_ctrs_t0,
struct cppc_perf_fb_ctrs *fb_ctrs_t1);
/**
* __cppc_scale_freq_tick - CPPC arch_freq_scale updater for frequency invariance
* @cppc_fi: per-cpu CPPC FIE data.
*
* 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.
*/
static void __cppc_scale_freq_tick(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, ref_perf;
cpu_data = cppc_fi->cpu_data;
if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) {
pr_warn("%s: failed to read perf counters\n", __func__);
return;
}
ref_perf = cpu_data->perf_caps.reference_perf;
perf = cppc_perf_from_fbctrs(ref_perf,
&cppc_fi->prev_perf_fb_ctrs, &fb_ctrs);
if (!perf)
return;
cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
perf <<= SCHED_CAPACITY_SHIFT;
local_freq_scale = div64_u64(perf, cpu_data->perf_caps.highest_perf);
/* This can happen due to counter's overflow */
if (unlikely(local_freq_scale > 1024))
local_freq_scale = 1024;
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;
cppc_fi = container_of(irq_work, struct cppc_freq_invariance, irq_work);
kthread_queue_work(kworker_fie, &cppc_fi->work);
}
/*
* 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
Annotation
- Immediate include surface: `linux/arch_topology.h`, `linux/kernel.h`, `linux/module.h`, `linux/delay.h`, `linux/cpu.h`, `linux/cpufreq.h`, `linux/irq_work.h`, `linux/kthread.h`.
- Detected declarations: `struct cppc_freq_invariance`, `function implementation`, `function cppc_scale_freq_tick`, `function cppc_scale_freq_workfn`, `function cppc_irq_work`, `function scale_freq_tick`, `function cppc_cpufreq_cpu_fie_init`, `function for_each_cpu`, `function cppc_cpufreq_cpu_fie_exit`, `function for_each_cpu`.
- Atlas domain: Driver Families / drivers/cpufreq.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.