Loading rust/kernel/cpufreq.rs +461 −2 Original line number Diff line number Diff line Loading @@ -10,13 +10,25 @@ use crate::{ clk::Hertz, error::{code::*, to_result, Result}, cpumask, device::Device, error::{code::*, from_err_ptr, to_result, Result, VTABLE_DEFAULT_ERROR}, ffi::c_ulong, prelude::*, types::ForeignOwnable, types::Opaque, }; use core::{ops::Deref, pin::Pin}; #[cfg(CONFIG_COMMON_CLK)] use crate::clk::Clk; use core::{ ops::{Deref, DerefMut}, pin::Pin, ptr, }; use macros::vtable; /// Default transition latency value in nanoseconds. pub const ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32; Loading Loading @@ -363,3 +375,450 @@ pub fn to_table(mut self) -> Result<TableBox> { TableBox::new(self.entries) } } /// CPU frequency policy. /// /// Rust abstraction for the C `struct cpufreq_policy`. /// /// # Invariants /// /// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`. /// /// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid /// for the lifetime of the returned reference. /// /// ## Examples /// /// The following example demonstrates how to create a CPU frequency table. /// /// ``` /// use kernel::cpufreq::{ETERNAL_LATENCY_NS, Policy}; /// /// fn update_policy(policy: &mut Policy) { /// policy /// .set_dvfs_possible_from_any_cpu(true) /// .set_fast_switch_possible(true) /// .set_transition_latency_ns(ETERNAL_LATENCY_NS); /// /// pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur())); /// } /// ``` #[repr(transparent)] pub struct Policy(Opaque<bindings::cpufreq_policy>); impl Policy { /// Creates a reference to an existing `struct cpufreq_policy` pointer. /// /// # Safety /// /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime /// of the returned reference. #[inline] pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self { // SAFETY: Guaranteed by the safety requirements of the function. // // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the // lifetime of the returned reference. unsafe { &*ptr.cast() } } /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer. /// /// # Safety /// /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime /// of the returned reference. #[inline] pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self { // SAFETY: Guaranteed by the safety requirements of the function. // // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the // lifetime of the returned reference. unsafe { &mut *ptr.cast() } } /// Returns a raw mutable pointer to the C `struct cpufreq_policy`. #[inline] fn as_raw(&self) -> *mut bindings::cpufreq_policy { let this: *const Self = self; this.cast_mut().cast() } #[inline] fn as_ref(&self) -> &bindings::cpufreq_policy { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { &*self.as_raw() } } #[inline] fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { &mut *self.as_raw() } } /// Returns the primary CPU for the [`Policy`]. #[inline] pub fn cpu(&self) -> u32 { self.as_ref().cpu } /// Returns the minimum frequency for the [`Policy`]. #[inline] pub fn min(&self) -> Hertz { Hertz::from_khz(self.as_ref().min as usize) } /// Set the minimum frequency for the [`Policy`]. #[inline] pub fn set_min(&mut self, min: Hertz) -> &mut Self { self.as_mut_ref().min = min.as_khz() as u32; self } /// Returns the maximum frequency for the [`Policy`]. #[inline] pub fn max(&self) -> Hertz { Hertz::from_khz(self.as_ref().max as usize) } /// Set the maximum frequency for the [`Policy`]. #[inline] pub fn set_max(&mut self, max: Hertz) -> &mut Self { self.as_mut_ref().max = max.as_khz() as u32; self } /// Returns the current frequency for the [`Policy`]. #[inline] pub fn cur(&self) -> Hertz { Hertz::from_khz(self.as_ref().cur as usize) } /// Returns the suspend frequency for the [`Policy`]. #[inline] pub fn suspend_freq(&self) -> Hertz { Hertz::from_khz(self.as_ref().suspend_freq as usize) } /// Sets the suspend frequency for the [`Policy`]. #[inline] pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self { self.as_mut_ref().suspend_freq = freq.as_khz() as u32; self } /// Provides a wrapper to the generic suspend routine. #[inline] pub fn generic_suspend(&mut self) -> Result { // SAFETY: By the type invariant, the pointer stored in `self` is valid. to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) }) } /// Provides a wrapper to the generic get routine. #[inline] pub fn generic_get(&self) -> Result<u32> { // SAFETY: By the type invariant, the pointer stored in `self` is valid. Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) } /// Provides a wrapper to the register with energy model using the OPP core. #[cfg(CONFIG_PM_OPP)] #[inline] pub fn register_em_opp(&mut self) { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) }; } /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`]. #[inline] pub fn cpus(&mut self) -> &mut cpumask::Cpumask { // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of // the returned reference. unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) } } /// Sets clock for the [`Policy`]. /// /// # Safety /// /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used /// by the C code. #[cfg(CONFIG_COMMON_CLK)] pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> { let clk = Clk::get(dev, name)?; self.as_mut_ref().clk = clk.as_raw(); Ok(clk) } /// Allows / disallows frequency switching code to run on any CPU. #[inline] pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self { self.as_mut_ref().dvfs_possible_from_any_cpu = val; self } /// Returns if fast switching of frequencies is possible or not. #[inline] pub fn fast_switch_possible(&self) -> bool { self.as_ref().fast_switch_possible } /// Enables / disables fast frequency switching. #[inline] pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self { self.as_mut_ref().fast_switch_possible = val; self } /// Sets transition latency (in nanoseconds) for the [`Policy`]. #[inline] pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self { self.as_mut_ref().cpuinfo.transition_latency = latency_ns; self } /// Sets cpuinfo `min_freq`. #[inline] pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self { self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32; self } /// Sets cpuinfo `max_freq`. #[inline] pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self { self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32; self } /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change /// requests. #[inline] pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self { self.as_mut_ref().transition_delay_us = transition_delay_us; self } /// Returns reference to the CPU frequency [`Table`] for the [`Policy`]. pub fn freq_table(&self) -> Result<&Table> { if self.as_ref().freq_table.is_null() { return Err(EINVAL); } // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the // lifetime of the returned reference. Ok(unsafe { Table::from_raw(self.as_ref().freq_table) }) } /// Sets the CPU frequency [`Table`] for the [`Policy`]. /// /// # Safety /// /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the /// C code. #[inline] pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self { self.as_mut_ref().freq_table = table.as_raw(); self } /// Returns the [`Policy`]'s private data. pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> { if self.as_ref().driver_data.is_null() { None } else { // SAFETY: The data is earlier set from [`set_data`]. Some(unsafe { T::borrow(self.as_ref().driver_data) }) } } /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper. /// /// # Errors /// /// Returns `EBUSY` if private data is already set. fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result { if self.as_ref().driver_data.is_null() { // Transfer the ownership of the data to the foreign interface. self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _; Ok(()) } else { Err(EBUSY) } } /// Clears and returns ownership of the private data. fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> { if self.as_ref().driver_data.is_null() { None } else { let data = Some( // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take // back the ownership of the data from the foreign interface. unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data) }, ); self.as_mut_ref().driver_data = ptr::null_mut(); data } } } /// CPU frequency policy created from a CPU number. /// /// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe /// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is /// dropped. struct PolicyCpu<'a>(&'a mut Policy); impl<'a> PolicyCpu<'a> { fn from_cpu(cpu: u32) -> Result<Self> { // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; Ok(Self( // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of // the returned reference. unsafe { Policy::from_raw_mut(ptr) }, )) } } impl<'a> Deref for PolicyCpu<'a> { type Target = Policy; fn deref(&self) -> &Self::Target { self.0 } } impl<'a> DerefMut for PolicyCpu<'a> { fn deref_mut(&mut self) -> &mut Policy { self.0 } } impl<'a> Drop for PolicyCpu<'a> { fn drop(&mut self) { // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`. unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) }; } } /// CPU frequency driver. /// /// Implement this trait to provide a CPU frequency driver and its callbacks. /// /// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html> #[vtable] pub trait Driver { /// Driver's name. const NAME: &'static CStr; /// Driver's flags. const FLAGS: u16; /// Boost support. const BOOST_ENABLED: bool; /// Policy specific data. /// /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying /// wrapped data structure. type PData: ForeignOwnable; /// Driver's `init` callback. fn init(policy: &mut Policy) -> Result<Self::PData>; /// Driver's `exit` callback. fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `online` callback. fn online(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `offline` callback. fn offline(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `suspend` callback. fn suspend(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `resume` callback. fn resume(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `ready` callback. fn ready(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `verify` callback. fn verify(data: &mut PolicyData) -> Result; /// Driver's `setpolicy` callback. fn setpolicy(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target` callback. fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target_index` callback. fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `fast_switch` callback. fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `adjust_perf` callback. fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `get_intermediate` callback. fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target_intermediate` callback. fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `get` callback. fn get(_policy: &mut Policy) -> Result<u32> { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `update_limits` callback. fn update_limits(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `bios_limit` callback. fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `set_boost` callback. fn set_boost(_policy: &mut Policy, _state: i32) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `register_em` callback. fn register_em(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } } Loading
rust/kernel/cpufreq.rs +461 −2 Original line number Diff line number Diff line Loading @@ -10,13 +10,25 @@ use crate::{ clk::Hertz, error::{code::*, to_result, Result}, cpumask, device::Device, error::{code::*, from_err_ptr, to_result, Result, VTABLE_DEFAULT_ERROR}, ffi::c_ulong, prelude::*, types::ForeignOwnable, types::Opaque, }; use core::{ops::Deref, pin::Pin}; #[cfg(CONFIG_COMMON_CLK)] use crate::clk::Clk; use core::{ ops::{Deref, DerefMut}, pin::Pin, ptr, }; use macros::vtable; /// Default transition latency value in nanoseconds. pub const ETERNAL_LATENCY_NS: u32 = bindings::CPUFREQ_ETERNAL as u32; Loading Loading @@ -363,3 +375,450 @@ pub fn to_table(mut self) -> Result<TableBox> { TableBox::new(self.entries) } } /// CPU frequency policy. /// /// Rust abstraction for the C `struct cpufreq_policy`. /// /// # Invariants /// /// A [`Policy`] instance always corresponds to a valid C `struct cpufreq_policy`. /// /// The callers must ensure that the `struct cpufreq_policy` is valid for access and remains valid /// for the lifetime of the returned reference. /// /// ## Examples /// /// The following example demonstrates how to create a CPU frequency table. /// /// ``` /// use kernel::cpufreq::{ETERNAL_LATENCY_NS, Policy}; /// /// fn update_policy(policy: &mut Policy) { /// policy /// .set_dvfs_possible_from_any_cpu(true) /// .set_fast_switch_possible(true) /// .set_transition_latency_ns(ETERNAL_LATENCY_NS); /// /// pr_info!("The policy details are: {:?}\n", (policy.cpu(), policy.cur())); /// } /// ``` #[repr(transparent)] pub struct Policy(Opaque<bindings::cpufreq_policy>); impl Policy { /// Creates a reference to an existing `struct cpufreq_policy` pointer. /// /// # Safety /// /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime /// of the returned reference. #[inline] pub unsafe fn from_raw<'a>(ptr: *const bindings::cpufreq_policy) -> &'a Self { // SAFETY: Guaranteed by the safety requirements of the function. // // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the // lifetime of the returned reference. unsafe { &*ptr.cast() } } /// Creates a mutable reference to an existing `struct cpufreq_policy` pointer. /// /// # Safety /// /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime /// of the returned reference. #[inline] pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpufreq_policy) -> &'a mut Self { // SAFETY: Guaranteed by the safety requirements of the function. // // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the // lifetime of the returned reference. unsafe { &mut *ptr.cast() } } /// Returns a raw mutable pointer to the C `struct cpufreq_policy`. #[inline] fn as_raw(&self) -> *mut bindings::cpufreq_policy { let this: *const Self = self; this.cast_mut().cast() } #[inline] fn as_ref(&self) -> &bindings::cpufreq_policy { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { &*self.as_raw() } } #[inline] fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { &mut *self.as_raw() } } /// Returns the primary CPU for the [`Policy`]. #[inline] pub fn cpu(&self) -> u32 { self.as_ref().cpu } /// Returns the minimum frequency for the [`Policy`]. #[inline] pub fn min(&self) -> Hertz { Hertz::from_khz(self.as_ref().min as usize) } /// Set the minimum frequency for the [`Policy`]. #[inline] pub fn set_min(&mut self, min: Hertz) -> &mut Self { self.as_mut_ref().min = min.as_khz() as u32; self } /// Returns the maximum frequency for the [`Policy`]. #[inline] pub fn max(&self) -> Hertz { Hertz::from_khz(self.as_ref().max as usize) } /// Set the maximum frequency for the [`Policy`]. #[inline] pub fn set_max(&mut self, max: Hertz) -> &mut Self { self.as_mut_ref().max = max.as_khz() as u32; self } /// Returns the current frequency for the [`Policy`]. #[inline] pub fn cur(&self) -> Hertz { Hertz::from_khz(self.as_ref().cur as usize) } /// Returns the suspend frequency for the [`Policy`]. #[inline] pub fn suspend_freq(&self) -> Hertz { Hertz::from_khz(self.as_ref().suspend_freq as usize) } /// Sets the suspend frequency for the [`Policy`]. #[inline] pub fn set_suspend_freq(&mut self, freq: Hertz) -> &mut Self { self.as_mut_ref().suspend_freq = freq.as_khz() as u32; self } /// Provides a wrapper to the generic suspend routine. #[inline] pub fn generic_suspend(&mut self) -> Result { // SAFETY: By the type invariant, the pointer stored in `self` is valid. to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_mut_ref()) }) } /// Provides a wrapper to the generic get routine. #[inline] pub fn generic_get(&self) -> Result<u32> { // SAFETY: By the type invariant, the pointer stored in `self` is valid. Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) } /// Provides a wrapper to the register with energy model using the OPP core. #[cfg(CONFIG_PM_OPP)] #[inline] pub fn register_em_opp(&mut self) { // SAFETY: By the type invariant, the pointer stored in `self` is valid. unsafe { bindings::cpufreq_register_em_with_opp(self.as_mut_ref()) }; } /// Gets [`cpumask::Cpumask`] for a cpufreq [`Policy`]. #[inline] pub fn cpus(&mut self) -> &mut cpumask::Cpumask { // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of // the returned reference. unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) } } /// Sets clock for the [`Policy`]. /// /// # Safety /// /// The caller must guarantee that the returned [`Clk`] is not dropped while it is getting used /// by the C code. #[cfg(CONFIG_COMMON_CLK)] pub unsafe fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result<Clk> { let clk = Clk::get(dev, name)?; self.as_mut_ref().clk = clk.as_raw(); Ok(clk) } /// Allows / disallows frequency switching code to run on any CPU. #[inline] pub fn set_dvfs_possible_from_any_cpu(&mut self, val: bool) -> &mut Self { self.as_mut_ref().dvfs_possible_from_any_cpu = val; self } /// Returns if fast switching of frequencies is possible or not. #[inline] pub fn fast_switch_possible(&self) -> bool { self.as_ref().fast_switch_possible } /// Enables / disables fast frequency switching. #[inline] pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self { self.as_mut_ref().fast_switch_possible = val; self } /// Sets transition latency (in nanoseconds) for the [`Policy`]. #[inline] pub fn set_transition_latency_ns(&mut self, latency_ns: u32) -> &mut Self { self.as_mut_ref().cpuinfo.transition_latency = latency_ns; self } /// Sets cpuinfo `min_freq`. #[inline] pub fn set_cpuinfo_min_freq(&mut self, min_freq: Hertz) -> &mut Self { self.as_mut_ref().cpuinfo.min_freq = min_freq.as_khz() as u32; self } /// Sets cpuinfo `max_freq`. #[inline] pub fn set_cpuinfo_max_freq(&mut self, max_freq: Hertz) -> &mut Self { self.as_mut_ref().cpuinfo.max_freq = max_freq.as_khz() as u32; self } /// Set `transition_delay_us`, i.e. the minimum time between successive frequency change /// requests. #[inline] pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self { self.as_mut_ref().transition_delay_us = transition_delay_us; self } /// Returns reference to the CPU frequency [`Table`] for the [`Policy`]. pub fn freq_table(&self) -> Result<&Table> { if self.as_ref().freq_table.is_null() { return Err(EINVAL); } // SAFETY: The `freq_table` is guaranteed to be valid for reading and remains valid for the // lifetime of the returned reference. Ok(unsafe { Table::from_raw(self.as_ref().freq_table) }) } /// Sets the CPU frequency [`Table`] for the [`Policy`]. /// /// # Safety /// /// The caller must guarantee that the [`Table`] is not dropped while it is getting used by the /// C code. #[inline] pub unsafe fn set_freq_table(&mut self, table: &Table) -> &mut Self { self.as_mut_ref().freq_table = table.as_raw(); self } /// Returns the [`Policy`]'s private data. pub fn data<T: ForeignOwnable>(&mut self) -> Option<<T>::Borrowed<'_>> { if self.as_ref().driver_data.is_null() { None } else { // SAFETY: The data is earlier set from [`set_data`]. Some(unsafe { T::borrow(self.as_ref().driver_data) }) } } /// Sets the private data of the [`Policy`] using a foreign-ownable wrapper. /// /// # Errors /// /// Returns `EBUSY` if private data is already set. fn set_data<T: ForeignOwnable>(&mut self, data: T) -> Result { if self.as_ref().driver_data.is_null() { // Transfer the ownership of the data to the foreign interface. self.as_mut_ref().driver_data = <T as ForeignOwnable>::into_foreign(data) as _; Ok(()) } else { Err(EBUSY) } } /// Clears and returns ownership of the private data. fn clear_data<T: ForeignOwnable>(&mut self) -> Option<T> { if self.as_ref().driver_data.is_null() { None } else { let data = Some( // SAFETY: The data is earlier set by us from [`set_data`]. It is safe to take // back the ownership of the data from the foreign interface. unsafe { <T as ForeignOwnable>::from_foreign(self.as_ref().driver_data) }, ); self.as_mut_ref().driver_data = ptr::null_mut(); data } } } /// CPU frequency policy created from a CPU number. /// /// This struct represents the CPU frequency policy obtained for a specific CPU, providing safe /// access to the underlying `cpufreq_policy` and ensuring proper cleanup when the `PolicyCpu` is /// dropped. struct PolicyCpu<'a>(&'a mut Policy); impl<'a> PolicyCpu<'a> { fn from_cpu(cpu: u32) -> Result<Self> { // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; Ok(Self( // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of // the returned reference. unsafe { Policy::from_raw_mut(ptr) }, )) } } impl<'a> Deref for PolicyCpu<'a> { type Target = Policy; fn deref(&self) -> &Self::Target { self.0 } } impl<'a> DerefMut for PolicyCpu<'a> { fn deref_mut(&mut self) -> &mut Policy { self.0 } } impl<'a> Drop for PolicyCpu<'a> { fn drop(&mut self) { // SAFETY: The underlying pointer is guaranteed to be valid for the lifetime of `self`. unsafe { bindings::cpufreq_cpu_put(self.0.as_raw()) }; } } /// CPU frequency driver. /// /// Implement this trait to provide a CPU frequency driver and its callbacks. /// /// Reference: <https://docs.kernel.org/cpu-freq/cpu-drivers.html> #[vtable] pub trait Driver { /// Driver's name. const NAME: &'static CStr; /// Driver's flags. const FLAGS: u16; /// Boost support. const BOOST_ENABLED: bool; /// Policy specific data. /// /// Require that `PData` implements `ForeignOwnable`. We guarantee to never move the underlying /// wrapped data structure. type PData: ForeignOwnable; /// Driver's `init` callback. fn init(policy: &mut Policy) -> Result<Self::PData>; /// Driver's `exit` callback. fn exit(_policy: &mut Policy, _data: Option<Self::PData>) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `online` callback. fn online(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `offline` callback. fn offline(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `suspend` callback. fn suspend(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `resume` callback. fn resume(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `ready` callback. fn ready(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `verify` callback. fn verify(data: &mut PolicyData) -> Result; /// Driver's `setpolicy` callback. fn setpolicy(_policy: &mut Policy) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target` callback. fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target_index` callback. fn target_index(_policy: &mut Policy, _index: TableIndex) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `fast_switch` callback. fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `adjust_perf` callback. fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `get_intermediate` callback. fn get_intermediate(_policy: &mut Policy, _index: TableIndex) -> u32 { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `target_intermediate` callback. fn target_intermediate(_policy: &mut Policy, _index: TableIndex) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `get` callback. fn get(_policy: &mut Policy) -> Result<u32> { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `update_limits` callback. fn update_limits(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `bios_limit` callback. fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `set_boost` callback. fn set_boost(_policy: &mut Policy, _state: i32) -> Result { build_error!(VTABLE_DEFAULT_ERROR) } /// Driver's `register_em` callback. fn register_em(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } }