diff mbox series

[V10,14/15] rust: opp: Extend OPP abstractions with cpufreq support

Message ID a940d1b1a02d99fdc80ba8d0526c35a776854cb3.1744783509.git.viresh.kumar@linaro.org (mailing list archive)
State New
Headers show
Series Rust abstractions for clk, cpumask, cpufreq, OPP | expand

Commit Message

Viresh Kumar April 16, 2025, 6:39 a.m. UTC
Extend the OPP abstractions to include support for interacting with the
cpufreq core, including the ability to retrieve frequency tables from
OPP table.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 rust/kernel/opp.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

Comments

Danilo Krummrich April 16, 2025, 8:52 a.m. UTC | #1
On Wed, Apr 16, 2025 at 12:09:31PM +0530, Viresh Kumar wrote:
> Extend the OPP abstractions to include support for interacting with the
> cpufreq core, including the ability to retrieve frequency tables from
> OPP table.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  rust/kernel/opp.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
> index 44e11808793a..734be8b6d0ef 100644
> --- a/rust/kernel/opp.rs
> +++ b/rust/kernel/opp.rs
> @@ -19,6 +19,12 @@
>      types::{ARef, AlwaysRefCounted, Opaque},
>  };
>  
> +#[cfg(CONFIG_CPU_FREQ)]

This config is needed quite often, it probably makes sense to move this code in
its own Rust module, i.e.:

	#[cfg(CONFIG_CPU_FREQ)]
	pub mod freq;
Viresh Kumar April 16, 2025, 9:59 a.m. UTC | #2
On 16-04-25, 10:52, Danilo Krummrich wrote:
> This config is needed quite often, it probably makes sense to move this code in
> its own Rust module, i.e.:
> 
> 	#[cfg(CONFIG_CPU_FREQ)]
> 	pub mod freq;

Like this ?

diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index 734be8b6d0ef..f4cabe859c43 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -20,10 +20,67 @@
 };

 #[cfg(CONFIG_CPU_FREQ)]
-use crate::cpufreq;
+// Frequency table implementation.
+mod freq {
+    use crate::cpufreq;
+    use core::ops::Deref;
+    use super::*;
+
+    /// OPP frequency table.
+    ///
+    /// A [`cpufreq::Table`] created from [`Table`].
+    pub struct FreqTable {
+        dev: ARef<Device>,
+        ptr: *mut bindings::cpufreq_frequency_table,
+    }
+
+    impl FreqTable {
+        /// Creates a new instance of [`FreqTable`] from [`Table`].
+        pub(crate) fn new(table: &Table) -> Result<Self> {
+            let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();
+
+            // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
+            // requirements.
+            to_result(unsafe {
+                bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)
+            })?;
+
+            Ok(Self {
+                dev: table.dev.clone(),
+                ptr,
+            })
+        }
+
+        // Returns a reference to the underlying [`cpufreq::Table`].
+        #[inline]
+        fn table(&self) -> &cpufreq::Table {
+            // SAFETY: The `ptr` is guaranteed by the C code to be valid.
+            unsafe { cpufreq::Table::from_raw(self.ptr) }
+        }
+    }
+
+    impl Deref for FreqTable {
+        type Target = cpufreq::Table;
+
+        #[inline]
+        fn deref(&self) -> &Self::Target {
+            self.table()
+        }
+    }
+
+    impl Drop for FreqTable {
+        fn drop(&mut self) {
+            // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only
+            // freed here.
+            unsafe {
+                bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw())
+            };
+        }
+    }
+}

 #[cfg(CONFIG_CPU_FREQ)]
-use core::ops::Deref;
+pub use freq::FreqTable;

 use core::{marker::PhantomData, ptr};

@@ -502,60 +559,6 @@ extern "C" fn config_regulators(
     }
 }

-/// OPP frequency table.
-///
-/// A [`cpufreq::Table`] created from [`Table`].
-#[cfg(CONFIG_CPU_FREQ)]
-pub struct FreqTable {
-    dev: ARef<Device>,
-    ptr: *mut bindings::cpufreq_frequency_table,
-}
-
-#[cfg(CONFIG_CPU_FREQ)]
-impl FreqTable {
-    /// Creates a new instance of [`FreqTable`] from [`Table`].
-    fn new(table: &Table) -> Result<Self> {
-        let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();
-
-        // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
-        // requirements.
-        to_result(unsafe {
-            bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)
-        })?;
-
-        Ok(Self {
-            dev: table.dev.clone(),
-            ptr,
-        })
-    }
-
-    // Returns a reference to the underlying [`cpufreq::Table`].
-    #[inline]
-    fn table(&self) -> &cpufreq::Table {
-        // SAFETY: The `ptr` is guaranteed by the C code to be valid.
-        unsafe { cpufreq::Table::from_raw(self.ptr) }
-    }
-}
-
-#[cfg(CONFIG_CPU_FREQ)]
-impl Deref for FreqTable {
-    type Target = cpufreq::Table;
-
-    #[inline]
-    fn deref(&self) -> &Self::Target {
-        self.table()
-    }
-}
-
-#[cfg(CONFIG_CPU_FREQ)]
-impl Drop for FreqTable {
-    fn drop(&mut self) {
-        // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only freed
-        // here.
-        unsafe { bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw()) };
-    }
-}
-
 /// A reference-counted OPP table.
 ///
 /// Rust abstraction for the C `struct opp_table`.
Miguel Ojeda April 16, 2025, 10:31 a.m. UTC | #3
On Wed, Apr 16, 2025 at 11:59 AM Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> +// Frequency table implementation.

///

> +        // Returns a reference to the underlying [`cpufreq::Table`].

Ditto.

I wonder if we should have a `checkpatch.pl` warnings (not error) for
this -- it is not always a mistake, but there is a fair chance it is.
The likelihood increases if we notice things like ``[`...`]`` there.
Added:

    https://github.com/Rust-for-Linux/linux/issues/1157

Cheers,
Miguel
Viresh Kumar April 16, 2025, 10:40 a.m. UTC | #4
On 16-04-25, 12:31, Miguel Ojeda wrote:
> On Wed, Apr 16, 2025 at 11:59 AM Viresh Kumar <viresh.kumar@linaro.org> wrote:
> >
> > +// Frequency table implementation.
> 
> ///
> 
> > +        // Returns a reference to the underlying [`cpufreq::Table`].
> 
> Ditto.

Hmm, I did not use /// as the comments were added to private
definitions.

Sorry for the dumb question, but why should we use /// in such cases ?
They will never show up in documentation anyway, right ?
Miguel Ojeda April 16, 2025, 10:47 a.m. UTC | #5
On Wed, Apr 16, 2025 at 12:40 PM Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> Hmm, I did not use /// as the comments were added to private
> definitions.
>
> Sorry for the dumb question, but why should we use /// in such cases ?
> They will never show up in documentation anyway, right ?

It is not a dumb question at all!

The reason is that using `///` is not just for `rustdoc`, but intended
to convey it is documentation for the item, rather than a comment that
talks about implementation details or things like TODOs.

So you may have both `///` or `//` even for private items, and it is a
meaningful difference for the reader. Plus it makes it consistent with
the public ones.

Moreover, if we ever move to documenting private items, then we will
want these to be correct -- `rustdoc` supports generating docs with
private items (e.g. it puts a cute lock emoji on private items in the
lists etc.). I think some kernel developers would appreciate it -- we
could offer both versions in rust.docs.kernel.org with a toggle, for
instance.

Cheers,
Miguel
Danilo Krummrich April 16, 2025, 12:46 p.m. UTC | #6
On Wed, Apr 16, 2025 at 03:29:43PM +0530, Viresh Kumar wrote:
> On 16-04-25, 10:52, Danilo Krummrich wrote:
> > This config is needed quite often, it probably makes sense to move this code in
> > its own Rust module, i.e.:
> > 
> > 	#[cfg(CONFIG_CPU_FREQ)]
> > 	pub mod freq;
> 
> Like this ?

Yes, I thought of a separate file, but I that should work as well.

> 
> diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
> index 734be8b6d0ef..f4cabe859c43 100644
> --- a/rust/kernel/opp.rs
> +++ b/rust/kernel/opp.rs
> @@ -20,10 +20,67 @@
>  };
> 
>  #[cfg(CONFIG_CPU_FREQ)]
> -use crate::cpufreq;
> +// Frequency table implementation.
> +mod freq {
> +    use crate::cpufreq;
> +    use core::ops::Deref;
> +    use super::*;
> +
> +    /// OPP frequency table.
> +    ///
> +    /// A [`cpufreq::Table`] created from [`Table`].
> +    pub struct FreqTable {
> +        dev: ARef<Device>,
> +        ptr: *mut bindings::cpufreq_frequency_table,
> +    }
> +
> +    impl FreqTable {
> +        /// Creates a new instance of [`FreqTable`] from [`Table`].
> +        pub(crate) fn new(table: &Table) -> Result<Self> {
> +            let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();
> +
> +            // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
> +            // requirements.
> +            to_result(unsafe {
> +                bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)
> +            })?;
> +
> +            Ok(Self {
> +                dev: table.dev.clone(),
> +                ptr,
> +            })
> +        }
> +
> +        // Returns a reference to the underlying [`cpufreq::Table`].
> +        #[inline]
> +        fn table(&self) -> &cpufreq::Table {
> +            // SAFETY: The `ptr` is guaranteed by the C code to be valid.
> +            unsafe { cpufreq::Table::from_raw(self.ptr) }
> +        }
> +    }
> +
> +    impl Deref for FreqTable {
> +        type Target = cpufreq::Table;
> +
> +        #[inline]
> +        fn deref(&self) -> &Self::Target {
> +            self.table()
> +        }
> +    }
> +
> +    impl Drop for FreqTable {
> +        fn drop(&mut self) {
> +            // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only
> +            // freed here.
> +            unsafe {
> +                bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw())
> +            };
> +        }
> +    }
> +}
> 
>  #[cfg(CONFIG_CPU_FREQ)]
> -use core::ops::Deref;
> +pub use freq::FreqTable;
> 
>  use core::{marker::PhantomData, ptr};
> 
> @@ -502,60 +559,6 @@ extern "C" fn config_regulators(
>      }
>  }
> 
> -/// OPP frequency table.
> -///
> -/// A [`cpufreq::Table`] created from [`Table`].
> -#[cfg(CONFIG_CPU_FREQ)]
> -pub struct FreqTable {
> -    dev: ARef<Device>,
> -    ptr: *mut bindings::cpufreq_frequency_table,
> -}
> -
> -#[cfg(CONFIG_CPU_FREQ)]
> -impl FreqTable {
> -    /// Creates a new instance of [`FreqTable`] from [`Table`].
> -    fn new(table: &Table) -> Result<Self> {
> -        let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();
> -
> -        // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
> -        // requirements.
> -        to_result(unsafe {
> -            bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)
> -        })?;
> -
> -        Ok(Self {
> -            dev: table.dev.clone(),
> -            ptr,
> -        })
> -    }
> -
> -    // Returns a reference to the underlying [`cpufreq::Table`].
> -    #[inline]
> -    fn table(&self) -> &cpufreq::Table {
> -        // SAFETY: The `ptr` is guaranteed by the C code to be valid.
> -        unsafe { cpufreq::Table::from_raw(self.ptr) }
> -    }
> -}
> -
> -#[cfg(CONFIG_CPU_FREQ)]
> -impl Deref for FreqTable {
> -    type Target = cpufreq::Table;
> -
> -    #[inline]
> -    fn deref(&self) -> &Self::Target {
> -        self.table()
> -    }
> -}
> -
> -#[cfg(CONFIG_CPU_FREQ)]
> -impl Drop for FreqTable {
> -    fn drop(&mut self) {
> -        // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only freed
> -        // here.
> -        unsafe { bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw()) };
> -    }
> -}
> -
>  /// A reference-counted OPP table.
>  ///
>  /// Rust abstraction for the C `struct opp_table`.
> 
> -- 
> viresh
diff mbox series

Patch

diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index 44e11808793a..734be8b6d0ef 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -19,6 +19,12 @@ 
     types::{ARef, AlwaysRefCounted, Opaque},
 };
 
+#[cfg(CONFIG_CPU_FREQ)]
+use crate::cpufreq;
+
+#[cfg(CONFIG_CPU_FREQ)]
+use core::ops::Deref;
+
 use core::{marker::PhantomData, ptr};
 
 use macros::vtable;
@@ -496,6 +502,60 @@  extern "C" fn config_regulators(
     }
 }
 
+/// OPP frequency table.
+///
+/// A [`cpufreq::Table`] created from [`Table`].
+#[cfg(CONFIG_CPU_FREQ)]
+pub struct FreqTable {
+    dev: ARef<Device>,
+    ptr: *mut bindings::cpufreq_frequency_table,
+}
+
+#[cfg(CONFIG_CPU_FREQ)]
+impl FreqTable {
+    /// Creates a new instance of [`FreqTable`] from [`Table`].
+    fn new(table: &Table) -> Result<Self> {
+        let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut();
+
+        // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety
+        // requirements.
+        to_result(unsafe {
+            bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr)
+        })?;
+
+        Ok(Self {
+            dev: table.dev.clone(),
+            ptr,
+        })
+    }
+
+    // Returns a reference to the underlying [`cpufreq::Table`].
+    #[inline]
+    fn table(&self) -> &cpufreq::Table {
+        // SAFETY: The `ptr` is guaranteed by the C code to be valid.
+        unsafe { cpufreq::Table::from_raw(self.ptr) }
+    }
+}
+
+#[cfg(CONFIG_CPU_FREQ)]
+impl Deref for FreqTable {
+    type Target = cpufreq::Table;
+
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        self.table()
+    }
+}
+
+#[cfg(CONFIG_CPU_FREQ)]
+impl Drop for FreqTable {
+    fn drop(&mut self) {
+        // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only freed
+        // here.
+        unsafe { bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw()) };
+    }
+}
+
 /// A reference-counted OPP table.
 ///
 /// Rust abstraction for the C `struct opp_table`.
@@ -751,6 +811,13 @@  pub fn adjust_voltage(
         })
     }
 
+    /// Creates [`FreqTable`] from [`Table`].
+    #[cfg(CONFIG_CPU_FREQ)]
+    #[inline]
+    pub fn cpufreq_table(&mut self) -> Result<FreqTable> {
+        FreqTable::new(self)
+    }
+
     /// Configures device with [`OPP`] matching the frequency value.
     #[inline]
     pub fn set_rate(&self, freq: Hertz) -> Result<()> {