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