xref: /linux/rust/kernel/cpufreq.rs (revision f688b599d711d169b22e99f2d055847d66c4e0d3)
12207856fSViresh Kumar // SPDX-License-Identifier: GPL-2.0
22207856fSViresh Kumar 
32207856fSViresh Kumar //! CPU frequency scaling.
42207856fSViresh Kumar //!
52207856fSViresh Kumar //! This module provides rust abstractions for interacting with the cpufreq subsystem.
62207856fSViresh Kumar //!
72207856fSViresh Kumar //! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h)
82207856fSViresh Kumar //!
92207856fSViresh Kumar //! Reference: <https://docs.kernel.org/admin-guide/pm/cpufreq.html>
102207856fSViresh Kumar 
112207856fSViresh Kumar use crate::{
122207856fSViresh Kumar     clk::Hertz,
13*33db8c97SViresh Kumar     cpu::CpuId,
146ebdd7c9SViresh Kumar     cpumask,
15c6af9a11SViresh Kumar     device::{Bound, Device},
16c6af9a11SViresh Kumar     devres::Devres,
17c6af9a11SViresh Kumar     error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR},
18c6af9a11SViresh Kumar     ffi::{c_char, c_ulong},
192207856fSViresh Kumar     prelude::*,
206ebdd7c9SViresh Kumar     types::ForeignOwnable,
212207856fSViresh Kumar     types::Opaque,
222207856fSViresh Kumar };
232207856fSViresh Kumar 
246ebdd7c9SViresh Kumar #[cfg(CONFIG_COMMON_CLK)]
256ebdd7c9SViresh Kumar use crate::clk::Clk;
266ebdd7c9SViresh Kumar 
276ebdd7c9SViresh Kumar use core::{
28c6af9a11SViresh Kumar     cell::UnsafeCell,
29c6af9a11SViresh Kumar     marker::PhantomData,
30c6af9a11SViresh Kumar     mem::MaybeUninit,
316ebdd7c9SViresh Kumar     ops::{Deref, DerefMut},
326ebdd7c9SViresh Kumar     pin::Pin,
336ebdd7c9SViresh Kumar     ptr,
346ebdd7c9SViresh Kumar };
356ebdd7c9SViresh Kumar 
366ebdd7c9SViresh Kumar use macros::vtable;
372207856fSViresh Kumar 
38c6af9a11SViresh Kumar /// Maximum length of CPU frequency driver's name.
39c6af9a11SViresh Kumar const CPUFREQ_NAME_LEN: usize = bindings::CPUFREQ_NAME_LEN as usize;
40c6af9a11SViresh Kumar 
412207856fSViresh Kumar /// Default transition latency value in nanoseconds.
422207856fSViresh Kumar pub const ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32;
432207856fSViresh Kumar 
442207856fSViresh Kumar /// CPU frequency driver flags.
452207856fSViresh Kumar pub mod flags {
462207856fSViresh Kumar     /// Driver needs to update internal limits even if frequency remains unchanged.
472207856fSViresh Kumar     pub const NEED_UPDATE_LIMITS: u16 = 1 << 0;
482207856fSViresh Kumar 
492207856fSViresh Kumar     /// Platform where constants like `loops_per_jiffy` are unaffected by frequency changes.
502207856fSViresh Kumar     pub const CONST_LOOPS: u16 = 1 << 1;
512207856fSViresh Kumar 
522207856fSViresh Kumar     /// Register driver as a thermal cooling device automatically.
532207856fSViresh Kumar     pub const IS_COOLING_DEV: u16 = 1 << 2;
542207856fSViresh Kumar 
552207856fSViresh Kumar     /// Supports multiple clock domains with per-policy governors in `cpu/cpuN/cpufreq/`.
562207856fSViresh Kumar     pub const HAVE_GOVERNOR_PER_POLICY: u16 = 1 << 3;
572207856fSViresh Kumar 
582207856fSViresh Kumar     /// Allows post-change notifications outside of the `target()` routine.
592207856fSViresh Kumar     pub const ASYNC_NOTIFICATION: u16 = 1 << 4;
602207856fSViresh Kumar 
612207856fSViresh Kumar     /// Ensure CPU starts at a valid frequency from the driver's freq-table.
622207856fSViresh Kumar     pub const NEED_INITIAL_FREQ_CHECK: u16 = 1 << 5;
632207856fSViresh Kumar 
642207856fSViresh Kumar     /// Disallow governors with `dynamic_switching` capability.
652207856fSViresh Kumar     pub const NO_AUTO_DYNAMIC_SWITCHING: u16 = 1 << 6;
662207856fSViresh Kumar }
672207856fSViresh Kumar 
682207856fSViresh Kumar /// Relations from the C code.
692207856fSViresh Kumar const CPUFREQ_RELATION_L: u32 = 0;
702207856fSViresh Kumar const CPUFREQ_RELATION_H: u32 = 1;
712207856fSViresh Kumar const CPUFREQ_RELATION_C: u32 = 2;
722207856fSViresh Kumar 
732207856fSViresh Kumar /// Can be used with any of the above values.
742207856fSViresh Kumar const CPUFREQ_RELATION_E: u32 = 1 << 2;
752207856fSViresh Kumar 
762207856fSViresh Kumar /// CPU frequency selection relations.
772207856fSViresh Kumar ///
782207856fSViresh Kumar /// CPU frequency selection relations, each optionally marked as "efficient".
792207856fSViresh Kumar #[derive(Copy, Clone, Debug, Eq, PartialEq)]
802207856fSViresh Kumar pub enum Relation {
812207856fSViresh Kumar     /// Select the lowest frequency at or above target.
822207856fSViresh Kumar     Low(bool),
832207856fSViresh Kumar     /// Select the highest frequency below or at target.
842207856fSViresh Kumar     High(bool),
852207856fSViresh Kumar     /// Select the closest frequency to the target.
862207856fSViresh Kumar     Close(bool),
872207856fSViresh Kumar }
882207856fSViresh Kumar 
892207856fSViresh Kumar impl Relation {
902207856fSViresh Kumar     // Construct from a C-compatible `u32` value.
new(val: u32) -> Result<Self>912207856fSViresh Kumar     fn new(val: u32) -> Result<Self> {
922207856fSViresh Kumar         let efficient = val & CPUFREQ_RELATION_E != 0;
932207856fSViresh Kumar 
942207856fSViresh Kumar         Ok(match val & !CPUFREQ_RELATION_E {
952207856fSViresh Kumar             CPUFREQ_RELATION_L => Self::Low(efficient),
962207856fSViresh Kumar             CPUFREQ_RELATION_H => Self::High(efficient),
972207856fSViresh Kumar             CPUFREQ_RELATION_C => Self::Close(efficient),
982207856fSViresh Kumar             _ => return Err(EINVAL),
992207856fSViresh Kumar         })
1002207856fSViresh Kumar     }
1012207856fSViresh Kumar }
1022207856fSViresh Kumar 
1032207856fSViresh Kumar impl From<Relation> for u32 {
1042207856fSViresh Kumar     // Convert to a C-compatible `u32` value.
from(rel: Relation) -> Self1052207856fSViresh Kumar     fn from(rel: Relation) -> Self {
1062207856fSViresh Kumar         let (mut val, efficient) = match rel {
1072207856fSViresh Kumar             Relation::Low(e) => (CPUFREQ_RELATION_L, e),
1082207856fSViresh Kumar             Relation::High(e) => (CPUFREQ_RELATION_H, e),
1092207856fSViresh Kumar             Relation::Close(e) => (CPUFREQ_RELATION_C, e),
1102207856fSViresh Kumar         };
1112207856fSViresh Kumar 
1122207856fSViresh Kumar         if efficient {
1132207856fSViresh Kumar             val |= CPUFREQ_RELATION_E;
1142207856fSViresh Kumar         }
1152207856fSViresh Kumar 
1162207856fSViresh Kumar         val
1172207856fSViresh Kumar     }
1182207856fSViresh Kumar }
1192207856fSViresh Kumar 
1202207856fSViresh Kumar /// Policy data.
1212207856fSViresh Kumar ///
1222207856fSViresh Kumar /// Rust abstraction for the C `struct cpufreq_policy_data`.
1232207856fSViresh Kumar ///
1242207856fSViresh Kumar /// # Invariants
1252207856fSViresh Kumar ///
1262207856fSViresh Kumar /// A [`PolicyData`] instance always corresponds to a valid C `struct cpufreq_policy_data`.
1272207856fSViresh Kumar ///
1282207856fSViresh Kumar /// The callers must ensure that the `struct cpufreq_policy_data` is valid for access and remains
1292207856fSViresh Kumar /// valid for the lifetime of the returned reference.
1302207856fSViresh Kumar #[repr(transparent)]
1312207856fSViresh Kumar pub struct PolicyData(Opaque<bindings::cpufreq_policy_data>);
1322207856fSViresh Kumar 
1332207856fSViresh Kumar impl PolicyData {
1342207856fSViresh Kumar     /// Creates a mutable reference to an existing `struct cpufreq_policy_data` pointer.
1352207856fSViresh Kumar     ///
1362207856fSViresh Kumar     /// # Safety
1372207856fSViresh Kumar     ///
1382207856fSViresh Kumar     /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
1392207856fSViresh Kumar     /// of the returned reference.
1402207856fSViresh Kumar     #[inline]
from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy_data) -> &'a mut Self1412207856fSViresh Kumar     pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy_data) -> &'a mut Self {
1422207856fSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
1432207856fSViresh Kumar         //
1442207856fSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
1452207856fSViresh Kumar         // lifetime of the returned reference.
1462207856fSViresh Kumar         unsafe { &mut *ptr.cast() }
1472207856fSViresh Kumar     }
1482207856fSViresh Kumar 
1492207856fSViresh Kumar     /// Returns a raw pointer to the underlying C `cpufreq_policy_data`.
1502207856fSViresh Kumar     #[inline]
as_raw(&self) -> *mut bindings::cpufreq_policy_data1512207856fSViresh Kumar     pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data {
1522207856fSViresh Kumar         let this: *const Self = self;
1532207856fSViresh Kumar         this.cast_mut().cast()
1542207856fSViresh Kumar     }
1552207856fSViresh Kumar 
1562207856fSViresh Kumar     /// Wrapper for `cpufreq_generic_frequency_table_verify`.
1572207856fSViresh Kumar     #[inline]
generic_verify(&self) -> Result1582207856fSViresh Kumar     pub fn generic_verify(&self) -> Result {
1592207856fSViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
1602207856fSViresh Kumar         to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) })
1612207856fSViresh Kumar     }
1622207856fSViresh Kumar }
1632207856fSViresh Kumar 
1642207856fSViresh Kumar /// The frequency table index.
1652207856fSViresh Kumar ///
1662207856fSViresh Kumar /// Represents index with a frequency table.
1672207856fSViresh Kumar ///
1682207856fSViresh Kumar /// # Invariants
1692207856fSViresh Kumar ///
1702207856fSViresh Kumar /// The index must correspond to a valid entry in the [`Table`] it is used for.
1712207856fSViresh Kumar #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1722207856fSViresh Kumar pub struct TableIndex(usize);
1732207856fSViresh Kumar 
1742207856fSViresh Kumar impl TableIndex {
1752207856fSViresh Kumar     /// Creates an instance of [`TableIndex`].
1762207856fSViresh Kumar     ///
1772207856fSViresh Kumar     /// # Safety
1782207856fSViresh Kumar     ///
1792207856fSViresh Kumar     /// The caller must ensure that `index` correspond to a valid entry in the [`Table`] it is used
1802207856fSViresh Kumar     /// for.
new(index: usize) -> Self1812207856fSViresh Kumar     pub unsafe fn new(index: usize) -> Self {
1822207856fSViresh Kumar         // INVARIANT: The caller ensures that `index` correspond to a valid entry in the [`Table`].
1832207856fSViresh Kumar         Self(index)
1842207856fSViresh Kumar     }
1852207856fSViresh Kumar }
1862207856fSViresh Kumar 
1872207856fSViresh Kumar impl From<TableIndex> for usize {
1882207856fSViresh Kumar     #[inline]
from(index: TableIndex) -> Self1892207856fSViresh Kumar     fn from(index: TableIndex) -> Self {
1902207856fSViresh Kumar         index.0
1912207856fSViresh Kumar     }
1922207856fSViresh Kumar }
1932207856fSViresh Kumar 
1942207856fSViresh Kumar /// CPU frequency table.
1952207856fSViresh Kumar ///
1962207856fSViresh Kumar /// Rust abstraction for the C `struct cpufreq_frequency_table`.
1972207856fSViresh Kumar ///
1982207856fSViresh Kumar /// # Invariants
1992207856fSViresh Kumar ///
2002207856fSViresh Kumar /// A [`Table`] instance always corresponds to a valid C `struct cpufreq_frequency_table`.
2012207856fSViresh Kumar ///
2022207856fSViresh Kumar /// The callers must ensure that the `struct cpufreq_frequency_table` is valid for access and
2032207856fSViresh Kumar /// remains valid for the lifetime of the returned reference.
2042207856fSViresh Kumar ///
2052207856fSViresh Kumar /// ## Examples
2062207856fSViresh Kumar ///
2072207856fSViresh Kumar /// The following example demonstrates how to read a frequency value from [`Table`].
2082207856fSViresh Kumar ///
2092207856fSViresh Kumar /// ```
2102207856fSViresh Kumar /// use kernel::cpufreq::{Policy, TableIndex};
2112207856fSViresh Kumar ///
2122207856fSViresh Kumar /// fn show_freq(policy: &Policy) -> Result {
2132207856fSViresh Kumar ///     let table = policy.freq_table()?;
2142207856fSViresh Kumar ///
2152207856fSViresh Kumar ///     // SAFETY: Index is a valid entry in the table.
2162207856fSViresh Kumar ///     let index = unsafe { TableIndex::new(0) };
2172207856fSViresh Kumar ///
2182207856fSViresh Kumar ///     pr_info!("The frequency at index 0 is: {:?}\n", table.freq(index)?);
2192207856fSViresh Kumar ///     pr_info!("The flags at index 0 is: {}\n", table.flags(index));
2202207856fSViresh Kumar ///     pr_info!("The data at index 0 is: {}\n", table.data(index));
2212207856fSViresh Kumar ///     Ok(())
2222207856fSViresh Kumar /// }
2232207856fSViresh Kumar /// ```
2242207856fSViresh Kumar #[repr(transparent)]
2252207856fSViresh Kumar pub struct Table(Opaque<bindings::cpufreq_frequency_table>);
2262207856fSViresh Kumar 
2272207856fSViresh Kumar impl Table {
2282207856fSViresh Kumar     /// Creates a reference to an existing C `struct cpufreq_frequency_table` pointer.
2292207856fSViresh Kumar     ///
2302207856fSViresh Kumar     /// # Safety
2312207856fSViresh Kumar     ///
2322207856fSViresh Kumar     /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
2332207856fSViresh Kumar     /// of the returned reference.
2342207856fSViresh Kumar     #[inline]
from_raw<'a>(ptr: *const bindings::cpufreq_frequency_table) -> &'a Self2352207856fSViresh Kumar     pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_frequency_table) -> &'a Self {
2362207856fSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
2372207856fSViresh Kumar         //
2382207856fSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
2392207856fSViresh Kumar         // lifetime of the returned reference.
2402207856fSViresh Kumar         unsafe { &*ptr.cast() }
2412207856fSViresh Kumar     }
2422207856fSViresh Kumar 
2432207856fSViresh Kumar     /// Returns the raw mutable pointer to the C `struct cpufreq_frequency_table`.
2442207856fSViresh Kumar     #[inline]
as_raw(&self) -> *mut bindings::cpufreq_frequency_table2452207856fSViresh Kumar     pub fn as_raw(&self) -> *mut bindings::cpufreq_frequency_table {
2462207856fSViresh Kumar         let this: *const Self = self;
2472207856fSViresh Kumar         this.cast_mut().cast()
2482207856fSViresh Kumar     }
2492207856fSViresh Kumar 
2502207856fSViresh Kumar     /// Returns frequency at `index` in the [`Table`].
2512207856fSViresh Kumar     #[inline]
freq(&self, index: TableIndex) -> Result<Hertz>2522207856fSViresh Kumar     pub fn freq(&self, index: TableIndex) -> Result<Hertz> {
2532207856fSViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
2542207856fSViresh Kumar         // guaranteed to be valid by its safety requirements.
2552207856fSViresh Kumar         Ok(Hertz::from_khz(unsafe {
2562207856fSViresh Kumar             (*self.as_raw().add(index.into())).frequency.try_into()?
2572207856fSViresh Kumar         }))
2582207856fSViresh Kumar     }
2592207856fSViresh Kumar 
2602207856fSViresh Kumar     /// Returns flags at `index` in the [`Table`].
2612207856fSViresh Kumar     #[inline]
flags(&self, index: TableIndex) -> u322622207856fSViresh Kumar     pub fn flags(&self, index: TableIndex) -> u32 {
2632207856fSViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
2642207856fSViresh Kumar         // guaranteed to be valid by its safety requirements.
2652207856fSViresh Kumar         unsafe { (*self.as_raw().add(index.into())).flags }
2662207856fSViresh Kumar     }
2672207856fSViresh Kumar 
2682207856fSViresh Kumar     /// Returns data at `index` in the [`Table`].
2692207856fSViresh Kumar     #[inline]
data(&self, index: TableIndex) -> u322702207856fSViresh Kumar     pub fn data(&self, index: TableIndex) -> u32 {
2712207856fSViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid and `index` is
2722207856fSViresh Kumar         // guaranteed to be valid by its safety requirements.
2732207856fSViresh Kumar         unsafe { (*self.as_raw().add(index.into())).driver_data }
2742207856fSViresh Kumar     }
2752207856fSViresh Kumar }
2762207856fSViresh Kumar 
2772207856fSViresh Kumar /// CPU frequency table owned and pinned in memory, created from a [`TableBuilder`].
2782207856fSViresh Kumar pub struct TableBox {
2792207856fSViresh Kumar     entries: Pin<KVec<bindings::cpufreq_frequency_table>>,
2802207856fSViresh Kumar }
2812207856fSViresh Kumar 
2822207856fSViresh Kumar impl TableBox {
2832207856fSViresh Kumar     /// Constructs a new [`TableBox`] from a [`KVec`] of entries.
2842207856fSViresh Kumar     ///
2852207856fSViresh Kumar     /// # Errors
2862207856fSViresh Kumar     ///
2872207856fSViresh Kumar     /// Returns `EINVAL` if the entries list is empty.
2882207856fSViresh Kumar     #[inline]
new(entries: KVec<bindings::cpufreq_frequency_table>) -> Result<Self>2892207856fSViresh Kumar     fn new(entries: KVec<bindings::cpufreq_frequency_table>) -> Result<Self> {
2902207856fSViresh Kumar         if entries.is_empty() {
2912207856fSViresh Kumar             return Err(EINVAL);
2922207856fSViresh Kumar         }
2932207856fSViresh Kumar 
2942207856fSViresh Kumar         Ok(Self {
2952207856fSViresh Kumar             // Pin the entries to memory, since we are passing its pointer to the C code.
2962207856fSViresh Kumar             entries: Pin::new(entries),
2972207856fSViresh Kumar         })
2982207856fSViresh Kumar     }
2992207856fSViresh Kumar 
3002207856fSViresh Kumar     /// Returns a raw pointer to the underlying C `cpufreq_frequency_table`.
3012207856fSViresh Kumar     #[inline]
as_raw(&self) -> *const bindings::cpufreq_frequency_table3022207856fSViresh Kumar     fn as_raw(&self) -> *const bindings::cpufreq_frequency_table {
3032207856fSViresh Kumar         // The pointer is valid until the table gets dropped.
3042207856fSViresh Kumar         self.entries.as_ptr()
3052207856fSViresh Kumar     }
3062207856fSViresh Kumar }
3072207856fSViresh Kumar 
3082207856fSViresh Kumar impl Deref for TableBox {
3092207856fSViresh Kumar     type Target = Table;
3102207856fSViresh Kumar 
deref(&self) -> &Self::Target3112207856fSViresh Kumar     fn deref(&self) -> &Self::Target {
3122207856fSViresh Kumar         // SAFETY: The caller owns TableBox, it is safe to deref.
3132207856fSViresh Kumar         unsafe { Self::Target::from_raw(self.as_raw()) }
3142207856fSViresh Kumar     }
3152207856fSViresh Kumar }
3162207856fSViresh Kumar 
3172207856fSViresh Kumar /// CPU frequency table builder.
3182207856fSViresh Kumar ///
3192207856fSViresh Kumar /// This is used by the CPU frequency drivers to build a frequency table dynamically.
3202207856fSViresh Kumar ///
3212207856fSViresh Kumar /// ## Examples
3222207856fSViresh Kumar ///
3232207856fSViresh Kumar /// The following example demonstrates how to create a CPU frequency table.
3242207856fSViresh Kumar ///
3252207856fSViresh Kumar /// ```
3262207856fSViresh Kumar /// use kernel::cpufreq::{TableBuilder, TableIndex};
3272207856fSViresh Kumar /// use kernel::clk::Hertz;
3282207856fSViresh Kumar ///
3292207856fSViresh Kumar /// let mut builder = TableBuilder::new();
3302207856fSViresh Kumar ///
3312207856fSViresh Kumar /// // Adds few entries to the table.
3322207856fSViresh Kumar /// builder.add(Hertz::from_mhz(700), 0, 1).unwrap();
3332207856fSViresh Kumar /// builder.add(Hertz::from_mhz(800), 2, 3).unwrap();
3342207856fSViresh Kumar /// builder.add(Hertz::from_mhz(900), 4, 5).unwrap();
3352207856fSViresh Kumar /// builder.add(Hertz::from_ghz(1), 6, 7).unwrap();
3362207856fSViresh Kumar ///
3372207856fSViresh Kumar /// let table = builder.to_table().unwrap();
3382207856fSViresh Kumar ///
3392207856fSViresh Kumar /// // SAFETY: Index values correspond to valid entries in the table.
3402207856fSViresh Kumar /// let (index0, index2) = unsafe { (TableIndex::new(0), TableIndex::new(2)) };
3412207856fSViresh Kumar ///
3422207856fSViresh Kumar /// assert_eq!(table.freq(index0), Ok(Hertz::from_mhz(700)));
3432207856fSViresh Kumar /// assert_eq!(table.flags(index0), 0);
3442207856fSViresh Kumar /// assert_eq!(table.data(index0), 1);
3452207856fSViresh Kumar ///
3462207856fSViresh Kumar /// assert_eq!(table.freq(index2), Ok(Hertz::from_mhz(900)));
3472207856fSViresh Kumar /// assert_eq!(table.flags(index2), 4);
3482207856fSViresh Kumar /// assert_eq!(table.data(index2), 5);
3492207856fSViresh Kumar /// ```
3502207856fSViresh Kumar #[derive(Default)]
3512207856fSViresh Kumar #[repr(transparent)]
3522207856fSViresh Kumar pub struct TableBuilder {
3532207856fSViresh Kumar     entries: KVec<bindings::cpufreq_frequency_table>,
3542207856fSViresh Kumar }
3552207856fSViresh Kumar 
3562207856fSViresh Kumar impl TableBuilder {
3572207856fSViresh Kumar     /// Creates a new instance of [`TableBuilder`].
3582207856fSViresh Kumar     #[inline]
new() -> Self3592207856fSViresh Kumar     pub fn new() -> Self {
3602207856fSViresh Kumar         Self {
3612207856fSViresh Kumar             entries: KVec::new(),
3622207856fSViresh Kumar         }
3632207856fSViresh Kumar     }
3642207856fSViresh Kumar 
3652207856fSViresh Kumar     /// Adds a new entry to the table.
add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result3662207856fSViresh Kumar     pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {
3672207856fSViresh Kumar         // Adds the new entry at the end of the vector.
3682207856fSViresh Kumar         Ok(self.entries.push(
3692207856fSViresh Kumar             bindings::cpufreq_frequency_table {
3702207856fSViresh Kumar                 flags,
3712207856fSViresh Kumar                 driver_data,
3722207856fSViresh Kumar                 frequency: freq.as_khz() as u32,
3732207856fSViresh Kumar             },
3742207856fSViresh Kumar             GFP_KERNEL,
3752207856fSViresh Kumar         )?)
3762207856fSViresh Kumar     }
3772207856fSViresh Kumar 
3782207856fSViresh Kumar     /// Consumes the [`TableBuilder`] and returns [`TableBox`].
to_table(mut self) -> Result<TableBox>3792207856fSViresh Kumar     pub fn to_table(mut self) -> Result<TableBox> {
3802207856fSViresh Kumar         // Add last entry to the table.
3812207856fSViresh Kumar         self.add(Hertz(c_ulong::MAX), 0, 0)?;
3822207856fSViresh Kumar 
3832207856fSViresh Kumar         TableBox::new(self.entries)
3842207856fSViresh Kumar     }
3852207856fSViresh Kumar }
3866ebdd7c9SViresh Kumar 
3876ebdd7c9SViresh Kumar /// CPU frequency policy.
3886ebdd7c9SViresh Kumar ///
3896ebdd7c9SViresh Kumar /// Rust abstraction for the C `struct cpufreq_policy`.
3906ebdd7c9SViresh Kumar ///
3916ebdd7c9SViresh Kumar /// # Invariants
3926ebdd7c9SViresh Kumar ///
3936ebdd7c9SViresh Kumar /// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`.
3946ebdd7c9SViresh Kumar ///
3956ebdd7c9SViresh Kumar /// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid
3966ebdd7c9SViresh Kumar /// for the lifetime of the returned reference.
3976ebdd7c9SViresh Kumar ///
3986ebdd7c9SViresh Kumar /// ## Examples
3996ebdd7c9SViresh Kumar ///
4006ebdd7c9SViresh Kumar /// The following example demonstrates how to create a CPU frequency table.
4016ebdd7c9SViresh Kumar ///
4026ebdd7c9SViresh Kumar /// ```
4036ebdd7c9SViresh Kumar /// use kernel::cpufreq::{ETERNAL_LATENCY_NS, Policy};
4046ebdd7c9SViresh Kumar ///
4056ebdd7c9SViresh Kumar /// fn update_policy(policy: &mut Policy) {
4066ebdd7c9SViresh Kumar ///     policy
4076ebdd7c9SViresh Kumar ///         .set_dvfs_possible_from_any_cpu(true)
4086ebdd7c9SViresh Kumar ///         .set_fast_switch_possible(true)
4096ebdd7c9SViresh Kumar ///         .set_transition_latency_ns(ETERNAL_LATENCY_NS);
4106ebdd7c9SViresh Kumar ///
4116ebdd7c9SViresh Kumar ///     pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur()));
4126ebdd7c9SViresh Kumar /// }
4136ebdd7c9SViresh Kumar /// ```
4146ebdd7c9SViresh Kumar #[repr(transparent)]
4156ebdd7c9SViresh Kumar pub struct Policy(Opaque<bindings::cpufreq_policy>);
4166ebdd7c9SViresh Kumar 
4176ebdd7c9SViresh Kumar impl Policy {
4186ebdd7c9SViresh Kumar     /// Creates a reference to an existing `struct cpufreq_policy` pointer.
4196ebdd7c9SViresh Kumar     ///
4206ebdd7c9SViresh Kumar     /// # Safety
4216ebdd7c9SViresh Kumar     ///
4226ebdd7c9SViresh Kumar     /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
4236ebdd7c9SViresh Kumar     /// of the returned reference.
4246ebdd7c9SViresh Kumar     #[inline]
from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self4256ebdd7c9SViresh Kumar     pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self {
4266ebdd7c9SViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
4276ebdd7c9SViresh Kumar         //
4286ebdd7c9SViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
4296ebdd7c9SViresh Kumar         // lifetime of the returned reference.
4306ebdd7c9SViresh Kumar         unsafe { &*ptr.cast() }
4316ebdd7c9SViresh Kumar     }
4326ebdd7c9SViresh Kumar 
4336ebdd7c9SViresh Kumar     /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer.
4346ebdd7c9SViresh Kumar     ///
4356ebdd7c9SViresh Kumar     /// # Safety
4366ebdd7c9SViresh Kumar     ///
4376ebdd7c9SViresh Kumar     /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
4386ebdd7c9SViresh Kumar     /// of the returned reference.
4396ebdd7c9SViresh Kumar     #[inline]
from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self4406ebdd7c9SViresh Kumar     pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self {
4416ebdd7c9SViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
4426ebdd7c9SViresh Kumar         //
4436ebdd7c9SViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
4446ebdd7c9SViresh Kumar         // lifetime of the returned reference.
4456ebdd7c9SViresh Kumar         unsafe { &mut *ptr.cast() }
4466ebdd7c9SViresh Kumar     }
4476ebdd7c9SViresh Kumar 
4486ebdd7c9SViresh Kumar     /// Returns a raw mutable pointer to the C `struct cpufreq_policy`.
4496ebdd7c9SViresh Kumar     #[inline]
as_raw(&self) -> *mut bindings::cpufreq_policy4506ebdd7c9SViresh Kumar     fn as_raw(&self) -> *mut bindings::cpufreq_policy {
4516ebdd7c9SViresh Kumar         let this: *const Self = self;
4526ebdd7c9SViresh Kumar         this.cast_mut().cast()
4536ebdd7c9SViresh Kumar     }
4546ebdd7c9SViresh Kumar 
4556ebdd7c9SViresh Kumar     #[inline]
as_ref(&self) -> &bindings::cpufreq_policy4566ebdd7c9SViresh Kumar     fn as_ref(&self) -> &bindings::cpufreq_policy {
4576ebdd7c9SViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
4586ebdd7c9SViresh Kumar         unsafe { &*self.as_raw() }
4596ebdd7c9SViresh Kumar     }
4606ebdd7c9SViresh Kumar 
4616ebdd7c9SViresh Kumar     #[inline]
as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy4626ebdd7c9SViresh Kumar     fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy {
4636ebdd7c9SViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
4646ebdd7c9SViresh Kumar         unsafe { &mut *self.as_raw() }
4656ebdd7c9SViresh Kumar     }
4666ebdd7c9SViresh Kumar 
4676ebdd7c9SViresh Kumar     /// Returns the primary CPU for the [`Policy`].
4686ebdd7c9SViresh Kumar     #[inline]
cpu(&self) -> CpuId469*33db8c97SViresh Kumar     pub fn cpu(&self) -> CpuId {
470*33db8c97SViresh Kumar         // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
471*33db8c97SViresh Kumar         unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) }
4726ebdd7c9SViresh Kumar     }
4736ebdd7c9SViresh Kumar 
4746ebdd7c9SViresh Kumar     /// Returns the minimum frequency for the [`Policy`].
4756ebdd7c9SViresh Kumar     #[inline]
min(&self) -> Hertz4766ebdd7c9SViresh Kumar     pub fn min(&self) -> Hertz {
4776ebdd7c9SViresh Kumar         Hertz::from_khz(self.as_ref().min as usize)
4786ebdd7c9SViresh Kumar     }
4796ebdd7c9SViresh Kumar 
4806ebdd7c9SViresh Kumar     /// Set the minimum frequency for the [`Policy`].
4816ebdd7c9SViresh Kumar     #[inline]
set_min(&mut self, min: Hertz) -> &mut Self4826ebdd7c9SViresh Kumar     pub fn set_min(&mut self, min: Hertz) -> &mut Self {
4836ebdd7c9SViresh Kumar         self.as_mut_ref().min = min.as_khz() as u32;
4846ebdd7c9SViresh Kumar         self
4856ebdd7c9SViresh Kumar     }
4866ebdd7c9SViresh Kumar 
4876ebdd7c9SViresh Kumar     /// Returns the maximum frequency for the [`Policy`].
4886ebdd7c9SViresh Kumar     #[inline]
max(&self) -> Hertz4896ebdd7c9SViresh Kumar     pub fn max(&self) -> Hertz {
4906ebdd7c9SViresh Kumar         Hertz::from_khz(self.as_ref().max as usize)
4916ebdd7c9SViresh Kumar     }
4926ebdd7c9SViresh Kumar 
4936ebdd7c9SViresh Kumar     /// Set the maximum frequency for the [`Policy`].
4946ebdd7c9SViresh Kumar     #[inline]
set_max(&mut self, max: Hertz) -> &mut Self4956ebdd7c9SViresh Kumar     pub fn set_max(&mut self, max: Hertz) -> &mut Self {
4966ebdd7c9SViresh Kumar         self.as_mut_ref().max = max.as_khz() as u32;
4976ebdd7c9SViresh Kumar         self
4986ebdd7c9SViresh Kumar     }
4996ebdd7c9SViresh Kumar 
5006ebdd7c9SViresh Kumar     /// Returns the current frequency for the [`Policy`].
5016ebdd7c9SViresh Kumar     #[inline]
cur(&self) -> Hertz5026ebdd7c9SViresh Kumar     pub fn cur(&self) -> Hertz {
5036ebdd7c9SViresh Kumar         Hertz::from_khz(self.as_ref().cur as usize)
5046ebdd7c9SViresh Kumar     }
5056ebdd7c9SViresh Kumar 
5066ebdd7c9SViresh Kumar     /// Returns the suspend frequency for the [`Policy`].
5076ebdd7c9SViresh Kumar     #[inline]
suspend_freq(&self) -> Hertz5086ebdd7c9SViresh Kumar     pub fn suspend_freq(&self) -> Hertz {
5096ebdd7c9SViresh Kumar         Hertz::from_khz(self.as_ref().suspend_freq as usize)
5106ebdd7c9SViresh Kumar     }
5116ebdd7c9SViresh Kumar 
5126ebdd7c9SViresh Kumar     /// Sets the suspend frequency for the [`Policy`].
5136ebdd7c9SViresh Kumar     #[inline]
set_suspend_freq(&mut self, freq: Hertz) -> &mut Self5146ebdd7c9SViresh Kumar     pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self {
5156ebdd7c9SViresh Kumar         self.as_mut_ref().suspend_freq = freq.as_khz() as u32;
5166ebdd7c9SViresh Kumar         self
5176ebdd7c9SViresh Kumar     }
5186ebdd7c9SViresh Kumar 
5196ebdd7c9SViresh Kumar     /// Provides a wrapper to the generic suspend routine.
5206ebdd7c9SViresh Kumar     #[inline]
generic_suspend(&mut self) -> Result5216ebdd7c9SViresh Kumar     pub fn generic_suspend(&mut self) -> Result {
5226ebdd7c9SViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
5236ebdd7c9SViresh Kumar         to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) })
5246ebdd7c9SViresh Kumar     }
5256ebdd7c9SViresh Kumar 
5266ebdd7c9SViresh Kumar     /// Provides a wrapper to the generic get routine.
5276ebdd7c9SViresh Kumar     #[inline]
generic_get(&self) -> Result<u32>5286ebdd7c9SViresh Kumar     pub fn generic_get(&self) -> Result<u32> {
5296ebdd7c9SViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
530*33db8c97SViresh Kumar         Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) })
5316ebdd7c9SViresh Kumar     }
5326ebdd7c9SViresh Kumar 
5336ebdd7c9SViresh Kumar     /// Provides a wrapper to the register with energy model using the OPP core.
5346ebdd7c9SViresh Kumar     #[cfg(CONFIG_PM_OPP)]
5356ebdd7c9SViresh Kumar     #[inline]
register_em_opp(&mut self)5366ebdd7c9SViresh Kumar     pub fn register_em_opp(&mut self) {
5376ebdd7c9SViresh Kumar         // SAFETY: By the type invariant, the pointer stored in `self` is valid.
5386ebdd7c9SViresh Kumar         unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) };
5396ebdd7c9SViresh Kumar     }
5406ebdd7c9SViresh Kumar 
5416ebdd7c9SViresh Kumar     /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`].
5426ebdd7c9SViresh Kumar     #[inline]
cpus(&mut self) -> &mut cpumask::Cpumask5436ebdd7c9SViresh Kumar     pub fn cpus(&mut self) -> &mut cpumask::Cpumask {
5446ebdd7c9SViresh Kumar         // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of
5456ebdd7c9SViresh Kumar         // the returned reference.
5466ebdd7c9SViresh Kumar         unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) }
5476ebdd7c9SViresh Kumar     }
5486ebdd7c9SViresh Kumar 
5496ebdd7c9SViresh Kumar     /// Sets clock for the [`Policy`].
5506ebdd7c9SViresh Kumar     ///
5516ebdd7c9SViresh Kumar     /// # Safety
5526ebdd7c9SViresh Kumar     ///
5536ebdd7c9SViresh Kumar     /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used
5546ebdd7c9SViresh Kumar     /// by the C code.
5556ebdd7c9SViresh Kumar     #[cfg(CONFIG_COMMON_CLK)]
set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk>5566ebdd7c9SViresh Kumar     pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> {
5576ebdd7c9SViresh Kumar         let clk = Clk::get(dev, name)?;
5586ebdd7c9SViresh Kumar         self.as_mut_ref().clk = clk.as_raw();
5596ebdd7c9SViresh Kumar         Ok(clk)
5606ebdd7c9SViresh Kumar     }
5616ebdd7c9SViresh Kumar 
5626ebdd7c9SViresh Kumar     /// Allows / disallows frequency switching code to run on any CPU.
5636ebdd7c9SViresh Kumar     #[inline]
set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self5646ebdd7c9SViresh Kumar     pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self {
5656ebdd7c9SViresh Kumar         self.as_mut_ref().dvfs_possible_from_any_cpu = val;
5666ebdd7c9SViresh Kumar         self
5676ebdd7c9SViresh Kumar     }
5686ebdd7c9SViresh Kumar 
5696ebdd7c9SViresh Kumar     /// Returns if fast switching of frequencies is possible or not.
5706ebdd7c9SViresh Kumar     #[inline]
fast_switch_possible(&self) -> bool5716ebdd7c9SViresh Kumar     pub fn fast_switch_possible(&self) -> bool {
5726ebdd7c9SViresh Kumar         self.as_ref().fast_switch_possible
5736ebdd7c9SViresh Kumar     }
5746ebdd7c9SViresh Kumar 
5756ebdd7c9SViresh Kumar     /// Enables / disables fast frequency switching.
5766ebdd7c9SViresh Kumar     #[inline]
set_fast_switch_possible(&mut self, val: bool) -> &mut Self5776ebdd7c9SViresh Kumar     pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self {
5786ebdd7c9SViresh Kumar         self.as_mut_ref().fast_switch_possible = val;
5796ebdd7c9SViresh Kumar         self
5806ebdd7c9SViresh Kumar     }
5816ebdd7c9SViresh Kumar 
5826ebdd7c9SViresh Kumar     /// Sets transition latency (in nanoseconds) for the [`Policy`].
5836ebdd7c9SViresh Kumar     #[inline]
set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self5846ebdd7c9SViresh Kumar     pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self {
5856ebdd7c9SViresh Kumar         self.as_mut_ref().cpuinfo.transition_latency = latency_ns;
5866ebdd7c9SViresh Kumar         self
5876ebdd7c9SViresh Kumar     }
5886ebdd7c9SViresh Kumar 
5896ebdd7c9SViresh Kumar     /// Sets cpuinfo `min_freq`.
5906ebdd7c9SViresh Kumar     #[inline]
set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self5916ebdd7c9SViresh Kumar     pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self {
5926ebdd7c9SViresh Kumar         self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32;
5936ebdd7c9SViresh Kumar         self
5946ebdd7c9SViresh Kumar     }
5956ebdd7c9SViresh Kumar 
5966ebdd7c9SViresh Kumar     /// Sets cpuinfo `max_freq`.
5976ebdd7c9SViresh Kumar     #[inline]
set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self5986ebdd7c9SViresh Kumar     pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self {
5996ebdd7c9SViresh Kumar         self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32;
6006ebdd7c9SViresh Kumar         self
6016ebdd7c9SViresh Kumar     }
6026ebdd7c9SViresh Kumar 
6036ebdd7c9SViresh Kumar     /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change
6046ebdd7c9SViresh Kumar     /// requests.
6056ebdd7c9SViresh Kumar     #[inline]
set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self6066ebdd7c9SViresh Kumar     pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self {
6076ebdd7c9SViresh Kumar         self.as_mut_ref().transition_delay_us = transition_delay_us;
6086ebdd7c9SViresh Kumar         self
6096ebdd7c9SViresh Kumar     }
6106ebdd7c9SViresh Kumar 
6116ebdd7c9SViresh Kumar     /// Returns reference to the CPU frequency [`Table`] for the [`Policy`].
freq_table(&self) -> Result<&Table>6126ebdd7c9SViresh Kumar     pub fn freq_table(&self) -> Result<&Table> {
6136ebdd7c9SViresh Kumar         if self.as_ref().freq_table.is_null() {
6146ebdd7c9SViresh Kumar             return Err(EINVAL);
6156ebdd7c9SViresh Kumar         }
6166ebdd7c9SViresh Kumar 
6176ebdd7c9SViresh Kumar         // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the
6186ebdd7c9SViresh Kumar         // lifetime of the returned reference.
6196ebdd7c9SViresh Kumar         Ok(unsafe { Table::from_raw(self.as_ref().freq_table) })
6206ebdd7c9SViresh Kumar     }
6216ebdd7c9SViresh Kumar 
6226ebdd7c9SViresh Kumar     /// Sets the CPU frequency [`Table`] for the [`Policy`].
6236ebdd7c9SViresh Kumar     ///
6246ebdd7c9SViresh Kumar     /// # Safety
6256ebdd7c9SViresh Kumar     ///
6266ebdd7c9SViresh Kumar     /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the
6276ebdd7c9SViresh Kumar     /// C code.
6286ebdd7c9SViresh Kumar     #[inline]
set_freq_table(&mut self, table: &Table) -> &mut Self6296ebdd7c9SViresh Kumar     pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self {
6306ebdd7c9SViresh Kumar         self.as_mut_ref().freq_table = table.as_raw();
6316ebdd7c9SViresh Kumar         self
6326ebdd7c9SViresh Kumar     }
6336ebdd7c9SViresh Kumar 
6346ebdd7c9SViresh Kumar     /// Returns the [`Policy`]'s private data.
data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>>6356ebdd7c9SViresh Kumar     pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> {
6366ebdd7c9SViresh Kumar         if self.as_ref().driver_data.is_null() {
6376ebdd7c9SViresh Kumar             None
6386ebdd7c9SViresh Kumar         } else {
6396ebdd7c9SViresh Kumar             // SAFETY: The data is earlier set from [`set_data`].
640ec7714e4SLinus Torvalds             Some(unsafe { T::borrow(self.as_ref().driver_data.cast()) })
6416ebdd7c9SViresh Kumar         }
6426ebdd7c9SViresh Kumar     }
6436ebdd7c9SViresh Kumar 
6446ebdd7c9SViresh Kumar     /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper.
6456ebdd7c9SViresh Kumar     ///
6466ebdd7c9SViresh Kumar     /// # Errors
6476ebdd7c9SViresh Kumar     ///
6486ebdd7c9SViresh Kumar     /// Returns `EBUSY` if private data is already set.
set_data<T: ForeignOwnable>(&mut self, data: T) -> Result6496ebdd7c9SViresh Kumar     fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result {
6506ebdd7c9SViresh Kumar         if self.as_ref().driver_data.is_null() {
6516ebdd7c9SViresh Kumar             // Transfer the ownership of the data to the foreign interface.
6526ebdd7c9SViresh Kumar             self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _;
6536ebdd7c9SViresh Kumar             Ok(())
6546ebdd7c9SViresh Kumar         } else {
6556ebdd7c9SViresh Kumar             Err(EBUSY)
6566ebdd7c9SViresh Kumar         }
6576ebdd7c9SViresh Kumar     }
6586ebdd7c9SViresh Kumar 
6596ebdd7c9SViresh Kumar     /// Clears and returns ownership of the private data.
clear_data<T: ForeignOwnable>(&mut self) -> Option<T>6606ebdd7c9SViresh Kumar     fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> {
6616ebdd7c9SViresh Kumar         if self.as_ref().driver_data.is_null() {
6626ebdd7c9SViresh Kumar             None
6636ebdd7c9SViresh Kumar         } else {
6646ebdd7c9SViresh Kumar             let data = Some(
6656ebdd7c9SViresh Kumar                 // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take
6666ebdd7c9SViresh Kumar                 // back the ownership of the data from the foreign interface.
667ec7714e4SLinus Torvalds                 unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data.cast()) },
6686ebdd7c9SViresh Kumar             );
6696ebdd7c9SViresh Kumar             self.as_mut_ref().driver_data = ptr::null_mut();
6706ebdd7c9SViresh Kumar             data
6716ebdd7c9SViresh Kumar         }
6726ebdd7c9SViresh Kumar     }
6736ebdd7c9SViresh Kumar }
6746ebdd7c9SViresh Kumar 
6756ebdd7c9SViresh Kumar /// CPU frequency policy created from a CPU number.
6766ebdd7c9SViresh Kumar ///
6776ebdd7c9SViresh Kumar /// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe
6786ebdd7c9SViresh Kumar /// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is
6796ebdd7c9SViresh Kumar /// dropped.
6806ebdd7c9SViresh Kumar struct PolicyCpu<'a>(&'a mut Policy);
6816ebdd7c9SViresh Kumar 
6826ebdd7c9SViresh Kumar impl<'a> PolicyCpu<'a> {
from_cpu(cpu: CpuId) -> Result<Self>683*33db8c97SViresh Kumar     fn from_cpu(cpu: CpuId) -> Result<Self> {
6846ebdd7c9SViresh Kumar         // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU.
685*33db8c97SViresh Kumar         let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?;
6866ebdd7c9SViresh Kumar 
6876ebdd7c9SViresh Kumar         Ok(Self(
6886ebdd7c9SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of
6896ebdd7c9SViresh Kumar             // the returned reference.
6906ebdd7c9SViresh Kumar             unsafe { Policy::from_raw_mut(ptr) },
6916ebdd7c9SViresh Kumar         ))
6926ebdd7c9SViresh Kumar     }
6936ebdd7c9SViresh Kumar }
6946ebdd7c9SViresh Kumar 
6956ebdd7c9SViresh Kumar impl<'a> Deref for PolicyCpu<'a> {
6966ebdd7c9SViresh Kumar     type Target = Policy;
6976ebdd7c9SViresh Kumar 
deref(&self) -> &Self::Target6986ebdd7c9SViresh Kumar     fn deref(&self) -> &Self::Target {
6996ebdd7c9SViresh Kumar         self.0
7006ebdd7c9SViresh Kumar     }
7016ebdd7c9SViresh Kumar }
7026ebdd7c9SViresh Kumar 
7036ebdd7c9SViresh Kumar impl<'a> DerefMut for PolicyCpu<'a> {
deref_mut(&mut self) -> &mut Policy7046ebdd7c9SViresh Kumar     fn deref_mut(&mut self) -> &mut Policy {
7056ebdd7c9SViresh Kumar         self.0
7066ebdd7c9SViresh Kumar     }
7076ebdd7c9SViresh Kumar }
7086ebdd7c9SViresh Kumar 
7096ebdd7c9SViresh Kumar impl<'a> Drop for PolicyCpu<'a> {
drop(&mut self)7106ebdd7c9SViresh Kumar     fn drop(&mut self) {
7116ebdd7c9SViresh Kumar         // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`.
7126ebdd7c9SViresh Kumar         unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) };
7136ebdd7c9SViresh Kumar     }
7146ebdd7c9SViresh Kumar }
7156ebdd7c9SViresh Kumar 
7166ebdd7c9SViresh Kumar /// CPU frequency driver.
7176ebdd7c9SViresh Kumar ///
7186ebdd7c9SViresh Kumar /// Implement this trait to provide a CPU frequency driver and its callbacks.
7196ebdd7c9SViresh Kumar ///
7206ebdd7c9SViresh Kumar /// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html>
7216ebdd7c9SViresh Kumar #[vtable]
7226ebdd7c9SViresh Kumar pub trait Driver {
7236ebdd7c9SViresh Kumar     /// Driver's name.
7246ebdd7c9SViresh Kumar     const NAME: &'static CStr;
7256ebdd7c9SViresh Kumar 
7266ebdd7c9SViresh Kumar     /// Driver's flags.
7276ebdd7c9SViresh Kumar     const FLAGS: u16;
7286ebdd7c9SViresh Kumar 
7296ebdd7c9SViresh Kumar     /// Boost support.
7306ebdd7c9SViresh Kumar     const BOOST_ENABLED: bool;
7316ebdd7c9SViresh Kumar 
7326ebdd7c9SViresh Kumar     /// Policy specific data.
7336ebdd7c9SViresh Kumar     ///
7346ebdd7c9SViresh Kumar     /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying
7356ebdd7c9SViresh Kumar     /// wrapped data structure.
7366ebdd7c9SViresh Kumar     type PData: ForeignOwnable;
7376ebdd7c9SViresh Kumar 
7386ebdd7c9SViresh Kumar     /// Driver's `init` callback.
init(policy: &mut Policy) -> Result<Self::PData>7396ebdd7c9SViresh Kumar     fn init(policy: &mut Policy) -> Result<Self::PData>;
7406ebdd7c9SViresh Kumar 
7416ebdd7c9SViresh Kumar     /// Driver's `exit` callback.
exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result7426ebdd7c9SViresh Kumar     fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result {
7436ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7446ebdd7c9SViresh Kumar     }
7456ebdd7c9SViresh Kumar 
7466ebdd7c9SViresh Kumar     /// Driver's `online` callback.
online(_policy: &mut Policy) -> Result7476ebdd7c9SViresh Kumar     fn online(_policy: &mut Policy) -> Result {
7486ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7496ebdd7c9SViresh Kumar     }
7506ebdd7c9SViresh Kumar 
7516ebdd7c9SViresh Kumar     /// Driver's `offline` callback.
offline(_policy: &mut Policy) -> Result7526ebdd7c9SViresh Kumar     fn offline(_policy: &mut Policy) -> Result {
7536ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7546ebdd7c9SViresh Kumar     }
7556ebdd7c9SViresh Kumar 
7566ebdd7c9SViresh Kumar     /// Driver's `suspend` callback.
suspend(_policy: &mut Policy) -> Result7576ebdd7c9SViresh Kumar     fn suspend(_policy: &mut Policy) -> Result {
7586ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7596ebdd7c9SViresh Kumar     }
7606ebdd7c9SViresh Kumar 
7616ebdd7c9SViresh Kumar     /// Driver's `resume` callback.
resume(_policy: &mut Policy) -> Result7626ebdd7c9SViresh Kumar     fn resume(_policy: &mut Policy) -> Result {
7636ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7646ebdd7c9SViresh Kumar     }
7656ebdd7c9SViresh Kumar 
7666ebdd7c9SViresh Kumar     /// Driver's `ready` callback.
ready(_policy: &mut Policy)7676ebdd7c9SViresh Kumar     fn ready(_policy: &mut Policy) {
7686ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7696ebdd7c9SViresh Kumar     }
7706ebdd7c9SViresh Kumar 
7716ebdd7c9SViresh Kumar     /// Driver's `verify` callback.
verify(data: &mut PolicyData) -> Result7726ebdd7c9SViresh Kumar     fn verify(data: &mut PolicyData) -> Result;
7736ebdd7c9SViresh Kumar 
7746ebdd7c9SViresh Kumar     /// Driver's `setpolicy` callback.
setpolicy(_policy: &mut Policy) -> Result7756ebdd7c9SViresh Kumar     fn setpolicy(_policy: &mut Policy) -> Result {
7766ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7776ebdd7c9SViresh Kumar     }
7786ebdd7c9SViresh Kumar 
7796ebdd7c9SViresh Kumar     /// Driver's `target` callback.
target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result7806ebdd7c9SViresh Kumar     fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result {
7816ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7826ebdd7c9SViresh Kumar     }
7836ebdd7c9SViresh Kumar 
7846ebdd7c9SViresh Kumar     /// Driver's `target_index` callback.
target_index(_policy: &mut Policy, _index: TableIndex) -> Result7856ebdd7c9SViresh Kumar     fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result {
7866ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7876ebdd7c9SViresh Kumar     }
7886ebdd7c9SViresh Kumar 
7896ebdd7c9SViresh Kumar     /// Driver's `fast_switch` callback.
fast_switch(_policy: &mut Policy, _target_freq: u32) -> u327906ebdd7c9SViresh Kumar     fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 {
7916ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7926ebdd7c9SViresh Kumar     }
7936ebdd7c9SViresh Kumar 
7946ebdd7c9SViresh Kumar     /// Driver's `adjust_perf` callback.
adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize)7956ebdd7c9SViresh Kumar     fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) {
7966ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
7976ebdd7c9SViresh Kumar     }
7986ebdd7c9SViresh Kumar 
7996ebdd7c9SViresh Kumar     /// Driver's `get_intermediate` callback.
get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u328006ebdd7c9SViresh Kumar     fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 {
8016ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8026ebdd7c9SViresh Kumar     }
8036ebdd7c9SViresh Kumar 
8046ebdd7c9SViresh Kumar     /// Driver's `target_intermediate` callback.
target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result8056ebdd7c9SViresh Kumar     fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result {
8066ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8076ebdd7c9SViresh Kumar     }
8086ebdd7c9SViresh Kumar 
8096ebdd7c9SViresh Kumar     /// Driver's `get` callback.
get(_policy: &mut Policy) -> Result<u32>8106ebdd7c9SViresh Kumar     fn get(_policy: &mut Policy) -> Result<u32> {
8116ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8126ebdd7c9SViresh Kumar     }
8136ebdd7c9SViresh Kumar 
8146ebdd7c9SViresh Kumar     /// Driver's `update_limits` callback.
update_limits(_policy: &mut Policy)8156ebdd7c9SViresh Kumar     fn update_limits(_policy: &mut Policy) {
8166ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8176ebdd7c9SViresh Kumar     }
8186ebdd7c9SViresh Kumar 
8196ebdd7c9SViresh Kumar     /// Driver's `bios_limit` callback.
bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result8206ebdd7c9SViresh Kumar     fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result {
8216ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8226ebdd7c9SViresh Kumar     }
8236ebdd7c9SViresh Kumar 
8246ebdd7c9SViresh Kumar     /// Driver's `set_boost` callback.
set_boost(_policy: &mut Policy, _state: i32) -> Result8256ebdd7c9SViresh Kumar     fn set_boost(_policy: &mut Policy, _state: i32) -> Result {
8266ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8276ebdd7c9SViresh Kumar     }
8286ebdd7c9SViresh Kumar 
8296ebdd7c9SViresh Kumar     /// Driver's `register_em` callback.
register_em(_policy: &mut Policy)8306ebdd7c9SViresh Kumar     fn register_em(_policy: &mut Policy) {
8316ebdd7c9SViresh Kumar         build_error!(VTABLE_DEFAULT_ERROR)
8326ebdd7c9SViresh Kumar     }
8336ebdd7c9SViresh Kumar }
834c6af9a11SViresh Kumar 
835c6af9a11SViresh Kumar /// CPU frequency driver Registration.
836c6af9a11SViresh Kumar ///
837c6af9a11SViresh Kumar /// ## Examples
838c6af9a11SViresh Kumar ///
839c6af9a11SViresh Kumar /// The following example demonstrates how to register a cpufreq driver.
840c6af9a11SViresh Kumar ///
841c6af9a11SViresh Kumar /// ```
842c6af9a11SViresh Kumar /// use kernel::{
843c6af9a11SViresh Kumar ///     cpufreq,
844c6af9a11SViresh Kumar ///     c_str,
845c6af9a11SViresh Kumar ///     device::{Core, Device},
846c6af9a11SViresh Kumar ///     macros::vtable,
847c6af9a11SViresh Kumar ///     of, platform,
848c6af9a11SViresh Kumar ///     sync::Arc,
849c6af9a11SViresh Kumar /// };
850c6af9a11SViresh Kumar /// struct SampleDevice;
851c6af9a11SViresh Kumar ///
852c6af9a11SViresh Kumar /// #[derive(Default)]
853c6af9a11SViresh Kumar /// struct SampleDriver;
854c6af9a11SViresh Kumar ///
855c6af9a11SViresh Kumar /// #[vtable]
856c6af9a11SViresh Kumar /// impl cpufreq::Driver for SampleDriver {
857c6af9a11SViresh Kumar ///     const NAME: &'static CStr = c_str!("cpufreq-sample");
858c6af9a11SViresh Kumar ///     const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
859c6af9a11SViresh Kumar ///     const BOOST_ENABLED: bool = true;
860c6af9a11SViresh Kumar ///
861c6af9a11SViresh Kumar ///     type PData = Arc<SampleDevice>;
862c6af9a11SViresh Kumar ///
863c6af9a11SViresh Kumar ///     fn init(policy: &mut cpufreq::Policy) -> Result<Self::PData> {
864c6af9a11SViresh Kumar ///         // Initialize here
865c6af9a11SViresh Kumar ///         Ok(Arc::new(SampleDevice, GFP_KERNEL)?)
866c6af9a11SViresh Kumar ///     }
867c6af9a11SViresh Kumar ///
868c6af9a11SViresh Kumar ///     fn exit(_policy: &mut cpufreq::Policy, _data: Option<Self::PData>) -> Result {
869c6af9a11SViresh Kumar ///         Ok(())
870c6af9a11SViresh Kumar ///     }
871c6af9a11SViresh Kumar ///
872c6af9a11SViresh Kumar ///     fn suspend(policy: &mut cpufreq::Policy) -> Result {
873c6af9a11SViresh Kumar ///         policy.generic_suspend()
874c6af9a11SViresh Kumar ///     }
875c6af9a11SViresh Kumar ///
876c6af9a11SViresh Kumar ///     fn verify(data: &mut cpufreq::PolicyData) -> Result {
877c6af9a11SViresh Kumar ///         data.generic_verify()
878c6af9a11SViresh Kumar ///     }
879c6af9a11SViresh Kumar ///
880c6af9a11SViresh Kumar ///     fn target_index(policy: &mut cpufreq::Policy, index: cpufreq::TableIndex) -> Result {
881c6af9a11SViresh Kumar ///         // Update CPU frequency
882c6af9a11SViresh Kumar ///         Ok(())
883c6af9a11SViresh Kumar ///     }
884c6af9a11SViresh Kumar ///
885c6af9a11SViresh Kumar ///     fn get(policy: &mut cpufreq::Policy) -> Result<u32> {
886c6af9a11SViresh Kumar ///         policy.generic_get()
887c6af9a11SViresh Kumar ///     }
888c6af9a11SViresh Kumar /// }
889c6af9a11SViresh Kumar ///
890c6af9a11SViresh Kumar /// impl platform::Driver for SampleDriver {
891c6af9a11SViresh Kumar ///     type IdInfo = ();
892c6af9a11SViresh Kumar ///     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
893c6af9a11SViresh Kumar ///
894c6af9a11SViresh Kumar ///     fn probe(
895c6af9a11SViresh Kumar ///         pdev: &platform::Device<Core>,
896c6af9a11SViresh Kumar ///         _id_info: Option<&Self::IdInfo>,
897c6af9a11SViresh Kumar ///     ) -> Result<Pin<KBox<Self>>> {
898c6af9a11SViresh Kumar ///         cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;
899c6af9a11SViresh Kumar ///         Ok(KBox::new(Self {}, GFP_KERNEL)?.into())
900c6af9a11SViresh Kumar ///     }
901c6af9a11SViresh Kumar /// }
902c6af9a11SViresh Kumar /// ```
903c6af9a11SViresh Kumar #[repr(transparent)]
904c6af9a11SViresh Kumar pub struct Registration<T: Driver>(KBox<UnsafeCell<bindings::cpufreq_driver>>, PhantomData<T>);
905c6af9a11SViresh Kumar 
906c6af9a11SViresh Kumar /// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
907c6af9a11SViresh Kumar /// or CPUs, so it is safe to share it.
908c6af9a11SViresh Kumar unsafe impl<T: Driver> Sync for Registration<T> {}
909c6af9a11SViresh Kumar 
910c6af9a11SViresh Kumar #[allow(clippy::non_send_fields_in_send_ty)]
911c6af9a11SViresh Kumar /// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any
912c6af9a11SViresh Kumar /// thread.
913c6af9a11SViresh Kumar unsafe impl<T: Driver> Send for Registration<T> {}
914c6af9a11SViresh Kumar 
915c6af9a11SViresh Kumar impl<T: Driver> Registration<T> {
916c6af9a11SViresh Kumar     const VTABLE: bindings::cpufreq_driver = bindings::cpufreq_driver {
917c6af9a11SViresh Kumar         name: Self::copy_name(T::NAME),
918c6af9a11SViresh Kumar         boost_enabled: T::BOOST_ENABLED,
919c6af9a11SViresh Kumar         flags: T::FLAGS,
920c6af9a11SViresh Kumar 
921c6af9a11SViresh Kumar         // Initialize mandatory callbacks.
922c6af9a11SViresh Kumar         init: Some(Self::init_callback),
923c6af9a11SViresh Kumar         verify: Some(Self::verify_callback),
924c6af9a11SViresh Kumar 
925c6af9a11SViresh Kumar         // Initialize optional callbacks based on the traits of `T`.
926c6af9a11SViresh Kumar         setpolicy: if T::HAS_SETPOLICY {
927c6af9a11SViresh Kumar             Some(Self::setpolicy_callback)
928c6af9a11SViresh Kumar         } else {
929c6af9a11SViresh Kumar             None
930c6af9a11SViresh Kumar         },
931c6af9a11SViresh Kumar         target: if T::HAS_TARGET {
932c6af9a11SViresh Kumar             Some(Self::target_callback)
933c6af9a11SViresh Kumar         } else {
934c6af9a11SViresh Kumar             None
935c6af9a11SViresh Kumar         },
936c6af9a11SViresh Kumar         target_index: if T::HAS_TARGET_INDEX {
937c6af9a11SViresh Kumar             Some(Self::target_index_callback)
938c6af9a11SViresh Kumar         } else {
939c6af9a11SViresh Kumar             None
940c6af9a11SViresh Kumar         },
941c6af9a11SViresh Kumar         fast_switch: if T::HAS_FAST_SWITCH {
942c6af9a11SViresh Kumar             Some(Self::fast_switch_callback)
943c6af9a11SViresh Kumar         } else {
944c6af9a11SViresh Kumar             None
945c6af9a11SViresh Kumar         },
946c6af9a11SViresh Kumar         adjust_perf: if T::HAS_ADJUST_PERF {
947c6af9a11SViresh Kumar             Some(Self::adjust_perf_callback)
948c6af9a11SViresh Kumar         } else {
949c6af9a11SViresh Kumar             None
950c6af9a11SViresh Kumar         },
951c6af9a11SViresh Kumar         get_intermediate: if T::HAS_GET_INTERMEDIATE {
952c6af9a11SViresh Kumar             Some(Self::get_intermediate_callback)
953c6af9a11SViresh Kumar         } else {
954c6af9a11SViresh Kumar             None
955c6af9a11SViresh Kumar         },
956c6af9a11SViresh Kumar         target_intermediate: if T::HAS_TARGET_INTERMEDIATE {
957c6af9a11SViresh Kumar             Some(Self::target_intermediate_callback)
958c6af9a11SViresh Kumar         } else {
959c6af9a11SViresh Kumar             None
960c6af9a11SViresh Kumar         },
961c6af9a11SViresh Kumar         get: if T::HAS_GET {
962c6af9a11SViresh Kumar             Some(Self::get_callback)
963c6af9a11SViresh Kumar         } else {
964c6af9a11SViresh Kumar             None
965c6af9a11SViresh Kumar         },
966c6af9a11SViresh Kumar         update_limits: if T::HAS_UPDATE_LIMITS {
967c6af9a11SViresh Kumar             Some(Self::update_limits_callback)
968c6af9a11SViresh Kumar         } else {
969c6af9a11SViresh Kumar             None
970c6af9a11SViresh Kumar         },
971c6af9a11SViresh Kumar         bios_limit: if T::HAS_BIOS_LIMIT {
972c6af9a11SViresh Kumar             Some(Self::bios_limit_callback)
973c6af9a11SViresh Kumar         } else {
974c6af9a11SViresh Kumar             None
975c6af9a11SViresh Kumar         },
976c6af9a11SViresh Kumar         online: if T::HAS_ONLINE {
977c6af9a11SViresh Kumar             Some(Self::online_callback)
978c6af9a11SViresh Kumar         } else {
979c6af9a11SViresh Kumar             None
980c6af9a11SViresh Kumar         },
981c6af9a11SViresh Kumar         offline: if T::HAS_OFFLINE {
982c6af9a11SViresh Kumar             Some(Self::offline_callback)
983c6af9a11SViresh Kumar         } else {
984c6af9a11SViresh Kumar             None
985c6af9a11SViresh Kumar         },
986c6af9a11SViresh Kumar         exit: if T::HAS_EXIT {
987c6af9a11SViresh Kumar             Some(Self::exit_callback)
988c6af9a11SViresh Kumar         } else {
989c6af9a11SViresh Kumar             None
990c6af9a11SViresh Kumar         },
991c6af9a11SViresh Kumar         suspend: if T::HAS_SUSPEND {
992c6af9a11SViresh Kumar             Some(Self::suspend_callback)
993c6af9a11SViresh Kumar         } else {
994c6af9a11SViresh Kumar             None
995c6af9a11SViresh Kumar         },
996c6af9a11SViresh Kumar         resume: if T::HAS_RESUME {
997c6af9a11SViresh Kumar             Some(Self::resume_callback)
998c6af9a11SViresh Kumar         } else {
999c6af9a11SViresh Kumar             None
1000c6af9a11SViresh Kumar         },
1001c6af9a11SViresh Kumar         ready: if T::HAS_READY {
1002c6af9a11SViresh Kumar             Some(Self::ready_callback)
1003c6af9a11SViresh Kumar         } else {
1004c6af9a11SViresh Kumar             None
1005c6af9a11SViresh Kumar         },
1006c6af9a11SViresh Kumar         set_boost: if T::HAS_SET_BOOST {
1007c6af9a11SViresh Kumar             Some(Self::set_boost_callback)
1008c6af9a11SViresh Kumar         } else {
1009c6af9a11SViresh Kumar             None
1010c6af9a11SViresh Kumar         },
1011c6af9a11SViresh Kumar         register_em: if T::HAS_REGISTER_EM {
1012c6af9a11SViresh Kumar             Some(Self::register_em_callback)
1013c6af9a11SViresh Kumar         } else {
1014c6af9a11SViresh Kumar             None
1015c6af9a11SViresh Kumar         },
1016c6af9a11SViresh Kumar         // SAFETY: All zeros is a valid value for `bindings::cpufreq_driver`.
1017c6af9a11SViresh Kumar         ..unsafe { MaybeUninit::zeroed().assume_init() }
1018c6af9a11SViresh Kumar     };
1019c6af9a11SViresh Kumar 
copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN]1020c6af9a11SViresh Kumar     const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
1021c6af9a11SViresh Kumar         let src = name.as_bytes_with_nul();
1022c6af9a11SViresh Kumar         let mut dst = [0; CPUFREQ_NAME_LEN];
1023c6af9a11SViresh Kumar 
1024c6af9a11SViresh Kumar         build_assert!(src.len() <= CPUFREQ_NAME_LEN);
1025c6af9a11SViresh Kumar 
1026c6af9a11SViresh Kumar         let mut i = 0;
1027c6af9a11SViresh Kumar         while i < src.len() {
1028c6af9a11SViresh Kumar             dst[i] = src[i];
1029c6af9a11SViresh Kumar             i += 1;
1030c6af9a11SViresh Kumar         }
1031c6af9a11SViresh Kumar 
1032c6af9a11SViresh Kumar         dst
1033c6af9a11SViresh Kumar     }
1034c6af9a11SViresh Kumar 
1035c6af9a11SViresh Kumar     /// Registers a CPU frequency driver with the cpufreq core.
new() -> Result<Self>1036c6af9a11SViresh Kumar     pub fn new() -> Result<Self> {
1037c6af9a11SViresh Kumar         // We can't use `&Self::VTABLE` directly because the cpufreq core modifies some fields in
1038c6af9a11SViresh Kumar         // the C `struct cpufreq_driver`, which requires a mutable reference.
1039c6af9a11SViresh Kumar         let mut drv = KBox::new(UnsafeCell::new(Self::VTABLE), GFP_KERNEL)?;
1040c6af9a11SViresh Kumar 
1041c6af9a11SViresh Kumar         // SAFETY: `drv` is guaranteed to be valid for the lifetime of `Registration`.
1042c6af9a11SViresh Kumar         to_result(unsafe { bindings::cpufreq_register_driver(drv.get_mut()) })?;
1043c6af9a11SViresh Kumar 
1044c6af9a11SViresh Kumar         Ok(Self(drv, PhantomData))
1045c6af9a11SViresh Kumar     }
1046c6af9a11SViresh Kumar 
1047c6af9a11SViresh Kumar     /// Same as [`Registration::new`], but does not return a [`Registration`] instance.
1048c6af9a11SViresh Kumar     ///
1049c6af9a11SViresh Kumar     /// Instead the [`Registration`] is owned by [`Devres`] and will be revoked / dropped, once the
1050c6af9a11SViresh Kumar     /// device is detached.
new_foreign_owned(dev: &Device<Bound>) -> Result1051c6af9a11SViresh Kumar     pub fn new_foreign_owned(dev: &Device<Bound>) -> Result {
1052c6af9a11SViresh Kumar         Devres::new_foreign_owned(dev, Self::new()?, GFP_KERNEL)
1053c6af9a11SViresh Kumar     }
1054c6af9a11SViresh Kumar }
1055c6af9a11SViresh Kumar 
1056c6af9a11SViresh Kumar /// CPU frequency driver callbacks.
1057c6af9a11SViresh Kumar impl<T: Driver> Registration<T> {
1058c6af9a11SViresh Kumar     /// Driver's `init` callback.
1059c6af9a11SViresh Kumar     ///
10604823a580SViresh Kumar     /// # Safety
10614823a580SViresh Kumar     ///
10624823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
10634823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int10644823a580SViresh Kumar     unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1065c6af9a11SViresh Kumar         from_result(|| {
1066c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1067c6af9a11SViresh Kumar             // lifetime of `policy`.
1068c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1069c6af9a11SViresh Kumar 
1070c6af9a11SViresh Kumar             let data = T::init(policy)?;
1071c6af9a11SViresh Kumar             policy.set_data(data)?;
1072c6af9a11SViresh Kumar             Ok(0)
1073c6af9a11SViresh Kumar         })
1074c6af9a11SViresh Kumar     }
1075c6af9a11SViresh Kumar 
1076c6af9a11SViresh Kumar     /// Driver's `exit` callback.
1077c6af9a11SViresh Kumar     ///
10784823a580SViresh Kumar     /// # Safety
10794823a580SViresh Kumar     ///
10804823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
10814823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
exit_callback(ptr: *mut bindings::cpufreq_policy)10824823a580SViresh Kumar     unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) {
1083c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1084c6af9a11SViresh Kumar         // lifetime of `policy`.
1085c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1086c6af9a11SViresh Kumar 
1087c6af9a11SViresh Kumar         let data = policy.clear_data();
1088c6af9a11SViresh Kumar         let _ = T::exit(policy, data);
1089c6af9a11SViresh Kumar     }
1090c6af9a11SViresh Kumar 
1091c6af9a11SViresh Kumar     /// Driver's `online` callback.
1092c6af9a11SViresh Kumar     ///
10934823a580SViresh Kumar     /// # Safety
10944823a580SViresh Kumar     ///
10954823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
10964823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int10974823a580SViresh Kumar     unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1098c6af9a11SViresh Kumar         from_result(|| {
1099c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1100c6af9a11SViresh Kumar             // lifetime of `policy`.
1101c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1102c6af9a11SViresh Kumar             T::online(policy).map(|()| 0)
1103c6af9a11SViresh Kumar         })
1104c6af9a11SViresh Kumar     }
1105c6af9a11SViresh Kumar 
1106c6af9a11SViresh Kumar     /// Driver's `offline` callback.
1107c6af9a11SViresh Kumar     ///
11084823a580SViresh Kumar     /// # Safety
11094823a580SViresh Kumar     ///
11104823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11114823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
offline_callback( ptr: *mut bindings::cpufreq_policy, ) -> kernel::ffi::c_int11124823a580SViresh Kumar     unsafe extern "C" fn offline_callback(
11134823a580SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
11144823a580SViresh Kumar     ) -> kernel::ffi::c_int {
1115c6af9a11SViresh Kumar         from_result(|| {
1116c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1117c6af9a11SViresh Kumar             // lifetime of `policy`.
1118c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1119c6af9a11SViresh Kumar             T::offline(policy).map(|()| 0)
1120c6af9a11SViresh Kumar         })
1121c6af9a11SViresh Kumar     }
1122c6af9a11SViresh Kumar 
1123c6af9a11SViresh Kumar     /// Driver's `suspend` callback.
1124c6af9a11SViresh Kumar     ///
11254823a580SViresh Kumar     /// # Safety
11264823a580SViresh Kumar     ///
11274823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11284823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
suspend_callback( ptr: *mut bindings::cpufreq_policy, ) -> kernel::ffi::c_int11294823a580SViresh Kumar     unsafe extern "C" fn suspend_callback(
11304823a580SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
11314823a580SViresh Kumar     ) -> kernel::ffi::c_int {
1132c6af9a11SViresh Kumar         from_result(|| {
1133c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1134c6af9a11SViresh Kumar             // lifetime of `policy`.
1135c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1136c6af9a11SViresh Kumar             T::suspend(policy).map(|()| 0)
1137c6af9a11SViresh Kumar         })
1138c6af9a11SViresh Kumar     }
1139c6af9a11SViresh Kumar 
1140c6af9a11SViresh Kumar     /// Driver's `resume` callback.
1141c6af9a11SViresh Kumar     ///
11424823a580SViresh Kumar     /// # Safety
11434823a580SViresh Kumar     ///
11444823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11454823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int11464823a580SViresh Kumar     unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
1147c6af9a11SViresh Kumar         from_result(|| {
1148c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1149c6af9a11SViresh Kumar             // lifetime of `policy`.
1150c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1151c6af9a11SViresh Kumar             T::resume(policy).map(|()| 0)
1152c6af9a11SViresh Kumar         })
1153c6af9a11SViresh Kumar     }
1154c6af9a11SViresh Kumar 
1155c6af9a11SViresh Kumar     /// Driver's `ready` callback.
1156c6af9a11SViresh Kumar     ///
11574823a580SViresh Kumar     /// # Safety
11584823a580SViresh Kumar     ///
11594823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11604823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
ready_callback(ptr: *mut bindings::cpufreq_policy)11614823a580SViresh Kumar     unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) {
1162c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1163c6af9a11SViresh Kumar         // lifetime of `policy`.
1164c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1165c6af9a11SViresh Kumar         T::ready(policy);
1166c6af9a11SViresh Kumar     }
1167c6af9a11SViresh Kumar 
1168c6af9a11SViresh Kumar     /// Driver's `verify` callback.
1169c6af9a11SViresh Kumar     ///
11704823a580SViresh Kumar     /// # Safety
11714823a580SViresh Kumar     ///
11724823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11734823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
verify_callback( ptr: *mut bindings::cpufreq_policy_data, ) -> kernel::ffi::c_int11744823a580SViresh Kumar     unsafe extern "C" fn verify_callback(
11754823a580SViresh Kumar         ptr: *mut bindings::cpufreq_policy_data,
11764823a580SViresh Kumar     ) -> kernel::ffi::c_int {
1177c6af9a11SViresh Kumar         from_result(|| {
1178c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1179c6af9a11SViresh Kumar             // lifetime of `policy`.
1180c6af9a11SViresh Kumar             let data = unsafe { PolicyData::from_raw_mut(ptr) };
1181c6af9a11SViresh Kumar             T::verify(data).map(|()| 0)
1182c6af9a11SViresh Kumar         })
1183c6af9a11SViresh Kumar     }
1184c6af9a11SViresh Kumar 
1185c6af9a11SViresh Kumar     /// Driver's `setpolicy` callback.
1186c6af9a11SViresh Kumar     ///
11874823a580SViresh Kumar     /// # Safety
11884823a580SViresh Kumar     ///
11894823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
11904823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
setpolicy_callback( ptr: *mut bindings::cpufreq_policy, ) -> kernel::ffi::c_int11914823a580SViresh Kumar     unsafe extern "C" fn setpolicy_callback(
11924823a580SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
11934823a580SViresh Kumar     ) -> kernel::ffi::c_int {
1194c6af9a11SViresh Kumar         from_result(|| {
1195c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1196c6af9a11SViresh Kumar             // lifetime of `policy`.
1197c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1198c6af9a11SViresh Kumar             T::setpolicy(policy).map(|()| 0)
1199c6af9a11SViresh Kumar         })
1200c6af9a11SViresh Kumar     }
1201c6af9a11SViresh Kumar 
1202c6af9a11SViresh Kumar     /// Driver's `target` callback.
1203c6af9a11SViresh Kumar     ///
12044823a580SViresh Kumar     /// # Safety
12054823a580SViresh Kumar     ///
12064823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
12074823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
target_callback( ptr: *mut bindings::cpufreq_policy, target_freq: u32, relation: u32, ) -> kernel::ffi::c_int12084823a580SViresh Kumar     unsafe extern "C" fn target_callback(
1209c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1210c6af9a11SViresh Kumar         target_freq: u32,
1211c6af9a11SViresh Kumar         relation: u32,
1212c6af9a11SViresh Kumar     ) -> kernel::ffi::c_int {
1213c6af9a11SViresh Kumar         from_result(|| {
1214c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1215c6af9a11SViresh Kumar             // lifetime of `policy`.
1216c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1217c6af9a11SViresh Kumar             T::target(policy, target_freq, Relation::new(relation)?).map(|()| 0)
1218c6af9a11SViresh Kumar         })
1219c6af9a11SViresh Kumar     }
1220c6af9a11SViresh Kumar 
1221c6af9a11SViresh Kumar     /// Driver's `target_index` callback.
1222c6af9a11SViresh Kumar     ///
12234823a580SViresh Kumar     /// # Safety
12244823a580SViresh Kumar     ///
12254823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
12264823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
target_index_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_int12274823a580SViresh Kumar     unsafe extern "C" fn target_index_callback(
1228c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1229c6af9a11SViresh Kumar         index: u32,
1230c6af9a11SViresh Kumar     ) -> kernel::ffi::c_int {
1231c6af9a11SViresh Kumar         from_result(|| {
1232c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1233c6af9a11SViresh Kumar             // lifetime of `policy`.
1234c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1235c6af9a11SViresh Kumar 
1236c6af9a11SViresh Kumar             // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1237c6af9a11SViresh Kumar             // frequency table.
1238c6af9a11SViresh Kumar             let index = unsafe { TableIndex::new(index as usize) };
1239c6af9a11SViresh Kumar 
1240c6af9a11SViresh Kumar             T::target_index(policy, index).map(|()| 0)
1241c6af9a11SViresh Kumar         })
1242c6af9a11SViresh Kumar     }
1243c6af9a11SViresh Kumar 
1244c6af9a11SViresh Kumar     /// Driver's `fast_switch` callback.
1245c6af9a11SViresh Kumar     ///
12464823a580SViresh Kumar     /// # Safety
12474823a580SViresh Kumar     ///
12484823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
12494823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
fast_switch_callback( ptr: *mut bindings::cpufreq_policy, target_freq: u32, ) -> kernel::ffi::c_uint12504823a580SViresh Kumar     unsafe extern "C" fn fast_switch_callback(
1251c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1252c6af9a11SViresh Kumar         target_freq: u32,
1253c6af9a11SViresh Kumar     ) -> kernel::ffi::c_uint {
1254c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1255c6af9a11SViresh Kumar         // lifetime of `policy`.
1256c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1257c6af9a11SViresh Kumar         T::fast_switch(policy, target_freq)
1258c6af9a11SViresh Kumar     }
1259c6af9a11SViresh Kumar 
1260c6af9a11SViresh Kumar     /// Driver's `adjust_perf` callback.
12614823a580SViresh Kumar     ///
12624823a580SViresh Kumar     /// # Safety
12634823a580SViresh Kumar     ///
12644823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
adjust_perf_callback( cpu: u32, min_perf: usize, target_perf: usize, capacity: usize, )12654823a580SViresh Kumar     unsafe extern "C" fn adjust_perf_callback(
1266c6af9a11SViresh Kumar         cpu: u32,
1267c6af9a11SViresh Kumar         min_perf: usize,
1268c6af9a11SViresh Kumar         target_perf: usize,
1269c6af9a11SViresh Kumar         capacity: usize,
1270c6af9a11SViresh Kumar     ) {
1271*33db8c97SViresh Kumar         // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1272*33db8c97SViresh Kumar         let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
1273*33db8c97SViresh Kumar 
1274*33db8c97SViresh Kumar         if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) {
1275c6af9a11SViresh Kumar             T::adjust_perf(&mut policy, min_perf, target_perf, capacity);
1276c6af9a11SViresh Kumar         }
1277c6af9a11SViresh Kumar     }
1278c6af9a11SViresh Kumar 
1279c6af9a11SViresh Kumar     /// Driver's `get_intermediate` callback.
1280c6af9a11SViresh Kumar     ///
12814823a580SViresh Kumar     /// # Safety
12824823a580SViresh Kumar     ///
12834823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
12844823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
get_intermediate_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_uint12854823a580SViresh Kumar     unsafe extern "C" fn get_intermediate_callback(
1286c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1287c6af9a11SViresh Kumar         index: u32,
1288c6af9a11SViresh Kumar     ) -> kernel::ffi::c_uint {
1289c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1290c6af9a11SViresh Kumar         // lifetime of `policy`.
1291c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1292c6af9a11SViresh Kumar 
1293c6af9a11SViresh Kumar         // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1294c6af9a11SViresh Kumar         // frequency table.
1295c6af9a11SViresh Kumar         let index = unsafe { TableIndex::new(index as usize) };
1296c6af9a11SViresh Kumar 
1297c6af9a11SViresh Kumar         T::get_intermediate(policy, index)
1298c6af9a11SViresh Kumar     }
1299c6af9a11SViresh Kumar 
1300c6af9a11SViresh Kumar     /// Driver's `target_intermediate` callback.
1301c6af9a11SViresh Kumar     ///
13024823a580SViresh Kumar     /// # Safety
13034823a580SViresh Kumar     ///
13044823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
13054823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
target_intermediate_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_int13064823a580SViresh Kumar     unsafe extern "C" fn target_intermediate_callback(
1307c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1308c6af9a11SViresh Kumar         index: u32,
1309c6af9a11SViresh Kumar     ) -> kernel::ffi::c_int {
1310c6af9a11SViresh Kumar         from_result(|| {
1311c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1312c6af9a11SViresh Kumar             // lifetime of `policy`.
1313c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1314c6af9a11SViresh Kumar 
1315c6af9a11SViresh Kumar             // SAFETY: The C code guarantees that `index` corresponds to a valid entry in the
1316c6af9a11SViresh Kumar             // frequency table.
1317c6af9a11SViresh Kumar             let index = unsafe { TableIndex::new(index as usize) };
1318c6af9a11SViresh Kumar 
1319c6af9a11SViresh Kumar             T::target_intermediate(policy, index).map(|()| 0)
1320c6af9a11SViresh Kumar         })
1321c6af9a11SViresh Kumar     }
1322c6af9a11SViresh Kumar 
1323c6af9a11SViresh Kumar     /// Driver's `get` callback.
13244823a580SViresh Kumar     ///
13254823a580SViresh Kumar     /// # Safety
13264823a580SViresh Kumar     ///
13274823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
get_callback(cpu: u32) -> kernel::ffi::c_uint13284823a580SViresh Kumar     unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
1329*33db8c97SViresh Kumar         // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1330*33db8c97SViresh Kumar         let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
1331*33db8c97SViresh Kumar 
1332*33db8c97SViresh Kumar         PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f))
1333c6af9a11SViresh Kumar     }
1334c6af9a11SViresh Kumar 
1335c6af9a11SViresh Kumar     /// Driver's `update_limit` callback.
13364823a580SViresh Kumar     ///
13374823a580SViresh Kumar     /// # Safety
13384823a580SViresh Kumar     ///
13394823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
13404823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
update_limits_callback(ptr: *mut bindings::cpufreq_policy)13414823a580SViresh Kumar     unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) {
1342c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1343c6af9a11SViresh Kumar         // lifetime of `policy`.
1344c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1345c6af9a11SViresh Kumar         T::update_limits(policy);
1346c6af9a11SViresh Kumar     }
1347c6af9a11SViresh Kumar 
1348c6af9a11SViresh Kumar     /// Driver's `bios_limit` callback.
1349c6af9a11SViresh Kumar     ///
13504823a580SViresh Kumar     /// # Safety
13514823a580SViresh Kumar     ///
13524823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
13534823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int13544823a580SViresh Kumar     unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
1355*33db8c97SViresh Kumar         // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
1356*33db8c97SViresh Kumar         let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
1357*33db8c97SViresh Kumar 
1358c6af9a11SViresh Kumar         from_result(|| {
1359*33db8c97SViresh Kumar             let mut policy = PolicyCpu::from_cpu(cpu_id)?;
1360c6af9a11SViresh Kumar 
1361c6af9a11SViresh Kumar             // SAFETY: `limit` is guaranteed by the C code to be valid.
1362c6af9a11SViresh Kumar             T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)
1363c6af9a11SViresh Kumar         })
1364c6af9a11SViresh Kumar     }
1365c6af9a11SViresh Kumar 
1366c6af9a11SViresh Kumar     /// Driver's `set_boost` callback.
1367c6af9a11SViresh Kumar     ///
13684823a580SViresh Kumar     /// # Safety
13694823a580SViresh Kumar     ///
13704823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
13714823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
set_boost_callback( ptr: *mut bindings::cpufreq_policy, state: i32, ) -> kernel::ffi::c_int13724823a580SViresh Kumar     unsafe extern "C" fn set_boost_callback(
1373c6af9a11SViresh Kumar         ptr: *mut bindings::cpufreq_policy,
1374c6af9a11SViresh Kumar         state: i32,
1375c6af9a11SViresh Kumar     ) -> kernel::ffi::c_int {
1376c6af9a11SViresh Kumar         from_result(|| {
1377c6af9a11SViresh Kumar             // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1378c6af9a11SViresh Kumar             // lifetime of `policy`.
1379c6af9a11SViresh Kumar             let policy = unsafe { Policy::from_raw_mut(ptr) };
1380c6af9a11SViresh Kumar             T::set_boost(policy, state).map(|()| 0)
1381c6af9a11SViresh Kumar         })
1382c6af9a11SViresh Kumar     }
1383c6af9a11SViresh Kumar 
1384c6af9a11SViresh Kumar     /// Driver's `register_em` callback.
1385c6af9a11SViresh Kumar     ///
13864823a580SViresh Kumar     /// # Safety
13874823a580SViresh Kumar     ///
13884823a580SViresh Kumar     /// - This function may only be called from the cpufreq C infrastructure.
13894823a580SViresh Kumar     /// - The pointer arguments must be valid pointers.
register_em_callback(ptr: *mut bindings::cpufreq_policy)13904823a580SViresh Kumar     unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) {
1391c6af9a11SViresh Kumar         // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
1392c6af9a11SViresh Kumar         // lifetime of `policy`.
1393c6af9a11SViresh Kumar         let policy = unsafe { Policy::from_raw_mut(ptr) };
1394c6af9a11SViresh Kumar         T::register_em(policy);
1395c6af9a11SViresh Kumar     }
1396c6af9a11SViresh Kumar }
1397c6af9a11SViresh Kumar 
1398c6af9a11SViresh Kumar impl<T: Driver> Drop for Registration<T> {
1399c6af9a11SViresh Kumar     /// Unregisters with the cpufreq core.
drop(&mut self)1400c6af9a11SViresh Kumar     fn drop(&mut self) {
1401c6af9a11SViresh Kumar         // SAFETY: `self.0` is guaranteed to be valid for the lifetime of `Registration`.
1402c6af9a11SViresh Kumar         unsafe { bindings::cpufreq_unregister_driver(self.0.get_mut()) };
1403c6af9a11SViresh Kumar     }
1404c6af9a11SViresh Kumar }
1405