kernel/cpufreq.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! CPU frequency scaling.
4//!
5//! This module provides rust abstractions for interacting with the cpufreq subsystem.
6//!
7//! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h)
8//!
9//! Reference: <https://docs.kernel.org/admin-guide/pm/cpufreq.html>
10
11use crate::{
12 clk::Hertz,
13 cpu::CpuId,
14 cpumask,
15 device::{Bound, Device},
16 devres,
17 error::{
18 code::*,
19 from_result,
20 to_result,
21 Result,
22 VTABLE_DEFAULT_ERROR, //
23 },
24 ffi::{c_char, c_ulong},
25 prelude::*,
26 types::ForeignOwnable,
27 types::Opaque,
28};
29
30#[cfg(CONFIG_COMMON_CLK)]
31use crate::clk::Clk;
32
33use core::{
34 cell::UnsafeCell,
35 marker::PhantomData,
36 ops::{Deref, DerefMut},
37 pin::Pin,
38 ptr::{
39 self,
40 NonNull, //
41 },
42};
43
44use macros::vtable;
45
46/// Maximum length of CPU frequency driver's name.
47const CPUFREQ_NAME_LEN: usize = bindings::CPUFREQ_NAME_LEN as usize;
48
49/// Default transition latency value in nanoseconds.
50pub const DEFAULT_TRANSITION_LATENCY_NS: u32 = bindings::CPUFREQ_DEFAULT_TRANSITION_LATENCY_NS;
51
52/// CPU frequency driver flags.
53pub mod flags {
54 /// Driver needs to update internal limits even if frequency remains unchanged.
55 pub const NEED_UPDATE_LIMITS: u16 = 1 << 0;
56
57 /// Platform where constants like `loops_per_jiffy` are unaffected by frequency changes.
58 pub const CONST_LOOPS: u16 = 1 << 1;
59
60 /// Register driver as a thermal cooling device automatically.
61 pub const IS_COOLING_DEV: u16 = 1 << 2;
62
63 /// Supports multiple clock domains with per-policy governors in `cpu/cpuN/cpufreq/`.
64 pub const HAVE_GOVERNOR_PER_POLICY: u16 = 1 << 3;
65
66 /// Allows post-change notifications outside of the `target()` routine.
67 pub const ASYNC_NOTIFICATION: u16 = 1 << 4;
68
69 /// Ensure CPU starts at a valid frequency from the driver's freq-table.
70 pub const NEED_INITIAL_FREQ_CHECK: u16 = 1 << 5;
71
72 /// Disallow governors with `dynamic_switching` capability.
73 pub const NO_AUTO_DYNAMIC_SWITCHING: u16 = 1 << 6;
74}
75
76/// Relations from the C code.
77const CPUFREQ_RELATION_L: u32 = 0;
78const CPUFREQ_RELATION_H: u32 = 1;
79const CPUFREQ_RELATION_C: u32 = 2;
80
81/// Can be used with any of the above values.
82const CPUFREQ_RELATION_E: u32 = 1 << 2;
83
84/// CPU frequency selection relations.
85///
86/// CPU frequency selection relations, each optionally marked as "efficient".
87#[derive(Copy, Clone, Debug, Eq, PartialEq)]
88pub enum Relation {
89 /// Select the lowest frequency at or above target.
90 Low(bool),
91 /// Select the highest frequency below or at target.
92 High(bool),
93 /// Select the closest frequency to the target.
94 Close(bool),
95}
96
97impl Relation {
98 // Construct from a C-compatible `u32` value.
99 fn new(val: u32) -> Result<Self> {
100 let efficient = val & CPUFREQ_RELATION_E != 0;
101
102 Ok(match val & !CPUFREQ_RELATION_E {
103 CPUFREQ_RELATION_L => Self::Low(efficient),
104 CPUFREQ_RELATION_H => Self::High(efficient),
105 CPUFREQ_RELATION_C => Self::Close(efficient),
106 _ => return Err(EINVAL),
107 })
108 }
109}
110
111impl From<Relation> for u32 {
112 // Convert to a C-compatible `u32` value.
113 fn from(rel: Relation) -> Self {
114 let (mut val, efficient) = match rel {
115 Relation::Low(e) => (CPUFREQ_RELATION_L, e),
116 Relation::High(e) => (CPUFREQ_RELATION_H, e),
117 Relation::Close(e) => (CPUFREQ_RELATION_C, e),
118 };
119
120 if efficient {
121 val |= CPUFREQ_RELATION_E;
122 }
123
124 val
125 }
126}
127
128/// Policy data.
129///
130/// Rust abstraction for the C `struct cpufreq_policy_data`.
131///
132/// # Invariants
133///
134/// A [`PolicyData`] instance always corresponds to a valid C `struct cpufreq_policy_data`.
135///
136/// The callers must ensure that the `struct cpufreq_policy_data` is valid for access and remains
137/// valid for the lifetime of the returned reference.
138#[repr(transparent)]
139pub struct PolicyData(Opaque<bindings::cpufreq_policy_data>);
140
141impl PolicyData {
142 /// Creates a mutable reference to an existing `struct cpufreq_policy_data` pointer.
143 ///
144 /// # Safety
145 ///
146 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
147 /// of the returned reference.
148 #[inline]
149 pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy_data) -> &'a mut Self {
150 // SAFETY: Guaranteed by the safety requirements of the function.
151 //
152 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
153 // lifetime of the returned reference.
154 unsafe { &mut *ptr.cast() }
155 }
156
157 /// Returns a raw pointer to the underlying C `cpufreq_policy_data`.
158 #[inline]
159 pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data {
160 let this: *const Self = self;
161 this.cast_mut().cast()
162 }
163
164 /// Wrapper for `cpufreq_generic_frequency_table_verify`.
165 #[inline]
166 pub fn generic_verify(&self) -> Result {
167 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
168 to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })
169 }
170}
171
172/// The frequency table index.
173///
174/// Represents index with a frequency table.
175///
176/// # Invariants
177///
178/// The index must correspond to a valid entry in the [`Table`] it is used for.
179#[derive(Copy, Clone, PartialEq, Eq, Debug)]
180pub struct TableIndex(usize);
181
182impl TableIndex {
183 /// Creates an instance of [`TableIndex`].
184 ///
185 /// # Safety
186 ///
187 /// The caller must ensure that `index` correspond to a valid entry in the [`Table`] it is used
188 /// for.
189 pub unsafe fn new(index: usize) -> Self {
190 // INVARIANT: The caller ensures that `index` correspond to a valid entry in the [`Table`].
191 Self(index)
192 }
193}
194
195impl From<TableIndex> for usize {
196 #[inline]
197 fn from(index: TableIndex) -> Self {
198 index.0
199 }
200}
201
202/// CPU frequency table.
203///
204/// Rust abstraction for the C `struct cpufreq_frequency_table`.
205///
206/// # Invariants
207///
208/// A [`Table`] instance always corresponds to a valid C `struct cpufreq_frequency_table`.
209///
210/// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and
211/// remains valid for the lifetime of the returned reference.
212///
213/// # Examples
214///
215/// The following example demonstrates how to read a frequency value from [`Table`].
216///
217/// ```
218/// use kernel::cpufreq::{Policy, TableIndex};
219///
220/// fn show_freq(policy: &Policy) -> Result {
221/// let table = policy.freq_table()?;
222///
223/// // SAFETY: Index is a valid entry in the table.
224/// let index = unsafe { TableIndex::new(0) };
225///
226/// pr_info!("The frequency at index 0 is: {:?}\n", table.freq(index)?);
227/// pr_info!("The flags at index 0 is: {}\n", table.flags(index));
228/// pr_info!("The data at index 0 is: {}\n", table.data(index));
229/// Ok(())
230/// }
231/// ```
232#[repr(transparent)]
233pub struct Table(Opaque<bindings::cpufreq_frequency_table>);
234
235impl Table {
236 /// Creates a reference to an existing C `struct cpufreq_frequency_table` pointer.
237 ///
238 /// # Safety
239 ///
240 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
241 /// of the returned reference.
242 #[inline]
243 pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_frequency_table) -> &'a Self {
244 // SAFETY: Guaranteed by the safety requirements of the function.
245 //
246 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
247 // lifetime of the returned reference.
248 unsafe { &*ptr.cast() }
249 }
250
251 /// Returns the raw mutable pointer to the C `struct cpufreq_frequency_table`.
252 #[inline]
253 pub fn as_raw(&self) -> *mut bindings::cpufreq_frequency_table {
254 let this: *const Self = self;
255 this.cast_mut().cast()
256 }
257
258 /// Returns frequency at `index` in the [`Table`].
259 #[inline]
260 pub fn freq(&self, index: TableIndex) -> Result<Hertz> {
261 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
262 // guaranteed to be valid by its safety requirements.
263 Ok(Hertz::from_khz(unsafe {
264 (*self.as_raw().add(index.into())).frequency.try_into()?
265 }))
266 }
267
268 /// Returns flags at `index` in the [`Table`].
269 #[inline]
270 pub fn flags(&self, index: TableIndex) -> u32 {
271 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
272 // guaranteed to be valid by its safety requirements.
273 unsafe { (*self.as_raw().add(index.into())).flags }
274 }
275
276 /// Returns data at `index` in the [`Table`].
277 #[inline]
278 pub fn data(&self, index: TableIndex) -> u32 {
279 // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
280 // guaranteed to be valid by its safety requirements.
281 unsafe { (*self.as_raw().add(index.into())).driver_data }
282 }
283}
284
285/// CPU frequency table owned and pinned in memory, created from a [`TableBuilder`].
286pub struct TableBox {
287 entries: Pin<KVec<bindings::cpufreq_frequency_table>>,
288}
289
290impl TableBox {
291 /// Constructs a new [`TableBox`] from a [`KVec`] of entries.
292 ///
293 /// # Errors
294 ///
295 /// Returns `EINVAL` if the entries list is empty.
296 #[inline]
297 fn new(entries: KVec<bindings::cpufreq_frequency_table>) -> Result<Self> {
298 if entries.is_empty() {
299 return Err(EINVAL);
300 }
301
302 Ok(Self {
303 // Pin the entries to memory, since we are passing its pointer to the C code.
304 entries: Pin::new(entries),
305 })
306 }
307
308 /// Returns a raw pointer to the underlying C `cpufreq_frequency_table`.
309 #[inline]
310 fn as_raw(&self) -> *const bindings::cpufreq_frequency_table {
311 // The pointer is valid until the table gets dropped.
312 self.entries.as_ptr()
313 }
314}
315
316impl Deref for TableBox {
317 type Target = Table;
318
319 fn deref(&self) -> &Self::Target {
320 // SAFETY: The caller owns TableBox, it is safe to deref.
321 unsafe { Self::Target::from_raw(self.as_raw()) }
322 }
323}
324
325/// CPU frequency table builder.
326///
327/// This is used by the CPU frequency drivers to build a frequency table dynamically.
328///
329/// # Examples
330///
331/// The following example demonstrates how to create a CPU frequency table.
332///
333/// ```
334/// use kernel::cpufreq::{TableBuilder, TableIndex};
335/// use kernel::clk::Hertz;
336///
337/// let mut builder = TableBuilder::new();
338///
339/// // Adds few entries to the table.
340/// builder.add(Hertz::from_mhz(700), 0, 1).unwrap();
341/// builder.add(Hertz::from_mhz(800), 2, 3).unwrap();
342/// builder.add(Hertz::from_mhz(900), 4, 5).unwrap();
343/// builder.add(Hertz::from_ghz(1), 6, 7).unwrap();
344///
345/// let table = builder.to_table().unwrap();
346///
347/// // SAFETY: Index values correspond to valid entries in the table.
348/// let (index0, index2) = unsafe { (TableIndex::new(0), TableIndex::new(2)) };
349///
350/// assert_eq!(table.freq(index0), Ok(Hertz::from_mhz(700)));
351/// assert_eq!(table.flags(index0), 0);
352/// assert_eq!(table.data(index0), 1);
353///
354/// assert_eq!(table.freq(index2), Ok(Hertz::from_mhz(900)));
355/// assert_eq!(table.flags(index2), 4);
356/// assert_eq!(table.data(index2), 5);
357/// ```
358#[derive(Default)]
359#[repr(transparent)]
360pub struct TableBuilder {
361 entries: KVec<bindings::cpufreq_frequency_table>,
362}
363
364impl TableBuilder {
365 /// Creates a new instance of [`TableBuilder`].
366 #[inline]
367 pub fn new() -> Self {
368 Self {
369 entries: KVec::new(),
370 }
371 }
372
373 /// Adds a raw frequency-table entry.
374 fn push(&mut self, frequency: u32, flags: u32, driver_data: u32) -> Result {
375 // Adds the new entry at the end of the vector.
376 Ok(self.entries.push(
377 bindings::cpufreq_frequency_table {
378 flags,
379 driver_data,
380 frequency,
381 },
382 GFP_KERNEL,
383 )?)
384 }
385
386 /// Adds a new entry to the table.
387 pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {
388 self.push(freq.as_khz() as u32, flags, driver_data)
389 }
390
391 /// Consumes the [`TableBuilder`] and returns [`TableBox`].
392 pub fn to_table(mut self) -> Result<TableBox> {
393 // Add last entry to the table.
394 self.push(bindings::CPUFREQ_TABLE_END as u32, 0, 0)?;
395
396 TableBox::new(self.entries)
397 }
398}
399
400/// CPU frequency policy.
401///
402/// Rust abstraction for the C `struct cpufreq_policy`.
403///
404/// # Invariants
405///
406/// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`.
407///
408/// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid
409/// for the lifetime of the returned reference.
410///
411/// # Examples
412///
413/// The following example demonstrates how to create a CPU frequency table.
414///
415/// ```
416/// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy};
417///
418/// #[allow(clippy::double_parens, reason = "False positive before 1.92.0")]
419/// fn update_policy(policy: &mut Policy) {
420/// policy
421/// .set_dvfs_possible_from_any_cpu(true)
422/// .set_fast_switch_possible(true)
423/// .set_transition_latency_ns(DEFAULT_TRANSITION_LATENCY_NS);
424///
425/// pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur()));
426/// }
427/// ```
428#[repr(transparent)]
429pub struct Policy(Opaque<bindings::cpufreq_policy>);
430
431impl Policy {
432 /// Creates a reference to an existing `struct cpufreq_policy` pointer.
433 ///
434 /// # Safety
435 ///
436 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
437 /// of the returned reference.
438 #[inline]
439 pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self {
440 // SAFETY: Guaranteed by the safety requirements of the function.
441 //
442 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
443 // lifetime of the returned reference.
444 unsafe { &*ptr.cast() }
445 }
446
447 /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer.
448 ///
449 /// # Safety
450 ///
451 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
452 /// of the returned reference.
453 #[inline]
454 pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self {
455 // SAFETY: Guaranteed by the safety requirements of the function.
456 //
457 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
458 // lifetime of the returned reference.
459 unsafe { &mut *ptr.cast() }
460 }
461
462 /// Returns a raw mutable pointer to the C `struct cpufreq_policy`.
463 #[inline]
464 fn as_raw(&self) -> *mut bindings::cpufreq_policy {
465 let this: *const Self = self;
466 this.cast_mut().cast()
467 }
468
469 #[inline]
470 fn as_ref(&self) -> &bindings::cpufreq_policy {
471 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
472 unsafe { &*self.as_raw() }
473 }
474
475 #[inline]
476 fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy {
477 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
478 unsafe { &mut *self.as_raw() }
479 }
480
481 /// Returns the primary CPU for the [`Policy`].
482 #[inline]
483 pub fn cpu(&self) -> CpuId {
484 // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
485 unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) }
486 }
487
488 /// Returns the minimum frequency for the [`Policy`].
489 #[inline]
490 pub fn min(&self) -> Hertz {
491 Hertz::from_khz(self.as_ref().min as usize)
492 }
493
494 /// Set the minimum frequency for the [`Policy`].
495 #[inline]
496 pub fn set_min(&mut self, min: Hertz) -> &mut Self {
497 self.as_mut_ref().min = min.as_khz() as u32;
498 self
499 }
500
501 /// Returns the maximum frequency for the [`Policy`].
502 #[inline]
503 pub fn max(&self) -> Hertz {
504 Hertz::from_khz(self.as_ref().max as usize)
505 }
506
507 /// Set the maximum frequency for the [`Policy`].
508 #[inline]
509 pub fn set_max(&mut self, max: Hertz) -> &mut Self {
510 self.as_mut_ref().max = max.as_khz() as u32;
511 self
512 }
513
514 /// Returns the current frequency for the [`Policy`].
515 #[inline]
516 pub fn cur(&self) -> Hertz {
517 Hertz::from_khz(self.as_ref().cur as usize)
518 }
519
520 /// Returns the suspend frequency for the [`Policy`].
521 #[inline]
522 pub fn suspend_freq(&self) -> Hertz {
523 Hertz::from_khz(self.as_ref().suspend_freq as usize)
524 }
525
526 /// Sets the suspend frequency for the [`Policy`].
527 #[inline]
528 pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {
529 self.as_mut_ref().suspend_freq = freq.as_khz() as u32;
530 self
531 }
532
533 /// Provides a wrapper to the generic suspend routine.
534 #[inline]
535 pub fn generic_suspend(&mut self) -> Result {
536 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
537 to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })
538 }
539
540 /// Provides a wrapper to the generic get routine.
541 #[inline]
542 pub fn generic_get(&self) -> Result<u32> {
543 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
544 Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) })
545 }
546
547 /// Provides a wrapper to the register with energy model using the OPP core.
548 #[cfg(CONFIG_PM_OPP)]
549 #[inline]
550 pub fn register_em_opp(&mut self) {
551 // SAFETY: By the type invariant, the pointer stored in `self` is valid.
552 unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) };
553 }
554
555 /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`].
556 #[inline]
557 pub fn cpus(&mut self) -> &mut cpumask::Cpumask {
558 // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of
559 // the returned reference.
560 unsafe { cpumask::CpumaskVar::from_raw_mut(&mut self.as_mut_ref().cpus) }
561 }
562
563 /// Sets clock for the [`Policy`].
564 ///
565 /// # Safety
566 ///
567 /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used
568 /// by the C code.
569 #[cfg(CONFIG_COMMON_CLK)]
570 pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> {
571 let clk = Clk::get(dev, name)?;
572 self.as_mut_ref().clk = clk.as_raw();
573 Ok(clk)
574 }
575
576 /// Allows / disallows frequency switching code to run on any CPU.
577 #[inline]
578 pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self {
579 self.as_mut_ref().dvfs_possible_from_any_cpu = val;
580 self
581 }
582
583 /// Returns if fast switching of frequencies is possible or not.
584 #[inline]
585 pub fn fast_switch_possible(&self) -> bool {
586 self.as_ref().fast_switch_possible
587 }
588
589 /// Enables / disables fast frequency switching.
590 #[inline]
591 pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self {
592 self.as_mut_ref().fast_switch_possible = val;
593 self
594 }
595
596 /// Sets transition latency (in nanoseconds) for the [`Policy`].
597 #[inline]
598 pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self {
599 self.as_mut_ref().cpuinfo.transition_latency = latency_ns;
600 self
601 }
602
603 /// Sets cpuinfo `min_freq`.
604 #[inline]
605 pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self {
606 self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32;
607 self
608 }
609
610 /// Sets cpuinfo `max_freq`.
611 #[inline]
612 pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self {
613 self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32;
614 self
615 }
616
617 /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change
618 /// requests.
619 #[inline]
620 pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self {
621 self.as_mut_ref().transition_delay_us = transition_delay_us;
622 self
623 }
624
625 /// Returns reference to the CPU frequency [`Table`] for the [`Policy`].
626 pub fn freq_table(&self) -> Result<&Table> {
627 if self.as_ref().freq_table.is_null() {
628 return Err(EINVAL);
629 }
630
631 // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the
632 // lifetime of the returned reference.
633 Ok(unsafe { Table::from_raw(self.as_ref().freq_table) })
634 }
635
636 /// Sets the CPU frequency [`Table`] for the [`Policy`].
637 ///
638 /// # Safety
639 ///
640 /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the
641 /// C code.
642 #[inline]
643 pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self {
644 self.as_mut_ref().freq_table = table.as_raw();
645 self
646 }
647
648 /// Returns the [`Policy`]'s private data.
649 pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> {
650 if self.as_ref().driver_data.is_null() {
651 None
652 } else {
653 // SAFETY: The data is earlier set from [`set_data`].
654 Some(unsafe { T::borrow(self.as_ref().driver_data.cast()) })
655 }
656 }
657
658 /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper.
659 ///
660 /// # Errors
661 ///
662 /// Returns `EBUSY` if private data is already set.
663 fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {
664 if self.as_ref().driver_data.is_null() {
665 // Transfer the ownership of the data to the foreign interface.
666 self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data).cast();
667 Ok(())
668 } else {
669 Err(EBUSY)
670 }
671 }
672
673 /// Clears and returns ownership of the private data.
674 fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> {
675 if self.as_ref().driver_data.is_null() {
676 None
677 } else {
678 let data = Some(
679 // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take
680 // back the ownership of the data from the foreign interface.
681 unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data.cast()) },
682 );
683 self.as_mut_ref().driver_data = ptr::null_mut();
684 data
685 }
686 }
687}
688
689/// CPU frequency policy created from a CPU number.
690///
691/// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe
692/// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is
693/// dropped.
694struct PolicyCpu<'a>(&'a mut Policy);
695
696impl<'a> PolicyCpu<'a> {
697 fn from_cpu(cpu: CpuId) -> Result<Self> {
698 // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.
699 let ptr =
700 NonNull::new(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) }).ok_or(ENODEV)?;
701
702 Ok(Self(
703 // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of
704 // the returned reference.
705 unsafe { Policy::from_raw_mut(ptr.as_ptr()) },
706 ))
707 }
708}
709
710impl<'a> Deref for PolicyCpu<'a> {
711 type Target = Policy;
712
713 fn deref(&self) -> &Self::Target {
714 self.0
715 }
716}
717
718impl<'a> DerefMut for PolicyCpu<'a> {
719 fn deref_mut(&mut self) -> &mut Policy {
720 self.0
721 }
722}
723
724impl<'a> Drop for PolicyCpu<'a> {
725 fn drop(&mut self) {
726 // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`.
727 unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) };
728 }
729}
730
731/// CPU frequency driver.
732///
733/// Implement this trait to provide a CPU frequency driver and its callbacks.
734///
735/// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html>
736#[vtable]
737pub trait Driver {
738 /// Driver's name.
739 const NAME: &'static CStr;
740
741 /// Driver's flags.
742 const FLAGS: u16;
743
744 /// Boost support.
745 const BOOST_ENABLED: bool;
746
747 /// Policy specific data.
748 ///
749 /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying
750 /// wrapped data structure.
751 type PData: ForeignOwnable;
752
753 /// Driver's `init` callback.
754 fn init(policy: &mut Policy) -> Result<Self::PData>;
755
756 /// Driver's `exit` callback.
757 fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result {
758 build_error!(VTABLE_DEFAULT_ERROR)
759 }
760
761 /// Driver's `online` callback.
762 fn online(_policy: &mut Policy) -> Result {
763 build_error!(VTABLE_DEFAULT_ERROR)
764 }
765
766 /// Driver's `offline` callback.
767 fn offline(_policy: &mut Policy) -> Result {
768 build_error!(VTABLE_DEFAULT_ERROR)
769 }
770
771 /// Driver's `suspend` callback.
772 fn suspend(_policy: &mut Policy) -> Result {
773 build_error!(VTABLE_DEFAULT_ERROR)
774 }
775
776 /// Driver's `resume` callback.
777 fn resume(_policy: &mut Policy) -> Result {
778 build_error!(VTABLE_DEFAULT_ERROR)
779 }
780
781 /// Driver's `ready` callback.
782 fn ready(_policy: &mut Policy) {
783 build_error!(VTABLE_DEFAULT_ERROR)
784 }
785
786 /// Driver's `verify` callback.
787 fn verify(data: &mut PolicyData) -> Result;
788
789 /// Driver's `setpolicy` callback.
790 fn setpolicy(_policy: &mut Policy) -> Result {
791 build_error!(VTABLE_DEFAULT_ERROR)
792 }
793
794 /// Driver's `target` callback.
795 fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result {
796 build_error!(VTABLE_DEFAULT_ERROR)
797 }
798
799 /// Driver's `target_index` callback.
800 fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result {
801 build_error!(VTABLE_DEFAULT_ERROR)
802 }
803
804 /// Driver's `fast_switch` callback.
805 fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {
806 build_error!(VTABLE_DEFAULT_ERROR)
807 }
808
809 /// Driver's `adjust_perf` callback.
810 fn adjust_perf(
811 _policy: &mut Policy,
812 _min_perf: usize,
813 _target_perf: usize,
814 _max_perf: usize,
815 _capacity: usize,
816 ) {
817 build_error!(VTABLE_DEFAULT_ERROR)
818 }
819
820 /// Driver's `get_intermediate` callback.
821 fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 {
822 build_error!(VTABLE_DEFAULT_ERROR)
823 }
824
825 /// Driver's `target_intermediate` callback.
826 fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result {
827 build_error!(VTABLE_DEFAULT_ERROR)
828 }
829
830 /// Driver's `get` callback.
831 fn get(_policy: &mut Policy) -> Result<u32> {
832 build_error!(VTABLE_DEFAULT_ERROR)
833 }
834
835 /// Driver's `update_limits` callback.
836 fn update_limits(_policy: &mut Policy) {
837 build_error!(VTABLE_DEFAULT_ERROR)
838 }
839
840 /// Driver's `bios_limit` callback.
841 ///
842 /// Returns HW/BIOS max frequency limitations for the CPU.
843 fn bios_limit(_policy: &mut Policy) -> Result<u32> {
844 build_error!(VTABLE_DEFAULT_ERROR)
845 }
846
847 /// Driver's `set_boost` callback.
848 fn set_boost(_policy: &mut Policy, _state: i32) -> Result {
849 build_error!(VTABLE_DEFAULT_ERROR)
850 }
851
852 /// Driver's `register_em` callback.
853 fn register_em(_policy: &mut Policy) {
854 build_error!(VTABLE_DEFAULT_ERROR)
855 }
856}
857
858/// CPU frequency driver Registration.
859///
860/// # Examples
861///
862/// The following example demonstrates how to register a cpufreq driver.
863///
864/// ```
865/// use kernel::{
866/// cpufreq,
867/// device::{Core, Device},
868/// macros::vtable,
869/// of, platform,
870/// sync::Arc,
871/// };
872/// struct SampleDevice;
873///
874/// #[derive(Default)]
875/// struct SampleDriver;
876///
877/// #[vtable]
878/// impl cpufreq::Driver for SampleDriver {
879/// const NAME: &'static CStr = c"cpufreq-sample";
880/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
881/// const BOOST_ENABLED: bool = true;
882///
883/// type PData = Arc<SampleDevice>;
884///
885/// fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {
886/// // Initialize here
887/// Ok(Arc::new(SampleDevice, GFP_KERNEL)?)
888/// }
889///
890/// fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {
891/// Ok(())
892/// }
893///
894/// fn suspend(policy: &mut cpufreq::Policy) -> Result {
895/// policy.generic_suspend()
896/// }
897///
898/// fn verify(data: &mut cpufreq::PolicyData) -> Result {
899/// data.generic_verify()
900/// }
901///
902/// fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {
903/// // Update CPU frequency
904/// Ok(())
905/// }
906///
907/// fn get(policy: &mut cpufreq::Policy) -> Result<u32> {
908/// policy.generic_get()
909/// }
910/// }
911///
912/// impl platform::Driver for SampleDriver {
913/// type IdInfo = ();
914/// type Data<'bound> = Self;
915/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
916///
917/// fn probe<'bound>(
918/// pdev: &'bound platform::Device<Core<'_>>,
919/// _id_info: Option<&'bound Self::IdInfo>,
920/// ) -> impl PinInit<Self, Error> + 'bound {
921/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;
922/// Ok(Self {})
923/// }
924/// }
925/// ```
926#[repr(transparent)]
927pub struct Registration<T: Driver>(KBox<UnsafeCell<bindings::cpufreq_driver>>, PhantomData<T>);
928
929/// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
930/// or CPUs, so it is safe to share it.
931unsafe impl<T: Driver> Sync for Registration<T> {}
932
933#[allow(clippy::non_send_fields_in_send_ty)]
934/// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any
935/// thread.
936unsafe impl<T: Driver> Send for Registration<T> {}
937
938impl<T: Driver> Registration<T> {
939 const VTABLE: bindings::cpufreq_driver = bindings::cpufreq_driver {
940 name: Self::copy_name(T::NAME),
941 boost_enabled: T::BOOST_ENABLED,
942 flags: T::FLAGS,
943
944 // Initialize mandatory callbacks.
945 init: Some(Self::init_callback),
946 verify: Some(Self::verify_callback),
947
948 // Initialize optional callbacks based on the traits of `T`.
949 setpolicy: if T::HAS_SETPOLICY {
950 Some(Self::setpolicy_callback)
951 } else {
952 None
953 },
954 target: if T::HAS_TARGET {
955 Some(Self::target_callback)
956 } else {
957 None
958 },
959 target_index: if T::HAS_TARGET_INDEX {
960 Some(Self::target_index_callback)
961 } else {
962 None
963 },
964 fast_switch: if T::HAS_FAST_SWITCH {
965 Some(Self::fast_switch_callback)
966 } else {
967 None
968 },
969 adjust_perf: if T::HAS_ADJUST_PERF {
970 Some(Self::adjust_perf_callback)
971 } else {
972 None
973 },
974 get_intermediate: if T::HAS_GET_INTERMEDIATE {
975 Some(Self::get_intermediate_callback)
976 } else {
977 None
978 },
979 target_intermediate: if T::HAS_TARGET_INTERMEDIATE {
980 Some(Self::target_intermediate_callback)
981 } else {
982 None
983 },
984 get: if T::HAS_GET {
985 Some(Self::get_callback)
986 } else {
987 None
988 },
989 update_limits: if T::HAS_UPDATE_LIMITS {
990 Some(Self::update_limits_callback)
991 } else {
992 None
993 },
994 bios_limit: if T::HAS_BIOS_LIMIT {
995 Some(Self::bios_limit_callback)
996 } else {
997 None
998 },
999 online: if T::HAS_ONLINE {
1000 Some(Self::online_callback)
1001 } else {
1002 None
1003 },
1004 offline: if T::HAS_OFFLINE {
1005 Some(Self::offline_callback)
1006 } else {
1007 None
1008 },
1009 exit: if T::HAS_EXIT {
1010 Some(Self::exit_callback)
1011 } else {
1012 None
1013 },
1014 suspend: if T::HAS_SUSPEND {
1015 Some(Self::suspend_callback)
1016 } else {
1017 None
1018 },
1019 resume: if T::HAS_RESUME {
1020 Some(Self::resume_callback)
1021 } else {
1022 None
1023 },
1024 ready: if T::HAS_READY {
1025 Some(Self::ready_callback)
1026 } else {
1027 None
1028 },
1029 set_boost: if T::HAS_SET_BOOST {
1030 Some(Self::set_boost_callback)
1031 } else {
1032 None
1033 },
1034 register_em: if T::HAS_REGISTER_EM {
1035 Some(Self::register_em_callback)
1036 } else {
1037 None
1038 },
1039 ..pin_init::zeroed()
1040 };
1041
1042 // Always inline to optimize out error path of `build_assert`.
1043 #[inline(always)]
1044 const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
1045 let src = name.to_bytes_with_nul();
1046 let mut dst = [0; CPUFREQ_NAME_LEN];
1047
1048 build_assert!(src.len() <= CPUFREQ_NAME_LEN);
1049
1050 let mut i = 0;
1051 while i < src.len() {
1052 dst[i] = src[i];
1053 i += 1;
1054 }
1055
1056 dst
1057 }
1058
1059 /// Registers a CPU frequency driver with the cpufreq core.
1060 pub fn new() -> Result<Self> {
1061 // We can't use `&Self::VTABLE` directly because the cpufreq core modifies some fields in
1062 // the C `struct cpufreq_driver`, which requires a mutable reference.
1063 let mut drv = KBox::new(UnsafeCell::new(Self::VTABLE), GFP_KERNEL)?;
1064
1065 // SAFETY: `drv` is guaranteed to be valid for the lifetime of `Registration`.
1066 to_result(unsafe { bindings::cpufreq_register_driver(drv.get_mut()) })?;
1067
1068 Ok(Self(drv, PhantomData))
1069 }
1070
1071 /// Same as [`Registration::new`], but does not return a [`Registration`] instance.
1072 ///
1073 /// Instead the [`Registration`] is owned by [`devres::register`] and will be dropped, once the
1074 /// device is detached.
1075 pub fn new_foreign_owned(dev: &Device<Bound>) -> Result
1076 where
1077 T: 'static,
1078 {
1079 devres::register(dev, Self::new()?, GFP_KERNEL)
1080 }
1081}
1082
1083/// CPU frequency driver callbacks.
1084impl<T: Driver> Registration<T> {
1085 /// Driver's `init` callback.
1086 ///
1087 /// # Safety
1088 ///
1089 /// - This function may only be called from the cpufreq C infrastructure.
1090 /// - The pointer arguments must be valid pointers.
1091 unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1092 from_result(|| {
1093 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1094 // lifetime of `policy`.
1095 let policy = unsafe { Policy::from_raw_mut(ptr) };
1096
1097 let data = T::init(policy)?;
1098 policy.set_data(data)?;
1099 Ok(0)
1100 })
1101 }
1102
1103 /// Driver's `exit` callback.
1104 ///
1105 /// # Safety
1106 ///
1107 /// - This function may only be called from the cpufreq C infrastructure.
1108 /// - The pointer arguments must be valid pointers.
1109 unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
1110 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1111 // lifetime of `policy`.
1112 let policy = unsafe { Policy::from_raw_mut(ptr) };
1113
1114 let data = policy.clear_data();
1115 let _ = T::exit(policy, data);
1116 }
1117
1118 /// Driver's `online` callback.
1119 ///
1120 /// # Safety
1121 ///
1122 /// - This function may only be called from the cpufreq C infrastructure.
1123 /// - The pointer arguments must be valid pointers.
1124 unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1125 from_result(|| {
1126 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1127 // lifetime of `policy`.
1128 let policy = unsafe { Policy::from_raw_mut(ptr) };
1129 T::online(policy).map(|()| 0)
1130 })
1131 }
1132
1133 /// Driver's `offline` callback.
1134 ///
1135 /// # Safety
1136 ///
1137 /// - This function may only be called from the cpufreq C infrastructure.
1138 /// - The pointer arguments must be valid pointers.
1139 unsafe extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1140 from_result(|| {
1141 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1142 // lifetime of `policy`.
1143 let policy = unsafe { Policy::from_raw_mut(ptr) };
1144 T::offline(policy).map(|()| 0)
1145 })
1146 }
1147
1148 /// Driver's `suspend` callback.
1149 ///
1150 /// # Safety
1151 ///
1152 /// - This function may only be called from the cpufreq C infrastructure.
1153 /// - The pointer arguments must be valid pointers.
1154 unsafe extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1155 from_result(|| {
1156 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1157 // lifetime of `policy`.
1158 let policy = unsafe { Policy::from_raw_mut(ptr) };
1159 T::suspend(policy).map(|()| 0)
1160 })
1161 }
1162
1163 /// Driver's `resume` callback.
1164 ///
1165 /// # Safety
1166 ///
1167 /// - This function may only be called from the cpufreq C infrastructure.
1168 /// - The pointer arguments must be valid pointers.
1169 unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1170 from_result(|| {
1171 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1172 // lifetime of `policy`.
1173 let policy = unsafe { Policy::from_raw_mut(ptr) };
1174 T::resume(policy).map(|()| 0)
1175 })
1176 }
1177
1178 /// Driver's `ready` callback.
1179 ///
1180 /// # Safety
1181 ///
1182 /// - This function may only be called from the cpufreq C infrastructure.
1183 /// - The pointer arguments must be valid pointers.
1184 unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
1185 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1186 // lifetime of `policy`.
1187 let policy = unsafe { Policy::from_raw_mut(ptr) };
1188 T::ready(policy);
1189 }
1190
1191 /// Driver's `verify` callback.
1192 ///
1193 /// # Safety
1194 ///
1195 /// - This function may only be called from the cpufreq C infrastructure.
1196 /// - The pointer arguments must be valid pointers.
1197 unsafe extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> c_int {
1198 from_result(|| {
1199 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1200 // lifetime of `policy`.
1201 let data = unsafe { PolicyData::from_raw_mut(ptr) };
1202 T::verify(data).map(|()| 0)
1203 })
1204 }
1205
1206 /// Driver's `setpolicy` callback.
1207 ///
1208 /// # Safety
1209 ///
1210 /// - This function may only be called from the cpufreq C infrastructure.
1211 /// - The pointer arguments must be valid pointers.
1212 unsafe extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
1213 from_result(|| {
1214 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1215 // lifetime of `policy`.
1216 let policy = unsafe { Policy::from_raw_mut(ptr) };
1217 T::setpolicy(policy).map(|()| 0)
1218 })
1219 }
1220
1221 /// Driver's `target` callback.
1222 ///
1223 /// # Safety
1224 ///
1225 /// - This function may only be called from the cpufreq C infrastructure.
1226 /// - The pointer arguments must be valid pointers.
1227 unsafe extern "C" fn target_callback(
1228 ptr: *mut bindings::cpufreq_policy,
1229 target_freq: c_uint,
1230 relation: c_uint,
1231 ) -> c_int {
1232 from_result(|| {
1233 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1234 // lifetime of `policy`.
1235 let policy = unsafe { Policy::from_raw_mut(ptr) };
1236 T::target(policy, target_freq, Relation::new(relation)?).map(|()| 0)
1237 })
1238 }
1239
1240 /// Driver's `target_index` callback.
1241 ///
1242 /// # Safety
1243 ///
1244 /// - This function may only be called from the cpufreq C infrastructure.
1245 /// - The pointer arguments must be valid pointers.
1246 unsafe extern "C" fn target_index_callback(
1247 ptr: *mut bindings::cpufreq_policy,
1248 index: c_uint,
1249 ) -> c_int {
1250 from_result(|| {
1251 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1252 // lifetime of `policy`.
1253 let policy = unsafe { Policy::from_raw_mut(ptr) };
1254
1255 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1256 // frequency table.
1257 let index = unsafe { TableIndex::new(index as usize) };
1258
1259 T::target_index(policy, index).map(|()| 0)
1260 })
1261 }
1262
1263 /// Driver's `fast_switch` callback.
1264 ///
1265 /// # Safety
1266 ///
1267 /// - This function may only be called from the cpufreq C infrastructure.
1268 /// - The pointer arguments must be valid pointers.
1269 unsafe extern "C" fn fast_switch_callback(
1270 ptr: *mut bindings::cpufreq_policy,
1271 target_freq: c_uint,
1272 ) -> c_uint {
1273 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1274 // lifetime of `policy`.
1275 let policy = unsafe { Policy::from_raw_mut(ptr) };
1276 T::fast_switch(policy, target_freq)
1277 }
1278
1279 /// Driver's `adjust_perf` callback.
1280 ///
1281 /// # Safety
1282 ///
1283 /// - This function may only be called from the cpufreq C infrastructure.
1284 /// - The pointer arguments must be valid pointers.
1285 unsafe extern "C" fn adjust_perf_callback(
1286 ptr: *mut bindings::cpufreq_policy,
1287 min_perf: c_ulong,
1288 target_perf: c_ulong,
1289 max_perf: c_ulong,
1290 capacity: c_ulong,
1291 ) {
1292 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1293 // lifetime of `policy`.
1294 let policy = unsafe { Policy::from_raw_mut(ptr) };
1295 T::adjust_perf(policy, min_perf, target_perf, max_perf, capacity);
1296 }
1297
1298 /// Driver's `get_intermediate` callback.
1299 ///
1300 /// # Safety
1301 ///
1302 /// - This function may only be called from the cpufreq C infrastructure.
1303 /// - The pointer arguments must be valid pointers.
1304 unsafe extern "C" fn get_intermediate_callback(
1305 ptr: *mut bindings::cpufreq_policy,
1306 index: c_uint,
1307 ) -> c_uint {
1308 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1309 // lifetime of `policy`.
1310 let policy = unsafe { Policy::from_raw_mut(ptr) };
1311
1312 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1313 // frequency table.
1314 let index = unsafe { TableIndex::new(index as usize) };
1315
1316 T::get_intermediate(policy, index)
1317 }
1318
1319 /// Driver's `target_intermediate` callback.
1320 ///
1321 /// # Safety
1322 ///
1323 /// - This function may only be called from the cpufreq C infrastructure.
1324 /// - The pointer arguments must be valid pointers.
1325 unsafe extern "C" fn target_intermediate_callback(
1326 ptr: *mut bindings::cpufreq_policy,
1327 index: c_uint,
1328 ) -> c_int {
1329 from_result(|| {
1330 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1331 // lifetime of `policy`.
1332 let policy = unsafe { Policy::from_raw_mut(ptr) };
1333
1334 // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1335 // frequency table.
1336 let index = unsafe { TableIndex::new(index as usize) };
1337
1338 T::target_intermediate(policy, index).map(|()| 0)
1339 })
1340 }
1341
1342 /// Driver's `get` callback.
1343 ///
1344 /// # Safety
1345 ///
1346 /// - This function may only be called from the cpufreq C infrastructure.
1347 unsafe extern "C" fn get_callback(cpu: c_uint) -> c_uint {
1348 // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1349 let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
1350
1351 PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).unwrap_or(0))
1352 }
1353
1354 /// Driver's `update_limit` callback.
1355 ///
1356 /// # Safety
1357 ///
1358 /// - This function may only be called from the cpufreq C infrastructure.
1359 /// - The pointer arguments must be valid pointers.
1360 unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
1361 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1362 // lifetime of `policy`.
1363 let policy = unsafe { Policy::from_raw_mut(ptr) };
1364 T::update_limits(policy);
1365 }
1366
1367 /// Driver's `bios_limit` callback.
1368 ///
1369 /// # Safety
1370 ///
1371 /// - This function may only be called from the cpufreq C infrastructure.
1372 /// - The pointer arguments must be valid pointers.
1373 unsafe extern "C" fn bios_limit_callback(cpu: c_int, limit: *mut c_uint) -> c_int {
1374 // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1375 let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
1376
1377 from_result(|| {
1378 let mut policy = PolicyCpu::from_cpu(cpu_id)?;
1379 let val = T::bios_limit(&mut policy)?;
1380 // SAFETY: `limit` is guaranteed by the C code to be valid.
1381 unsafe {
1382 *limit = val;
1383 }
1384 Ok(0)
1385 })
1386 }
1387
1388 /// Driver's `set_boost` callback.
1389 ///
1390 /// # Safety
1391 ///
1392 /// - This function may only be called from the cpufreq C infrastructure.
1393 /// - The pointer arguments must be valid pointers.
1394 unsafe extern "C" fn set_boost_callback(
1395 ptr: *mut bindings::cpufreq_policy,
1396 state: c_int,
1397 ) -> c_int {
1398 from_result(|| {
1399 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1400 // lifetime of `policy`.
1401 let policy = unsafe { Policy::from_raw_mut(ptr) };
1402 T::set_boost(policy, state).map(|()| 0)
1403 })
1404 }
1405
1406 /// Driver's `register_em` callback.
1407 ///
1408 /// # Safety
1409 ///
1410 /// - This function may only be called from the cpufreq C infrastructure.
1411 /// - The pointer arguments must be valid pointers.
1412 unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
1413 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1414 // lifetime of `policy`.
1415 let policy = unsafe { Policy::from_raw_mut(ptr) };
1416 T::register_em(policy);
1417 }
1418}
1419
1420impl<T: Driver> Drop for Registration<T> {
1421 /// Unregisters with the cpufreq core.
1422 fn drop(&mut self) {
1423 // SAFETY: `self.0` is guaranteed to be valid for the lifetime of `Registration`.
1424 unsafe { bindings::cpufreq_unregister_driver(self.0.get_mut()) };
1425 }
1426}