* [PATCH v3 0/3] Clk improvements
@ 2026-01-07 15:09 Daniel Almeida
2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida
` (2 more replies)
0 siblings, 3 replies; 68+ messages in thread
From: Daniel Almeida @ 2026-01-07 15:09 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Drew Fustini, Guo Ren, Fu Wei,
Uwe Kleine-König, Michael Turquette, Stephen Boyd,
Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross
Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm,
linux-clk, rust-for-linux, Daniel Almeida
This series contains a few improvements that simplifies clock handling for
drivers.
Patch 1 implements the same typestate pattern that has been used
successfully for Regulators. This is needed because otherwise drivers
will be responsible for unpreparing and disabling clocks themselves and
ultimately handling the reference counts on their own. This is
undesirable. The patch automatically encodes this information using the
type system so that no misuse can occur.
Patch 2 makes things more convenient by offering devres-managed APIs. This
lets drivers set clock parameters once and forget about lifetime
management.
Patch 3 converts clk.rs to the newer kernel-vertical style in order to make
future changes easier.
This depends on Alice Ryhl's series [0].
[0]: https://lore.kernel.org/rust-for-linux/20251218-clk-send-sync-v3-0-e48b2e2f1eac@google.com/
---
Changes in v3:
- Rebased on top of 6.19-rc4
- Dropped patch 1 (from Alice), added her series as a dependency instead
- Fixed Tyr, PWM_TH1520 drivers
- Changed clk.rs imports to kernel-vertical style
- Added support get_optional shortcut for Prepared and Enabled (i.e.:
Clk::<Enabled>::get_optional())
- Fixed misplaced #[inline] tag
Thanks, Danilo {
- Moved the devres changes into its own patch
- Require &Device<Bound> for all functions where a &Device is used
- Account for con_in in SAFETY comments where applicable
- Added backticks
}
- Link to v2: https://lore.kernel.org/r/20250910-clk-type-state-v2-0-1b97c11bb631@collabora.com
Changes in v2:
- Added Alice's patch as patch 1, since it is a dependency.
- Added devm helpers (like we did for Regulator<T>)
- Fixed missing clk_put() call in Drop (Danilo)
- Fixed missing parenthesis and wrong docs (Viresh)
- Removed extra "dev" parameter from "shutdown" example (Danilo)
- Removed useless type annotation from example (Danilo)
- Link to v1: https://lore.kernel.org/rust-for-linux/20250729-clk-type-state-v1-1-896b53816f7b@collabora.com/#r
---
Daniel Almeida (3):
rust: clk: use the type-state pattern
rust: clk: add devres-managed clks
rust: clk: use 'kernel vertical style' for imports
drivers/cpufreq/rcpufreq_dt.rs | 2 +-
drivers/gpu/drm/tyr/driver.rs | 31 +--
drivers/pwm/pwm_th1520.rs | 17 +-
rust/kernel/clk.rs | 466 +++++++++++++++++++++++++++++------------
rust/kernel/cpufreq.rs | 8 +-
5 files changed, 346 insertions(+), 178 deletions(-)
---
base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
change-id: 20250909-clk-type-state-c01aa7dd551d
prerequisite-change-id: 20250904-clk-send-sync-3cfa7f4e1ce2:v3
prerequisite-patch-id: 13476f9e7e7c3bdbcab42912948953743381b1e0
prerequisite-patch-id: 8f91583384bb4516afcac66d21ac08b3982747b2
prerequisite-patch-id: b2ad5ecbd9a395b622bc04f891b5bb276f6f6b16
Best regards,
--
Daniel Almeida <daniel.almeida@collabora.com>
^ permalink raw reply [flat|nested] 68+ messages in thread* [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-07 15:09 [PATCH v3 0/3] Clk improvements Daniel Almeida @ 2026-01-07 15:09 ` Daniel Almeida 2026-01-08 8:07 ` Maxime Ripard ` (2 more replies) 2026-01-07 15:09 ` [PATCH v3 2/3] rust: clk: add devres-managed clks Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports Daniel Almeida 2 siblings, 3 replies; 68+ messages in thread From: Daniel Almeida @ 2026-01-07 15:09 UTC (permalink / raw) To: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux, Daniel Almeida The current Clk abstraction can still be improved on the following issues: a) It only keeps track of a count to clk_get(), which means that users have to manually call disable() and unprepare(), or a variation of those, like disable_unprepare(). b) It allows repeated calls to prepare() or enable(), but it keeps no track of how often these were called, i.e., it's currently legal to write the following: clk.prepare(); clk.prepare(); clk.enable(); clk.enable(); And nothing gets undone on drop(). c) It adds a OptionalClk type that is probably not needed. There is no "struct optional_clk" in C and we should probably not add one. d) It does not let a user express the state of the clk through the type system. For example, there is currently no way to encode that a Clk is enabled via the type system alone. In light of the Regulator abstraction that was recently merged, switch this abstraction to use the type-state pattern instead. It solves both a) and b) by establishing a number of states and the valid ways to transition between them. It also automatically undoes any call to clk_get(), clk_prepare() and clk_enable() as applicable on drop(), so users do not have to do anything special before Clk goes out of scope. It solves c) by removing the OptionalClk type, which is now simply encoded as a Clk whose inner pointer is NULL. It solves d) by directly encoding the state of the Clk into the type, e.g.: Clk<Enabled> is now known to be a Clk that is enabled. The INVARIANTS section for Clk is expanded to highlight the relationship between the states and the respective reference counts that are owned by each of them. The examples are expanded to highlight how a user can transition between states, as well as highlight some of the shortcuts built into the API. The current implementation is also more flexible, in the sense that it allows for more states to be added in the future. This lets us implement different strategies for handling clocks, including one that mimics the current API, allowing for multiple calls to prepare() and enable(). The users (cpufreq.rs/ rcpufreq_dt.rs) were updated by this patch (and not a separate one) to reflect the new changes. This is needed, because otherwise this patch would break the build. Link: https://crates.io/crates/sealed [1] Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> --- drivers/cpufreq/rcpufreq_dt.rs | 2 +- drivers/gpu/drm/tyr/driver.rs | 31 +--- drivers/pwm/pwm_th1520.rs | 17 +- rust/kernel/clk.rs | 399 +++++++++++++++++++++++++++-------------- rust/kernel/cpufreq.rs | 8 +- 5 files changed, 281 insertions(+), 176 deletions(-) diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index 31e07f0279db..f1bd7d71ed54 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -41,7 +41,7 @@ struct CPUFreqDTDevice { freq_table: opp::FreqTable, _mask: CpumaskVar, _token: Option<opp::ConfigToken>, - _clk: Clk, + _clk: Clk<kernel::clk::Unprepared>, } #[derive(Default)] diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index 09711fb7fe0b..5692def25621 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -2,7 +2,7 @@ use kernel::c_str; use kernel::clk::Clk; -use kernel::clk::OptionalClk; +use kernel::clk::Enabled; use kernel::device::Bound; use kernel::device::Core; use kernel::device::Device; @@ -37,7 +37,7 @@ pub(crate) struct TyrDriver { device: ARef<TyrDevice>, } -#[pin_data(PinnedDrop)] +#[pin_data] pub(crate) struct TyrData { pub(crate) pdev: ARef<platform::Device>, @@ -92,13 +92,9 @@ fn probe( pdev: &platform::Device<Core>, _info: Option<&Self::IdInfo>, ) -> impl PinInit<Self, Error> { - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; - - core_clk.prepare_enable()?; - stacks_clk.prepare_enable()?; - coregroup_clk.prepare_enable()?; + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; + let stacks_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("stacks")))?; + let coregroup_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("coregroup")))?; let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("mali"))?; let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("sram"))?; @@ -145,17 +141,6 @@ impl PinnedDrop for TyrDriver { fn drop(self: Pin<&mut Self>) {} } -#[pinned_drop] -impl PinnedDrop for TyrData { - fn drop(self: Pin<&mut Self>) { - // TODO: the type-state pattern for Clks will fix this. - let clks = self.clks.lock(); - clks.core.disable_unprepare(); - clks.stacks.disable_unprepare(); - clks.coregroup.disable_unprepare(); - } -} - // We need to retain the name "panthor" to achieve drop-in compatibility with // the C driver in the userspace stack. const INFO: drm::DriverInfo = drm::DriverInfo { @@ -181,9 +166,9 @@ impl drm::Driver for TyrDriver { #[pin_data] struct Clocks { - core: Clk, - stacks: OptionalClk, - coregroup: OptionalClk, + core: Clk<Enabled>, + stacks: Clk<Enabled>, + coregroup: Clk<Enabled>, } #[pin_data] diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs index 043dc4dbc623..f4d03b988533 100644 --- a/drivers/pwm/pwm_th1520.rs +++ b/drivers/pwm/pwm_th1520.rs @@ -23,7 +23,7 @@ use core::ops::Deref; use kernel::{ c_str, - clk::Clk, + clk::{Clk, Enabled}, device::{Bound, Core, Device}, devres, io::mem::IoMem, @@ -90,11 +90,11 @@ struct Th1520WfHw { } /// The driver's private data struct. It holds all necessary devres managed resources. -#[pin_data(PinnedDrop)] +#[pin_data] struct Th1520PwmDriverData { #[pin] iomem: devres::Devres<IoMem<TH1520_PWM_REG_SIZE>>, - clk: Clk, + clk: Clk<Enabled>, } impl pwm::PwmOps for Th1520PwmDriverData { @@ -299,13 +299,6 @@ fn write_waveform( } } -#[pinned_drop] -impl PinnedDrop for Th1520PwmDriverData { - fn drop(self: Pin<&mut Self>) { - self.clk.disable_unprepare(); - } -} - struct Th1520PwmPlatformDriver; kernel::of_device_table!( @@ -326,9 +319,7 @@ fn probe( let dev = pdev.as_ref(); let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; - let clk = Clk::get(dev, None)?; - - clk.prepare_enable()?; + let clk = Clk::<Enabled>::get(dev, None)?; // TODO: Get exclusive ownership of the clock to prevent rate changes. // The Rust equivalent of `clk_rate_exclusive_get()` is not yet available. diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index d192fbd97861..6323b40dc7ba 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -80,17 +80,78 @@ fn from(freq: Hertz) -> Self { mod common_clk { use super::Hertz; use crate::{ - device::Device, + device::{Bound, Device}, error::{from_err_ptr, to_result, Result}, prelude::*, }; - use core::{ops::Deref, ptr}; + use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; + + mod private { + pub trait Sealed {} + + impl Sealed for super::Unprepared {} + impl Sealed for super::Prepared {} + impl Sealed for super::Enabled {} + } + + /// A trait representing the different states that a [`Clk`] can be in. + pub trait ClkState: private::Sealed { + /// Whether the clock should be disabled when dropped. + const DISABLE_ON_DROP: bool; + + /// Whether the clock should be unprepared when dropped. + const UNPREPARE_ON_DROP: bool; + } + + /// A state where the [`Clk`] is not prepared and not enabled. + pub struct Unprepared; + + /// A state where the [`Clk`] is prepared but not enabled. + pub struct Prepared; + + /// A state where the [`Clk`] is both prepared and enabled. + pub struct Enabled; + + impl ClkState for Unprepared { + const DISABLE_ON_DROP: bool = false; + const UNPREPARE_ON_DROP: bool = false; + } + + impl ClkState for Prepared { + const DISABLE_ON_DROP: bool = false; + const UNPREPARE_ON_DROP: bool = true; + } + + impl ClkState for Enabled { + const DISABLE_ON_DROP: bool = true; + const UNPREPARE_ON_DROP: bool = true; + } + + /// An error that can occur when trying to convert a [`Clk`] between states. + pub struct Error<State: ClkState> { + /// The error that occurred. + pub error: kernel::error::Error, + + /// The [`Clk`] that caused the error, so that the operation may be + /// retried. + pub clk: Clk<State>, + } /// A reference-counted clock. /// /// Rust abstraction for the C [`struct clk`]. /// + /// A [`Clk`] instance represents a clock that can be in one of several + /// states: [`Unprepared`], [`Prepared`], or [`Enabled`]. + /// + /// No action needs to be taken when a [`Clk`] is dropped. The calls to + /// `clk_unprepare()` and `clk_disable()` will be placed as applicable. + /// + /// An optional [`Clk`] is treated just like a regular [`Clk`], but its + /// inner `struct clk` pointer is `NULL`. This interfaces correctly with the + /// C API and also exposes all the methods of a regular [`Clk`] to users. + /// /// # Invariants /// /// A [`Clk`] instance holds either a pointer to a valid [`struct clk`] created by the C @@ -99,20 +160,39 @@ mod common_clk { /// Instances of this type are reference-counted. Calling [`Clk::get`] ensures that the /// allocation remains valid for the lifetime of the [`Clk`]. /// + /// The [`Prepared`] state is associated with a single count of + /// `clk_prepare()`, and the [`Enabled`] state is associated with a single + /// count of `clk_enable()`, and the [`Prepared`] state is associated with a + /// single count of `clk_prepare()` and `clk_enable()`. + /// + /// All states are associated with a single count of `clk_get()`. + /// /// # Examples /// /// The following example demonstrates how to obtain and configure a clock for a device. /// /// ``` /// use kernel::c_str; - /// use kernel::clk::{Clk, Hertz}; - /// use kernel::device::Device; + /// use kernel::clk::{Clk, Enabled, Hertz, Unprepared, Prepared}; + /// use kernel::device::{Bound, Device}; /// use kernel::error::Result; /// - /// fn configure_clk(dev: &Device) -> Result { - /// let clk = Clk::get(dev, Some(c_str!("apb_clk")))?; + /// fn configure_clk(dev: &Device<Bound>) -> Result { + /// // The fastest way is to use a version of `Clk::get` for the desired + /// // state, i.e.: + /// let clk: Clk<Enabled> = Clk::<Enabled>::get(dev, Some(c_str!("apb_clk")))?; /// - /// clk.prepare_enable()?; + /// // Any other state is also possible, e.g.: + /// let clk: Clk<Prepared> = Clk::<Prepared>::get(dev, Some(c_str!("apb_clk")))?; + /// + /// // Later: + /// let clk: Clk<Enabled> = clk.enable().map_err(|error| { + /// error.error + /// })?; + /// + /// // Note that error.clk is the original `clk` if the operation + /// // failed. It is provided as a convenience so that the operation may be + /// // retried in case of errors. /// /// let expected_rate = Hertz::from_ghz(1); /// @@ -120,111 +200,208 @@ mod common_clk { /// clk.set_rate(expected_rate)?; /// } /// - /// clk.disable_unprepare(); + /// // Nothing is needed here. The drop implementation will undo any + /// // operations as appropriate. + /// Ok(()) + /// } + /// + /// fn shutdown(clk: Clk<Enabled>) -> Result { + /// // The states can be traversed "in the reverse order" as well: + /// let clk: Clk<Prepared> = clk.disable().map_err(|error| { + /// error.error + /// })?; + /// + /// // This is of type `Clk<Unprepared>`. + /// let clk = clk.unprepare(); + /// /// Ok(()) /// } /// ``` /// /// [`struct clk`]: https://docs.kernel.org/driver-api/clk.html #[repr(transparent)] - pub struct Clk(*mut bindings::clk); + pub struct Clk<T: ClkState> { + inner: *mut bindings::clk, + _phantom: core::marker::PhantomData<T>, + } // SAFETY: It is safe to call `clk_put` on another thread than where `clk_get` was called. - unsafe impl Send for Clk {} + unsafe impl<T: ClkState> Send for Clk<T> {} // SAFETY: It is safe to call any combination of the `&self` methods in parallel, as the // methods are synchronized internally. - unsafe impl Sync for Clk {} + unsafe impl<T: ClkState> Sync for Clk<T> {} - impl Clk { - /// Gets [`Clk`] corresponding to a [`Device`] and a connection id. + impl Clk<Unprepared> { + /// Gets [`Clk`] corresponding to a bound [`Device`] and a connection + /// id. /// /// Equivalent to the kernel's [`clk_get`] API. /// /// [`clk_get`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_get - pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> { + #[inline] + pub fn get(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Unprepared>> { let con_id = name.map_or(ptr::null(), |n| n.as_char_ptr()); - // SAFETY: It is safe to call [`clk_get`] for a valid device pointer. - // + // SAFETY: It is safe to call [`clk_get`] for a valid device pointer + // and any `con_id`, including NULL. + let inner = from_err_ptr(unsafe { bindings::clk_get(dev.as_raw(), con_id) })?; + // INVARIANT: The reference-count is decremented when [`Clk`] goes out of scope. - Ok(Self(from_err_ptr(unsafe { - bindings::clk_get(dev.as_raw(), con_id) - })?)) + Ok(Self { + inner, + _phantom: PhantomData, + }) } - /// Obtain the raw [`struct clk`] pointer. + /// Behaves the same as [`Self::get`], except when there is no clock + /// producer. In this case, instead of returning [`ENOENT`], it returns + /// a dummy [`Clk`]. #[inline] - pub fn as_raw(&self) -> *mut bindings::clk { - self.0 + pub fn get_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Unprepared>> { + let con_id = name.map_or(ptr::null(), |n| n.as_char_ptr()); + + // SAFETY: It is safe to call [`clk_get`] for a valid device pointer + // and any `con_id`, including NULL. + let inner = from_err_ptr(unsafe { bindings::clk_get_optional(dev.as_raw(), con_id) })?; + + // INVARIANT: The reference-count is decremented when [`Clk`] goes out of scope. + Ok(Self { + inner, + _phantom: PhantomData, + }) } - /// Enable the clock. + /// Attempts to convert the [`Clk`] to a [`Prepared`] state. /// - /// Equivalent to the kernel's [`clk_enable`] API. + /// Equivalent to the kernel's [`clk_prepare`] API. /// - /// [`clk_enable`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_enable + /// [`clk_prepare`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_prepare #[inline] - pub fn enable(&self) -> Result { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for - // [`clk_enable`]. - to_result(unsafe { bindings::clk_enable(self.as_raw()) }) + pub fn prepare(self) -> Result<Clk<Prepared>, Error<Unprepared>> { + // We will be transferring the ownership of our `clk_get()` count to + // `Clk<Prepared>`. + let clk = ManuallyDrop::new(self); + + // SAFETY: By the type invariants, `self.0` is a valid argument for + // [`clk_prepare`]. + to_result(unsafe { bindings::clk_prepare(clk.as_raw()) }) + .map(|()| Clk { + inner: clk.inner, + _phantom: PhantomData, + }) + .map_err(|error| Error { + error, + clk: ManuallyDrop::into_inner(clk), + }) } + } - /// Disable the clock. - /// - /// Equivalent to the kernel's [`clk_disable`] API. + impl Clk<Prepared> { + /// Obtains a [`Clk`] from a bound [`Device`] and a connection id and + /// prepares it. /// - /// [`clk_disable`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_disable + /// Equivalent to calling [`Clk::get`], followed by [`Clk::prepare`], #[inline] - pub fn disable(&self) { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for - // [`clk_disable`]. - unsafe { bindings::clk_disable(self.as_raw()) }; + pub fn get(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Prepared>> { + Clk::<Unprepared>::get(dev, name)? + .prepare() + .map_err(|error| error.error) } - /// Prepare the clock. - /// - /// Equivalent to the kernel's [`clk_prepare`] API. - /// - /// [`clk_prepare`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_prepare + /// Behaves the same as [`Self::get`], except when there is no clock + /// producer. In this case, instead of returning [`ENOENT`], it returns + /// a dummy [`Clk`]. #[inline] - pub fn prepare(&self) -> Result { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for - // [`clk_prepare`]. - to_result(unsafe { bindings::clk_prepare(self.as_raw()) }) + pub fn get_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Prepared>> { + Clk::<Unprepared>::get_optional(dev, name)? + .prepare() + .map_err(|error| error.error) } - /// Unprepare the clock. + /// Attempts to convert the [`Clk`] to an [`Unprepared`] state. /// /// Equivalent to the kernel's [`clk_unprepare`] API. - /// - /// [`clk_unprepare`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_unprepare #[inline] - pub fn unprepare(&self) { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for + pub fn unprepare(self) -> Clk<Unprepared> { + // We will be transferring the ownership of our `clk_get()` count to + // `Clk<Unprepared>`. + let clk = ManuallyDrop::new(self); + + // SAFETY: By the type invariants, `self.0` is a valid argument for // [`clk_unprepare`]. - unsafe { bindings::clk_unprepare(self.as_raw()) }; + unsafe { bindings::clk_unprepare(clk.as_raw()) } + + Clk { + inner: clk.inner, + _phantom: PhantomData, + } } - /// Prepare and enable the clock. + /// Attempts to convert the [`Clk`] to an [`Enabled`] state. + /// + /// Equivalent to the kernel's [`clk_enable`] API. /// - /// Equivalent to calling [`Clk::prepare`] followed by [`Clk::enable`]. + /// [`clk_enable`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_enable #[inline] - pub fn prepare_enable(&self) -> Result { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for - // [`clk_prepare_enable`]. - to_result(unsafe { bindings::clk_prepare_enable(self.as_raw()) }) + pub fn enable(self) -> Result<Clk<Enabled>, Error<Prepared>> { + // We will be transferring the ownership of our `clk_get()` and + // `clk_prepare()` counts to `Clk<Enabled>`. + let clk = ManuallyDrop::new(self); + + // SAFETY: By the type invariants, `self.0` is a valid argument for + // [`clk_enable`]. + to_result(unsafe { bindings::clk_enable(clk.as_raw()) }) + .map(|()| Clk { + inner: clk.inner, + _phantom: PhantomData, + }) + .map_err(|error| Error { + error, + clk: ManuallyDrop::into_inner(clk), + }) } + } - /// Disable and unprepare the clock. + impl Clk<Enabled> { + /// Gets [`Clk`] corresponding to a bound [`Device`] and a connection id + /// and then prepares and enables it. /// - /// Equivalent to calling [`Clk::disable`] followed by [`Clk::unprepare`]. + /// Equivalent to calling [`Clk::get`], followed by [`Clk::prepare`], + /// followed by [`Clk::enable`]. #[inline] - pub fn disable_unprepare(&self) { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for - // [`clk_disable_unprepare`]. - unsafe { bindings::clk_disable_unprepare(self.as_raw()) }; + pub fn get(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { + Clk::<Prepared>::get(dev, name)? + .enable() + .map_err(|error| error.error) + } + + /// Behaves the same as [`Self::get`], except when there is no clock + /// producer. In this case, instead of returning [`ENOENT`], it returns + /// a dummy [`Clk`]. + #[inline] + pub fn get_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { + Clk::<Prepared>::get_optional(dev, name)? + .enable() + .map_err(|error| error.error) + } + + /// Attempts to disable the [`Clk`] and convert it to the [`Prepared`] + /// state. + #[inline] + pub fn disable(self) -> Result<Clk<Prepared>, Error<Enabled>> { + // We will be transferring the ownership of our `clk_get()` and + // `clk_enable()` counts to `Clk<Prepared>`. + let clk = ManuallyDrop::new(self); + + // SAFETY: By the type invariants, `self.0` is a valid argument for + // [`clk_disable`]. + unsafe { bindings::clk_disable(clk.as_raw()) }; + + Ok(Clk { + inner: clk.inner, + _phantom: PhantomData, + }) } /// Get clock's rate. @@ -252,83 +429,31 @@ pub fn set_rate(&self, rate: Hertz) -> Result { } } - impl Drop for Clk { - fn drop(&mut self) { - // SAFETY: By the type invariants, self.as_raw() is a valid argument for [`clk_put`]. - unsafe { bindings::clk_put(self.as_raw()) }; - } - } - - /// A reference-counted optional clock. - /// - /// A lightweight wrapper around an optional [`Clk`]. An [`OptionalClk`] represents a [`Clk`] - /// that a driver can function without but may improve performance or enable additional - /// features when available. - /// - /// # Invariants - /// - /// An [`OptionalClk`] instance encapsulates a [`Clk`] with either a valid [`struct clk`] or - /// `NULL` pointer. - /// - /// Instances of this type are reference-counted. Calling [`OptionalClk::get`] ensures that the - /// allocation remains valid for the lifetime of the [`OptionalClk`]. - /// - /// # Examples - /// - /// The following example demonstrates how to obtain and configure an optional clock for a - /// device. The code functions correctly whether or not the clock is available. - /// - /// ``` - /// use kernel::c_str; - /// use kernel::clk::{OptionalClk, Hertz}; - /// use kernel::device::Device; - /// use kernel::error::Result; - /// - /// fn configure_clk(dev: &Device) -> Result { - /// let clk = OptionalClk::get(dev, Some(c_str!("apb_clk")))?; - /// - /// clk.prepare_enable()?; - /// - /// let expected_rate = Hertz::from_ghz(1); - /// - /// if clk.rate() != expected_rate { - /// clk.set_rate(expected_rate)?; - /// } - /// - /// clk.disable_unprepare(); - /// Ok(()) - /// } - /// ``` - /// - /// [`struct clk`]: https://docs.kernel.org/driver-api/clk.html - pub struct OptionalClk(Clk); - - impl OptionalClk { - /// Gets [`OptionalClk`] corresponding to a [`Device`] and a connection id. - /// - /// Equivalent to the kernel's [`clk_get_optional`] API. - /// - /// [`clk_get_optional`]: - /// https://docs.kernel.org/core-api/kernel-api.html#c.clk_get_optional - pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> { - let con_id = name.map_or(ptr::null(), |n| n.as_char_ptr()); - - // SAFETY: It is safe to call [`clk_get_optional`] for a valid device pointer. - // - // INVARIANT: The reference-count is decremented when [`OptionalClk`] goes out of - // scope. - Ok(Self(Clk(from_err_ptr(unsafe { - bindings::clk_get_optional(dev.as_raw(), con_id) - })?))) + impl<T: ClkState> Clk<T> { + /// Obtain the raw [`struct clk`] pointer. + #[inline] + pub fn as_raw(&self) -> *mut bindings::clk { + self.inner } } - // Make [`OptionalClk`] behave like [`Clk`]. - impl Deref for OptionalClk { - type Target = Clk; + impl<T: ClkState> Drop for Clk<T> { + fn drop(&mut self) { + if T::DISABLE_ON_DROP { + // SAFETY: By the type invariants, self.as_raw() is a valid argument for + // [`clk_disable`]. + unsafe { bindings::clk_disable(self.as_raw()) }; + } + + if T::UNPREPARE_ON_DROP { + // SAFETY: By the type invariants, self.as_raw() is a valid argument for + // [`clk_unprepare`]. + unsafe { bindings::clk_unprepare(self.as_raw()) }; + } - fn deref(&self) -> &Clk { - &self.0 + // SAFETY: By the type invariants, self.as_raw() is a valid argument for + // [`clk_put`]. + unsafe { bindings::clk_put(self.as_raw()) }; } } } diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index f968fbd22890..d51c697cad9e 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -552,8 +552,12 @@ pub fn cpus(&mut self) -> &mut cpumask::Cpumask { /// 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)?; + pub unsafe fn set_clk( + &mut self, + dev: &Device<Bound>, + name: Option<&CStr>, + ) -> Result<Clk<crate::clk::Unprepared>> { + let clk = Clk::<crate::clk::Unprepared>::get(dev, name)?; self.as_mut_ref().clk = clk.as_raw(); Ok(clk) } -- 2.52.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida @ 2026-01-08 8:07 ` Maxime Ripard 2026-01-08 13:57 ` Miguel Ojeda 2026-01-08 14:14 ` Daniel Almeida 2026-01-19 14:20 ` Gary Guo 2026-02-03 9:17 ` Boris Brezillon 2 siblings, 2 replies; 68+ messages in thread From: Maxime Ripard @ 2026-01-08 8:07 UTC (permalink / raw) To: Daniel Almeida Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 4040 bytes --] Hi Daniel, On Wed, Jan 07, 2026 at 12:09:52PM -0300, Daniel Almeida wrote: > The current Clk abstraction can still be improved on the following issues: > > a) It only keeps track of a count to clk_get(), which means that users have > to manually call disable() and unprepare(), or a variation of those, like > disable_unprepare(). > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > of how often these were called, i.e., it's currently legal to write the > following: > > clk.prepare(); > clk.prepare(); > clk.enable(); > clk.enable(); > > And nothing gets undone on drop(). > > c) It adds a OptionalClk type that is probably not needed. There is no > "struct optional_clk" in C and we should probably not add one. > > d) It does not let a user express the state of the clk through the > type system. For example, there is currently no way to encode that a Clk is > enabled via the type system alone. > > In light of the Regulator abstraction that was recently merged, switch this > abstraction to use the type-state pattern instead. It solves both a) and b) > by establishing a number of states and the valid ways to transition between > them. It also automatically undoes any call to clk_get(), clk_prepare() and > clk_enable() as applicable on drop(), so users do not have to do anything > special before Clk goes out of scope. > > It solves c) by removing the OptionalClk type, which is now simply encoded > as a Clk whose inner pointer is NULL. > > It solves d) by directly encoding the state of the Clk into the type, e.g.: > Clk<Enabled> is now known to be a Clk that is enabled. > > The INVARIANTS section for Clk is expanded to highlight the relationship > between the states and the respective reference counts that are owned by > each of them. > > The examples are expanded to highlight how a user can transition between > states, as well as highlight some of the shortcuts built into the API. > > The current implementation is also more flexible, in the sense that it > allows for more states to be added in the future. This lets us implement > different strategies for handling clocks, including one that mimics the > current API, allowing for multiple calls to prepare() and enable(). > > The users (cpufreq.rs/ rcpufreq_dt.rs) were updated by this patch (and not > a separate one) to reflect the new changes. This is needed, because > otherwise this patch would break the build. > > Link: https://crates.io/crates/sealed [1] > Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> I don't know the typestate pattern that well, but I wonder if we don't paint ourselves into a corner by introducing it. While it's pretty common to get your clock from the get go into a state, and then don't modify it (like what devm_clk_get_enabled provides for example), and the typestate pattern indeed works great for those, we also have a significant number of drivers that will have a finer-grained control over the clock enablement for PM. For example, it's quite typical to have (at least) one clock for the bus interface that drives the register, and one that drives the main component logic. The former needs to be enabled only when you're accessing the registers (and can be abstracted with regmap_mmio_attach_clk for example), and the latter needs to be enabled only when the device actually starts operating. You have a similar thing for the prepare vs enable thing. The difference between the two is that enable can be called into atomic context but prepare can't. So for drivers that would care about this, you would create your device with an unprepared clock, and then at various times during the driver lifetime, you would mutate that state. AFAIU, encoding the state of the clock into the Clk type (and thus forcing the structure that holds it) prevents that mutation. If not, we should make it clearer (by expanding the doc maybe?) how such a pattern can be supported. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-08 8:07 ` Maxime Ripard @ 2026-01-08 13:57 ` Miguel Ojeda 2026-01-08 14:18 ` Daniel Almeida 2026-01-08 14:14 ` Daniel Almeida 1 sibling, 1 reply; 68+ messages in thread From: Miguel Ojeda @ 2026-01-08 13:57 UTC (permalink / raw) To: Maxime Ripard Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu, Jan 8, 2026 at 9:07 AM Maxime Ripard <mripard@kernel.org> wrote: > > AFAIU, encoding the state of the clock into the Clk type (and thus > forcing the structure that holds it) prevents that mutation. If not, we > should make it clearer (by expanding the doc maybe?) how such a pattern > can be supported. One possibility to consider in cases like this is whether supporting both cases differently makes sense, i.e. one for that covers easily/safely/... the usual "80%" of cases, and another "advanced" one (possibly unsafe etc.) for the rest. While it may be a bit more to maintain, it may pay itself off by making it easier to review the easy ones if the majority only need that etc. Cheers, Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-08 13:57 ` Miguel Ojeda @ 2026-01-08 14:18 ` Daniel Almeida 0 siblings, 0 replies; 68+ messages in thread From: Daniel Almeida @ 2026-01-08 14:18 UTC (permalink / raw) To: Miguel Ojeda Cc: Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 8 Jan 2026, at 10:57, Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > > On Thu, Jan 8, 2026 at 9:07 AM Maxime Ripard <mripard@kernel.org> wrote: >> >> AFAIU, encoding the state of the clock into the Clk type (and thus >> forcing the structure that holds it) prevents that mutation. If not, we >> should make it clearer (by expanding the doc maybe?) how such a pattern >> can be supported. > > One possibility to consider in cases like this is whether supporting > both cases differently makes sense, i.e. one for that covers > easily/safely/... the usual "80%" of cases, and another "advanced" one > (possibly unsafe etc.) for the rest. > > While it may be a bit more to maintain, it may pay itself off by > making it easier to review the easy ones if the majority only need > that etc. > > Cheers, > Miguel This is already the case. The devm_* stuff in the next patch covers a lot of simpler drivers (who might simply want to enable the clk, perhaps with a given rate), while the typestate pattern allows for more control when needed. There will be users for both, IMHO. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-08 8:07 ` Maxime Ripard 2026-01-08 13:57 ` Miguel Ojeda @ 2026-01-08 14:14 ` Daniel Almeida 2026-01-19 10:45 ` Maxime Ripard 1 sibling, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-01-08 14:14 UTC (permalink / raw) To: Maxime Ripard Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hi Maxime :) > > I don't know the typestate pattern that well, but I wonder if we don't > paint ourselves into a corner by introducing it. > > While it's pretty common to get your clock from the get go into a state, > and then don't modify it (like what devm_clk_get_enabled provides for > example), and the typestate pattern indeed works great for those, we Minor correction, devm_clk_get_enabled is not handled by the typestate pattern. The next patch does include this function for convenience, but you get a Result<()>. The typestate pattern is used when you want more control. > also have a significant number of drivers that will have a finer-grained > control over the clock enablement for PM. > > For example, it's quite typical to have (at least) one clock for the bus > interface that drives the register, and one that drives the main > component logic. The former needs to be enabled only when you're > accessing the registers (and can be abstracted with > regmap_mmio_attach_clk for example), and the latter needs to be enabled > only when the device actually starts operating. > > You have a similar thing for the prepare vs enable thing. The difference > between the two is that enable can be called into atomic context but > prepare can't. > > So for drivers that would care about this, you would create your device > with an unprepared clock, and then at various times during the driver > lifetime, you would mutate that state. > > AFAIU, encoding the state of the clock into the Clk type (and thus > forcing the structure that holds it) prevents that mutation. If not, we > should make it clearer (by expanding the doc maybe?) how such a pattern > can be supported. > > Maxime IIUC, your main point seems to be about mutating the state at runtime? This is possible with this code. You can just have an enum, for example: enum MyClocks { Unprepared(Clk<Unprepared>), Prepared(Clk<Prepared>), Enabled(Clk<Enabled>), } In fact, I specifically wanted to ensure that this was possible when writing these patches, as it’s needed by drivers. If you want to, I can cover that in the examples, no worries. Same for Regulator<T>, by the way. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-08 14:14 ` Daniel Almeida @ 2026-01-19 10:45 ` Maxime Ripard 2026-01-19 12:13 ` Daniel Almeida ` (2 more replies) 0 siblings, 3 replies; 68+ messages in thread From: Maxime Ripard @ 2026-01-19 10:45 UTC (permalink / raw) To: Daniel Almeida Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 2865 bytes --] On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > Hi Maxime :) > > > > > I don't know the typestate pattern that well, but I wonder if we don't > > paint ourselves into a corner by introducing it. > > > > While it's pretty common to get your clock from the get go into a state, > > and then don't modify it (like what devm_clk_get_enabled provides for > > example), and the typestate pattern indeed works great for those, we > > Minor correction, devm_clk_get_enabled is not handled by the typestate > pattern. The next patch does include this function for convenience, but > you get a Result<()>. The typestate pattern is used when you want more > control. > > > also have a significant number of drivers that will have a finer-grained > > control over the clock enablement for PM. > > > > For example, it's quite typical to have (at least) one clock for the bus > > interface that drives the register, and one that drives the main > > component logic. The former needs to be enabled only when you're > > accessing the registers (and can be abstracted with > > regmap_mmio_attach_clk for example), and the latter needs to be enabled > > only when the device actually starts operating. > > > > You have a similar thing for the prepare vs enable thing. The difference > > between the two is that enable can be called into atomic context but > > prepare can't. > > > > So for drivers that would care about this, you would create your device > > with an unprepared clock, and then at various times during the driver > > lifetime, you would mutate that state. > > > > AFAIU, encoding the state of the clock into the Clk type (and thus > > forcing the structure that holds it) prevents that mutation. If not, we > > should make it clearer (by expanding the doc maybe?) how such a pattern > > can be supported. > > > > Maxime > > IIUC, your main point seems to be about mutating the state at runtime? This is > possible with this code. You can just have an enum, for example: > > enum MyClocks { > Unprepared(Clk<Unprepared>), > Prepared(Clk<Prepared>), > Enabled(Clk<Enabled>), > } > > In fact, I specifically wanted to ensure that this was possible when writing > these patches, as it’s needed by drivers. If you want to, I can cover that in > the examples, no worries. Yes, that would be great. I do wonder though if it wouldn't make sense to turn it the other way around. It creates a fair share of boilerplate for a number of drivers. Can't we keep Clk the way it is as a lower-level type, and crate a ManagedClk (or whatever name you prefer) that drivers can use, and would be returned by higher-level helpers, if they so choose? That way, we do have the typestate API for whoever wants to, without creating too much boilerplate for everybody else. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 10:45 ` Maxime Ripard @ 2026-01-19 12:13 ` Daniel Almeida 2026-01-19 12:35 ` Alice Ryhl 2026-01-19 14:26 ` Gary Guo 2 siblings, 0 replies; 68+ messages in thread From: Daniel Almeida @ 2026-01-19 12:13 UTC (permalink / raw) To: Maxime Ripard Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 19 Jan 2026, at 07:45, Maxime Ripard <mripard@kernel.org> wrote: > > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >> Hi Maxime :) >> >>> >>> I don't know the typestate pattern that well, but I wonder if we don't >>> paint ourselves into a corner by introducing it. >>> >>> While it's pretty common to get your clock from the get go into a state, >>> and then don't modify it (like what devm_clk_get_enabled provides for >>> example), and the typestate pattern indeed works great for those, we >> >> Minor correction, devm_clk_get_enabled is not handled by the typestate >> pattern. The next patch does include this function for convenience, but >> you get a Result<()>. The typestate pattern is used when you want more >> control. >> >>> also have a significant number of drivers that will have a finer-grained >>> control over the clock enablement for PM. >>> >>> For example, it's quite typical to have (at least) one clock for the bus >>> interface that drives the register, and one that drives the main >>> component logic. The former needs to be enabled only when you're >>> accessing the registers (and can be abstracted with >>> regmap_mmio_attach_clk for example), and the latter needs to be enabled >>> only when the device actually starts operating. >>> >>> You have a similar thing for the prepare vs enable thing. The difference >>> between the two is that enable can be called into atomic context but >>> prepare can't. >>> >>> So for drivers that would care about this, you would create your device >>> with an unprepared clock, and then at various times during the driver >>> lifetime, you would mutate that state. >>> >>> AFAIU, encoding the state of the clock into the Clk type (and thus >>> forcing the structure that holds it) prevents that mutation. If not, we >>> should make it clearer (by expanding the doc maybe?) how such a pattern >>> can be supported. >>> >>> Maxime >> >> IIUC, your main point seems to be about mutating the state at runtime? This is >> possible with this code. You can just have an enum, for example: >> >> enum MyClocks { >> Unprepared(Clk<Unprepared>), >> Prepared(Clk<Prepared>), >> Enabled(Clk<Enabled>), >> } >> >> In fact, I specifically wanted to ensure that this was possible when writing >> these patches, as it’s needed by drivers. If you want to, I can cover that in >> the examples, no worries. > > Yes, that would be great. I do wonder though if it wouldn't make sense > to turn it the other way around. It creates a fair share of boilerplate > for a number of drivers. Can't we keep Clk the way it is as a > lower-level type, and crate a ManagedClk (or whatever name you prefer) > that drivers can use, and would be returned by higher-level helpers, if > they so choose? The problem with keeping it the way it is that you’re back to manual prepare/unprepare and enable/disable, as the type-state is what’s enforcing the correct order of calls. This is also the case when the type is dropped. In fact, one of the aims of this patch is to get rid of the current Clk type before we have more users. The current series fixes this by enforcing a sane order of operations. Most importantly, it enforces that the refcounts to get(), enable() and etc are handled correctly using the type system. It rids us of this problem, which is possible today: clk.enable(); clk.prepare(); clk.prepare(); clk.disable_unprepare(); clk.set_rate(); > > That way, we do have the typestate API for whoever wants to, without > creating too much boilerplate for everybody else. But that's how it works in this series. The typestate pattern is opt-in. If you need to "set and forget" there's the devm API that's introduced by the next patch. I can expose more devm_* APIs if you want. I'm not sure the boilerplate is significant, by the way. You can just do: Clk::<Enabled>::get(); As a starting point, and have the enum thing (which is also simple) _if_ you need to manually enable/disable at runtime. Most of the time, you will only need to mention the type state once, like I did in the call above, and then the type system will figure out the rest when transitions take place. What boilerplate did you have in mind? — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 10:45 ` Maxime Ripard 2026-01-19 12:13 ` Daniel Almeida @ 2026-01-19 12:35 ` Alice Ryhl 2026-01-19 12:54 ` Daniel Almeida ` (3 more replies) 2026-01-19 14:26 ` Gary Guo 2 siblings, 4 replies; 68+ messages in thread From: Alice Ryhl @ 2026-01-19 12:35 UTC (permalink / raw) To: Maxime Ripard Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > > > For example, it's quite typical to have (at least) one clock for the bus > > > interface that drives the register, and one that drives the main > > > component logic. The former needs to be enabled only when you're > > > accessing the registers (and can be abstracted with > > > regmap_mmio_attach_clk for example), and the latter needs to be enabled > > > only when the device actually starts operating. > > > > > > You have a similar thing for the prepare vs enable thing. The difference > > > between the two is that enable can be called into atomic context but > > > prepare can't. > > > > > > So for drivers that would care about this, you would create your device > > > with an unprepared clock, and then at various times during the driver > > > lifetime, you would mutate that state. The case where you're doing it only while accessing registers is interesting, because that means the Enable bit may be owned by a local variable. We may imagine an: let enabled = self.prepared_clk.enable_scoped(); ... use registers drop(enabled); Now ... this doesn't quite work with the current API - the current Enabled stated owns both a prepare and enable count, but the above keeps the prepare count in `self` and the enabled count in a local variable. But it could be done with a fourth state, or by a closure method: self.prepared_clk.with_enabled(|| { ... use registers }); All of this would work with an immutable variable of type Clk<Prepared>. > > > AFAIU, encoding the state of the clock into the Clk type (and thus > > > forcing the structure that holds it) prevents that mutation. If not, we > > > should make it clearer (by expanding the doc maybe?) how such a pattern > > > can be supported. > > > > > > Maxime > > > > IIUC, your main point seems to be about mutating the state at runtime? This is > > possible with this code. You can just have an enum, for example: > > > > enum MyClocks { > > Unprepared(Clk<Unprepared>), > > Prepared(Clk<Prepared>), > > Enabled(Clk<Enabled>), > > } I believe you need an extra state if the state is not bound to the scope of a function: enum MyClocks { Unprepared(Clk<Unprepared>), Prepared(Clk<Prepared>), Enabled(Clk<Enabled>), Transitioning, } since mem::replace() needs a new value before you can take ownership of the existing Clk value. > > In fact, I specifically wanted to ensure that this was possible when writing > > these patches, as it’s needed by drivers. If you want to, I can cover that in > > the examples, no worries. > > Yes, that would be great. I do wonder though if it wouldn't make sense > to turn it the other way around. It creates a fair share of boilerplate > for a number of drivers. Can't we keep Clk the way it is as a > lower-level type, and crate a ManagedClk (or whatever name you prefer) > that drivers can use, and would be returned by higher-level helpers, if > they so choose? > > That way, we do have the typestate API for whoever wants to, without > creating too much boilerplate for everybody else. I think that if you still want an API where you just call enable/disable directly on it with no protection against unbalanced calls, then that should be the special API. Probably called RawClk and functions marked unsafe. Unbalanced calls seem really dangerous and use should not be encouraged. The current type-state based API is the least-boilerplate option for drivers that exist today. Alice ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 12:35 ` Alice Ryhl @ 2026-01-19 12:54 ` Daniel Almeida 2026-01-19 13:13 ` Danilo Krummrich 2026-01-19 12:57 ` Gary Guo ` (2 subsequent siblings) 3 siblings, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-01-19 12:54 UTC (permalink / raw) To: Alice Ryhl Cc: Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: > > On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: >> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >>>> For example, it's quite typical to have (at least) one clock for the bus >>>> interface that drives the register, and one that drives the main >>>> component logic. The former needs to be enabled only when you're >>>> accessing the registers (and can be abstracted with >>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled >>>> only when the device actually starts operating. >>>> >>>> You have a similar thing for the prepare vs enable thing. The difference >>>> between the two is that enable can be called into atomic context but >>>> prepare can't. >>>> >>>> So for drivers that would care about this, you would create your device >>>> with an unprepared clock, and then at various times during the driver >>>> lifetime, you would mutate that state. > > The case where you're doing it only while accessing registers is > interesting, because that means the Enable bit may be owned by a local > variable. We may imagine an: > > let enabled = self.prepared_clk.enable_scoped(); > ... use registers > drop(enabled); Not sure I understand. You can get a Clk<Enabled>, do what you need, and then consume Clk<Enabled> to go back to Clk<Prepared>. I think I added this, but if I didn’t, it’s a trivial thing to do. > > Now ... this doesn't quite work with the current API - the current > Enabled stated owns both a prepare and enable count, but the above keeps > the prepare count in `self` and the enabled count in a local variable. > But it could be done with a fourth state, or by a closure method: > > self.prepared_clk.with_enabled(|| { > ... use registers > }); > > All of this would work with an immutable variable of type Clk<Prepared>. > >>>> AFAIU, encoding the state of the clock into the Clk type (and thus >>>> forcing the structure that holds it) prevents that mutation. If not, we >>>> should make it clearer (by expanding the doc maybe?) how such a pattern >>>> can be supported. >>>> >>>> Maxime >>> >>> IIUC, your main point seems to be about mutating the state at runtime? This is >>> possible with this code. You can just have an enum, for example: >>> >>> enum MyClocks { >>> Unprepared(Clk<Unprepared>), >>> Prepared(Clk<Prepared>), >>> Enabled(Clk<Enabled>), >>> } > > I believe you need an extra state if the state is not bound to the scope > of a function: > > enum MyClocks { > Unprepared(Clk<Unprepared>), > Prepared(Clk<Prepared>), > Enabled(Clk<Enabled>), > Transitioning, > } > > since mem::replace() needs a new value before you can take ownership of > the existing Clk value. Right, I need to update the docs to account for this, as they imply that you can do this with only two states. > >>> In fact, I specifically wanted to ensure that this was possible when writing >>> these patches, as it’s needed by drivers. If you want to, I can cover that in >>> the examples, no worries. >> >> Yes, that would be great. I do wonder though if it wouldn't make sense >> to turn it the other way around. It creates a fair share of boilerplate >> for a number of drivers. Can't we keep Clk the way it is as a >> lower-level type, and crate a ManagedClk (or whatever name you prefer) >> that drivers can use, and would be returned by higher-level helpers, if >> they so choose? >> >> That way, we do have the typestate API for whoever wants to, without >> creating too much boilerplate for everybody else. > > I think that if you still want an API where you just call enable/disable > directly on it with no protection against unbalanced calls, then that > should be the special API. Probably called RawClk and functions marked > unsafe. Unbalanced calls seem really dangerous and use should not be > encouraged. I think we should discourage RawClk if at all possible. But if the consensus is that we *really* need this easily-abused thing, I can provide a follow-up. > > The current type-state based API is the least-boilerplate option for > drivers that exist today. > > Alice ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 12:54 ` Daniel Almeida @ 2026-01-19 13:13 ` Danilo Krummrich 2026-01-19 14:18 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Danilo Krummrich @ 2026-01-19 13:13 UTC (permalink / raw) To: Daniel Almeida Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: >> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: >> I think that if you still want an API where you just call enable/disable >> directly on it with no protection against unbalanced calls, then that >> should be the special API. Probably called RawClk and functions marked >> unsafe. Unbalanced calls seem really dangerous and use should not be >> encouraged. +1; and unless there is a use-case that requires otherwise, it should not even be possible to do this at all -- at least for driver code. > I think we should discourage RawClk if at all possible. But if the consensus > is that we *really* need this easily-abused thing, I can provide a follow-up. I think we should only do this if there are use-case with no alternative, so far there haven't been any AFAIK. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 13:13 ` Danilo Krummrich @ 2026-01-19 14:18 ` Maxime Ripard 2026-01-19 14:37 ` Danilo Krummrich 0 siblings, 1 reply; 68+ messages in thread From: Maxime Ripard @ 2026-01-19 14:18 UTC (permalink / raw) To: Danilo Krummrich Cc: Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 1519 bytes --] On Mon, Jan 19, 2026 at 02:13:48PM +0100, Danilo Krummrich wrote: > On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: > >> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: > >> I think that if you still want an API where you just call enable/disable > >> directly on it with no protection against unbalanced calls, then that > >> should be the special API. Probably called RawClk and functions marked > >> unsafe. Unbalanced calls seem really dangerous and use should not be > >> encouraged. > > +1; and unless there is a use-case that requires otherwise, it should not even > be possible to do this at all -- at least for driver code. I mean, it's great, it's safe, etc. but it's also suboptimal from a PM perspective on many platforms. It's totally fine to provide nice, safe, ergonomic wrappers for the drivers that don't care (or can't, really), but treating a legitimate optimisation as something we should consider impossible to do is just weird to me. > > I think we should discourage RawClk if at all possible. But if the consensus > > is that we *really* need this easily-abused thing, I can provide a follow-up. > > I think we should only do this if there are use-case with no alternative, so far > there haven't been any AFAIK. I don't really care about which alternative we come up with, but look at devm_regmap_init_mmio_clk for example. It is a valid use-case that already exists today, and has had for more than a decade at this point. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 14:18 ` Maxime Ripard @ 2026-01-19 14:37 ` Danilo Krummrich 2026-01-22 13:44 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Danilo Krummrich @ 2026-01-19 14:37 UTC (permalink / raw) To: Maxime Ripard Cc: Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 3:18 PM CET, Maxime Ripard wrote: > On Mon, Jan 19, 2026 at 02:13:48PM +0100, Danilo Krummrich wrote: >> On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: >> >> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: >> >> I think that if you still want an API where you just call enable/disable >> >> directly on it with no protection against unbalanced calls, then that >> >> should be the special API. Probably called RawClk and functions marked >> >> unsafe. Unbalanced calls seem really dangerous and use should not be >> >> encouraged. >> >> +1; and unless there is a use-case that requires otherwise, it should not even >> be possible to do this at all -- at least for driver code. > > I mean, it's great, it's safe, etc. but it's also suboptimal from a PM > perspective on many platforms. It's totally fine to provide nice, safe, > ergonomic wrappers for the drivers that don't care (or can't, really), > but treating a legitimate optimisation as something we should consider > impossible to do is just weird to me. I said that an unsafe API with potentially unbalanced calls is something we should clearly avoid for drivers. This is *not* equivalent to "treating a legitimate optimisation as something we should consider impossible". If we discover use-cases where the current API doesn't work well, we can invenstigate further. >> > I think we should discourage RawClk if at all possible. But if the consensus >> > is that we *really* need this easily-abused thing, I can provide a follow-up. >> >> I think we should only do this if there are use-case with no alternative, so far >> there haven't been any AFAIK. > > I don't really care about which alternative we come up with, but look at > devm_regmap_init_mmio_clk for example. It is a valid use-case that > already exists today, and has had for more than a decade at this point. I don't see the issue with devm_regmap_init_mmio_clk()? It takes a reference count of the clock and prepares it when called and unprepares the clk in drops its reference in regmap_mmio_free_context() called from the devres callback. That something we can easily do with the current API, no? ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 14:37 ` Danilo Krummrich @ 2026-01-22 13:44 ` Maxime Ripard 2026-01-23 0:29 ` Daniel Almeida 2026-01-23 10:25 ` Danilo Krummrich 0 siblings, 2 replies; 68+ messages in thread From: Maxime Ripard @ 2026-01-22 13:44 UTC (permalink / raw) To: Danilo Krummrich Cc: Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 2623 bytes --] On Mon, Jan 19, 2026 at 03:37:17PM +0100, Danilo Krummrich wrote: > On Mon Jan 19, 2026 at 3:18 PM CET, Maxime Ripard wrote: > > On Mon, Jan 19, 2026 at 02:13:48PM +0100, Danilo Krummrich wrote: > >> On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: > >> >> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: > >> >> I think that if you still want an API where you just call enable/disable > >> >> directly on it with no protection against unbalanced calls, then that > >> >> should be the special API. Probably called RawClk and functions marked > >> >> unsafe. Unbalanced calls seem really dangerous and use should not be > >> >> encouraged. > >> > >> +1; and unless there is a use-case that requires otherwise, it should not even > >> be possible to do this at all -- at least for driver code. > > > > I mean, it's great, it's safe, etc. but it's also suboptimal from a PM > > perspective on many platforms. It's totally fine to provide nice, safe, > > ergonomic wrappers for the drivers that don't care (or can't, really), > > but treating a legitimate optimisation as something we should consider > > impossible to do is just weird to me. > > I said that an unsafe API with potentially unbalanced calls is something we > should clearly avoid for drivers. This is *not* equivalent to "treating a > legitimate optimisation as something we should consider impossible". > > If we discover use-cases where the current API doesn't work well, we can > invenstigate further. I'm not sure I'm following what you're saying, sorry. I've pointed out such a use-case already. > >> > I think we should discourage RawClk if at all possible. But if the consensus > >> > is that we *really* need this easily-abused thing, I can provide a follow-up. > >> > >> I think we should only do this if there are use-case with no alternative, so far > >> there haven't been any AFAIK. > > > > I don't really care about which alternative we come up with, but look at > > devm_regmap_init_mmio_clk for example. It is a valid use-case that > > already exists today, and has had for more than a decade at this point. > > I don't see the issue with devm_regmap_init_mmio_clk()? It takes a reference > count of the clock and prepares it when called and unprepares the clk in drops > its reference in regmap_mmio_free_context() called from the devres callback. > > That something we can easily do with the current API, no? The current one, yes. Doing that in the API suggested here would involve some boilerplate in all those drivers they don't have right now. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-22 13:44 ` Maxime Ripard @ 2026-01-23 0:29 ` Daniel Almeida 2026-02-04 9:15 ` Maxime Ripard 2026-01-23 10:25 ` Danilo Krummrich 1 sibling, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-01-23 0:29 UTC (permalink / raw) To: Maxime Ripard Cc: Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 22 Jan 2026, at 10:44, Maxime Ripard <mripard@kernel.org> wrote: > > On Mon, Jan 19, 2026 at 03:37:17PM +0100, Danilo Krummrich wrote: >> On Mon Jan 19, 2026 at 3:18 PM CET, Maxime Ripard wrote: >>> On Mon, Jan 19, 2026 at 02:13:48PM +0100, Danilo Krummrich wrote: >>>> On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: >>>>>> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: >>>>>> I think that if you still want an API where you just call enable/disable >>>>>> directly on it with no protection against unbalanced calls, then that >>>>>> should be the special API. Probably called RawClk and functions marked >>>>>> unsafe. Unbalanced calls seem really dangerous and use should not be >>>>>> encouraged. >>>> >>>> +1; and unless there is a use-case that requires otherwise, it should not even >>>> be possible to do this at all -- at least for driver code. >>> >>> I mean, it's great, it's safe, etc. but it's also suboptimal from a PM >>> perspective on many platforms. It's totally fine to provide nice, safe, >>> ergonomic wrappers for the drivers that don't care (or can't, really), >>> but treating a legitimate optimisation as something we should consider >>> impossible to do is just weird to me. >> >> I said that an unsafe API with potentially unbalanced calls is something we >> should clearly avoid for drivers. This is *not* equivalent to "treating a >> legitimate optimisation as something we should consider impossible". >> >> If we discover use-cases where the current API doesn't work well, we can >> invenstigate further. > > I'm not sure I'm following what you're saying, sorry. I've pointed out > such a use-case already. > >>>>> I think we should discourage RawClk if at all possible. But if the consensus >>>>> is that we *really* need this easily-abused thing, I can provide a follow-up. >>>> >>>> I think we should only do this if there are use-case with no alternative, so far >>>> there haven't been any AFAIK. >>> >>> I don't really care about which alternative we come up with, but look at >>> devm_regmap_init_mmio_clk for example. It is a valid use-case that >>> already exists today, and has had for more than a decade at this point. >> >> I don't see the issue with devm_regmap_init_mmio_clk()? It takes a reference >> count of the clock and prepares it when called and unprepares the clk in drops >> its reference in regmap_mmio_free_context() called from the devres callback. >> >> That something we can easily do with the current API, no? > > The current one, yes. Doing that in the API suggested here would involve > some boilerplate in all those drivers they don't have right now. > > Maxime Maxime, I know you’ve already pointed out a use-case, but I think the confusion stems from why you seem to think that the current solution cannot cater to the API you mentioned in a clean way. You seem to imply that there will be a lot of boilerplate involved, but we (or I) cannot see this. Perhaps it would help if you highlighted how exactly the type state solution would be verbose using some pseudocode. I guess that would make your point clearer for us. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-23 0:29 ` Daniel Almeida @ 2026-02-04 9:15 ` Maxime Ripard 2026-02-04 12:43 ` Daniel Almeida 0 siblings, 1 reply; 68+ messages in thread From: Maxime Ripard @ 2026-02-04 9:15 UTC (permalink / raw) To: Daniel Almeida Cc: Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 4346 bytes --] On Thu, Jan 22, 2026 at 09:29:30PM -0300, Daniel Almeida wrote: > > > > On 22 Jan 2026, at 10:44, Maxime Ripard <mripard@kernel.org> wrote: > > > > On Mon, Jan 19, 2026 at 03:37:17PM +0100, Danilo Krummrich wrote: > >> On Mon Jan 19, 2026 at 3:18 PM CET, Maxime Ripard wrote: > >>> On Mon, Jan 19, 2026 at 02:13:48PM +0100, Danilo Krummrich wrote: > >>>> On Mon Jan 19, 2026 at 1:54 PM CET, Daniel Almeida wrote: > >>>>>> On 19 Jan 2026, at 09:35, Alice Ryhl <aliceryhl@google.com> wrote: > >>>>>> I think that if you still want an API where you just call enable/disable > >>>>>> directly on it with no protection against unbalanced calls, then that > >>>>>> should be the special API. Probably called RawClk and functions marked > >>>>>> unsafe. Unbalanced calls seem really dangerous and use should not be > >>>>>> encouraged. > >>>> > >>>> +1; and unless there is a use-case that requires otherwise, it should not even > >>>> be possible to do this at all -- at least for driver code. > >>> > >>> I mean, it's great, it's safe, etc. but it's also suboptimal from a PM > >>> perspective on many platforms. It's totally fine to provide nice, safe, > >>> ergonomic wrappers for the drivers that don't care (or can't, really), > >>> but treating a legitimate optimisation as something we should consider > >>> impossible to do is just weird to me. > >> > >> I said that an unsafe API with potentially unbalanced calls is something we > >> should clearly avoid for drivers. This is *not* equivalent to "treating a > >> legitimate optimisation as something we should consider impossible". > >> > >> If we discover use-cases where the current API doesn't work well, we can > >> invenstigate further. > > > > I'm not sure I'm following what you're saying, sorry. I've pointed out > > such a use-case already. > > > >>>>> I think we should discourage RawClk if at all possible. But if the consensus > >>>>> is that we *really* need this easily-abused thing, I can provide a follow-up. > >>>> > >>>> I think we should only do this if there are use-case with no alternative, so far > >>>> there haven't been any AFAIK. > >>> > >>> I don't really care about which alternative we come up with, but look at > >>> devm_regmap_init_mmio_clk for example. It is a valid use-case that > >>> already exists today, and has had for more than a decade at this point. > >> > >> I don't see the issue with devm_regmap_init_mmio_clk()? It takes a reference > >> count of the clock and prepares it when called and unprepares the clk in drops > >> its reference in regmap_mmio_free_context() called from the devres callback. > >> > >> That something we can easily do with the current API, no? > > > > The current one, yes. Doing that in the API suggested here would involve > > some boilerplate in all those drivers they don't have right now. > > > > Maxime > > Maxime, I know you’ve already pointed out a use-case, but I think the > confusion stems from why you seem to think that the current solution cannot > cater to the API you mentioned in a clean way. You seem to imply that there > will be a lot of boilerplate involved, but we (or I) cannot see this. Perhaps > it would help if you highlighted how exactly the type state solution would be > verbose using some pseudocode. I guess that would make your point clearer for > us. I'm probably missing something then, but let's assume you have a driver that wants its clock prepared and enabled in an hypothetical enable() callback, and disabled / unprepared in a disable() callback. From a PM management perspective, this usecase makes total sense, is a valid usecase, is widely used in the kernel, and is currently supported by both the C and Rust clk APIs. The only solution to this you suggested so far (I think?) to implement this on top of the new clk API you propose is to have a driver specific enum that would store each of the possible state transition. That's the boilerplate I'm talking about. If every driver wanting to implement that pattern has to make such an enum, with all the relevant traits implementation that might come with it, we go from an API where everything works at no-cost from a code-size perspective to a situation where every driver has to develop and maintain that enum. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-04 9:15 ` Maxime Ripard @ 2026-02-04 12:43 ` Daniel Almeida 2026-02-04 14:34 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-02-04 12:43 UTC (permalink / raw) To: Maxime Ripard Cc: Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > > I'm probably missing something then, but let's assume you have a driver > that wants its clock prepared and enabled in an hypothetical enable() > callback, and disabled / unprepared in a disable() callback. > > From a PM management perspective, this usecase makes total sense, is a > valid usecase, is widely used in the kernel, and is currently supported > by both the C and Rust clk APIs. > > The only solution to this you suggested so far (I think?) to implement > this on top of the new clk API you propose is to have a driver specific > enum that would store each of the possible state transition. Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you only need two variants to implement the pattern you described. I do not consider this “boilerplate”, but rather a small cost to pay. I would understand if this was some elaborate pattern that had to be implemented by all drivers, but a two-variant enum is as straightforward as it gets. > > That's the boilerplate I'm talking about. If every driver wanting to > implement that pattern has to make such an enum, with all the relevant > traits implementation that might come with it, we go from an API where > everything works at no-cost from a code-size perspective to a situation > where every driver has to develop and maintain that enum. > > Maxime There are no "traits that come with it". It's just an enum, with two variants. > API where everything works at no-cost The previous API was far from “everything works”. It was fundamentally broken by design in multiple ways, i.e.: > a) It only keeps track of a count to clk_get(), which means that users have > to manually call disable() and unprepare(), or a variation of those, like > disable_unprepare(). > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > of how often these were called, i.e., it's currently legal to write the > following: > > clk.prepare(); > clk.prepare(); > clk.enable(); > clk.enable(); > > And nothing gets undone on drop(). IMHO, what we have here is an improvement that has been long overdue. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-04 12:43 ` Daniel Almeida @ 2026-02-04 14:34 ` Maxime Ripard 2026-02-09 9:50 ` Boris Brezillon 0 siblings, 1 reply; 68+ messages in thread From: Maxime Ripard @ 2026-02-04 14:34 UTC (permalink / raw) To: Daniel Almeida Cc: Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 3416 bytes --] On Wed, Feb 04, 2026 at 09:43:55AM -0300, Daniel Almeida wrote: > > I'm probably missing something then, but let's assume you have a driver > > that wants its clock prepared and enabled in an hypothetical enable() > > callback, and disabled / unprepared in a disable() callback. > > > > From a PM management perspective, this usecase makes total sense, is a > > valid usecase, is widely used in the kernel, and is currently supported > > by both the C and Rust clk APIs. > > > > The only solution to this you suggested so far (I think?) to implement > > this on top of the new clk API you propose is to have a driver specific > > enum that would store each of the possible state transition. > > Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you > only need two variants to implement the pattern you described. I do not > consider this “boilerplate”, but rather a small cost to pay. A maintenance cost to pay by every driver is kind of the textbook definition of boilerplate to me. > I would understand if this was some elaborate pattern that had to be > implemented by all drivers, but a two-variant enum is as > straightforward as it gets. And yet, that framework has dozens of helpers that do not remove anything from drivers but a couple of lines. So surely its users must find value in reducing that boilerplate as much as possible. And you do implement some of them, so you must find value in that too. > > That's the boilerplate I'm talking about. If every driver wanting to > > implement that pattern has to make such an enum, with all the relevant > > traits implementation that might come with it, we go from an API where > > everything works at no-cost from a code-size perspective to a situation > > where every driver has to develop and maintain that enum. > > There are no "traits that come with it". It's just an enum, with two > variants. > > > API where everything works at no-cost > > The previous API was far from “everything works”. It was fundamentally > broken by design in multiple ways, i.e.: Out of context and not what I meant, but ok. > > a) It only keeps track of a count to clk_get(), which means that users have > > to manually call disable() and unprepare(), or a variation of those, like > > disable_unprepare(). > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > of how often these were called, i.e., it's currently legal to write the > > following: > > > > clk.prepare(); > > clk.prepare(); > > clk.enable(); > > clk.enable(); > > > > And nothing gets undone on drop(). > > IMHO, what we have here is an improvement that has been long overdue. Nothing is absolute. It is indeed an improvement on the refcounting side of things and general safety of the API for the general case. I don't think I ever questionned that. However, for the use-cases we've been discussing (and dozens of drivers implementing it), it also comes with a regression in the amount of code to create and maintain. They used to be able to only deal with the Clk structure, and now they can't anymore. You might find that neglible, you might have a plan to address that in the future, etc. and that's fine, but if you can't acknowledge that it's indeed happening, there's no point in me raising the issue and continuing the discussion. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-04 14:34 ` Maxime Ripard @ 2026-02-09 9:50 ` Boris Brezillon 2026-02-11 16:37 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-09 9:50 UTC (permalink / raw) To: Maxime Ripard Cc: Daniel Almeida, Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hi Maxime, On Wed, 4 Feb 2026 15:34:29 +0100 Maxime Ripard <mripard@kernel.org> wrote: > On Wed, Feb 04, 2026 at 09:43:55AM -0300, Daniel Almeida wrote: > > > I'm probably missing something then, but let's assume you have a driver > > > that wants its clock prepared and enabled in an hypothetical enable() > > > callback, and disabled / unprepared in a disable() callback. > > > > > > From a PM management perspective, this usecase makes total sense, is a > > > valid usecase, is widely used in the kernel, and is currently supported > > > by both the C and Rust clk APIs. > > > > > > The only solution to this you suggested so far (I think?) to implement > > > this on top of the new clk API you propose is to have a driver specific > > > enum that would store each of the possible state transition. > > > > Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you > > only need two variants to implement the pattern you described. I do not > > consider this “boilerplate”, but rather a small cost to pay. > > A maintenance cost to pay by every driver is kind of the textbook > definition of boilerplate to me. > > > I would understand if this was some elaborate pattern that had to be > > implemented by all drivers, but a two-variant enum is as > > straightforward as it gets. > > And yet, that framework has dozens of helpers that do not remove > anything from drivers but a couple of lines. So surely its users must > find value in reducing that boilerplate as much as possible. And you do > implement some of them, so you must find value in that too. > > > > That's the boilerplate I'm talking about. If every driver wanting to > > > implement that pattern has to make such an enum, with all the relevant > > > traits implementation that might come with it, we go from an API where > > > everything works at no-cost from a code-size perspective to a situation > > > where every driver has to develop and maintain that enum. > > > > There are no "traits that come with it". It's just an enum, with two > > variants. > > > > > API where everything works at no-cost > > > > The previous API was far from “everything works”. It was fundamentally > > broken by design in multiple ways, i.e.: > > Out of context and not what I meant, but ok. > > > > a) It only keeps track of a count to clk_get(), which means that users have > > > to manually call disable() and unprepare(), or a variation of those, like > > > disable_unprepare(). > > > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > > of how often these were called, i.e., it's currently legal to write the > > > following: > > > > > > clk.prepare(); > > > clk.prepare(); > > > clk.enable(); > > > clk.enable(); > > > > > > And nothing gets undone on drop(). > > > > IMHO, what we have here is an improvement that has been long overdue. > > Nothing is absolute. It is indeed an improvement on the refcounting side > of things and general safety of the API for the general case. I don't > think I ever questionned that. > > However, for the use-cases we've been discussing (and dozens of drivers > implementing it), it also comes with a regression in the amount of code > to create and maintain. They used to be able to only deal with the Clk > structure, and now they can't anymore. > > You might find that neglible, you might have a plan to address that in > the future, etc. and that's fine, but if you can't acknowledge that it's > indeed happening, there's no point in me raising the issue and > continuing the discussion. Okay, let's see if I can sum-up the use case you'd like to support. You have some PM hooks, which I'm assuming are (or will be) written in rust. It will probably take the form of some Device{Rpm,Pm} trait to implement for your XxxDeviceData (Xxx being the bus under which is device is) object (since I've only recently joined the R4L effort, I wouldn't be surprised if what I'm describing already exists or is currently being proposed/reviewed somewhere, so please excuse my ignorance if that's the case :-)). The way I see it, rather than having one enum per clk/regulator/xxx where we keep track of each state individually, what we could have is a trait DevicePm { type ResumedState; type SuspendedState; fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>>; fn suspend(&self, state: SuspendedState) -> Result<SuspendedState, Error<ResumedState>>; }; enum DeviceState<T: DevicePm> { Resumed(T::ResumedState), Suspended(T::SuspendedState), }; and then in your driver: MySuspendedDeviceResources { xxx_clk: Clk<Unprepared>, }; MyResumedDeviceResources { xxx_clk: Clk<Enabled>, }; implem DevicePm for MyDevice { type ResumedState = MyResumedDeviceResources; type SuspendedState = MySuspendedDeviceResources; fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>> { // FIXME: error propagation not handled let enabled_clk = state.xxx_clk.clone().prepare()?.enable()?; Ok(ResumedState { xxx_clk: enabled_clk, }); } fn suspend(&self, state: ResumedState) -> Result<SuspendedState, Error<ResumedState>> { // FIXME: error propagation not handled let unprep_clk = state.xxx_clk.clone().disable().unprepare(); Ok(SuspendedState { xxx_clk: unprep_clk, }); } }; With this model, I don't think Daniel's refactor goes in the way of more generalization at the core level, it's just expressed differently than it would be if it was written in C. And I say that as someone who struggles with his C developer bias every time I'm looking at or trying to write rust code. As others have said in this thread (Danilo and Gary), and after having played myself with both approaches in Tyr, I do see this shift from manual prepare/enable to an RAII approach as an improvement, so I hope we can find a middle-ground where every one is happy. Regards, Boris ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-09 9:50 ` Boris Brezillon @ 2026-02-11 16:37 ` Maxime Ripard 2026-02-11 16:47 ` Danilo Krummrich 2026-02-12 8:16 ` Alice Ryhl 0 siblings, 2 replies; 68+ messages in thread From: Maxime Ripard @ 2026-02-11 16:37 UTC (permalink / raw) To: Boris Brezillon Cc: Daniel Almeida, Danilo Krummrich, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 7150 bytes --] On Mon, Feb 09, 2026 at 10:50:47AM +0100, Boris Brezillon wrote: > Hi Maxime, > > On Wed, 4 Feb 2026 15:34:29 +0100 > Maxime Ripard <mripard@kernel.org> wrote: > > > On Wed, Feb 04, 2026 at 09:43:55AM -0300, Daniel Almeida wrote: > > > > I'm probably missing something then, but let's assume you have a driver > > > > that wants its clock prepared and enabled in an hypothetical enable() > > > > callback, and disabled / unprepared in a disable() callback. > > > > > > > > From a PM management perspective, this usecase makes total sense, is a > > > > valid usecase, is widely used in the kernel, and is currently supported > > > > by both the C and Rust clk APIs. > > > > > > > > The only solution to this you suggested so far (I think?) to implement > > > > this on top of the new clk API you propose is to have a driver specific > > > > enum that would store each of the possible state transition. > > > > > > Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you > > > only need two variants to implement the pattern you described. I do not > > > consider this “boilerplate”, but rather a small cost to pay. > > > > A maintenance cost to pay by every driver is kind of the textbook > > definition of boilerplate to me. > > > > > I would understand if this was some elaborate pattern that had to be > > > implemented by all drivers, but a two-variant enum is as > > > straightforward as it gets. > > > > And yet, that framework has dozens of helpers that do not remove > > anything from drivers but a couple of lines. So surely its users must > > find value in reducing that boilerplate as much as possible. And you do > > implement some of them, so you must find value in that too. > > > > > > That's the boilerplate I'm talking about. If every driver wanting to > > > > implement that pattern has to make such an enum, with all the relevant > > > > traits implementation that might come with it, we go from an API where > > > > everything works at no-cost from a code-size perspective to a situation > > > > where every driver has to develop and maintain that enum. > > > > > > There are no "traits that come with it". It's just an enum, with two > > > variants. > > > > > > > API where everything works at no-cost > > > > > > The previous API was far from “everything works”. It was fundamentally > > > broken by design in multiple ways, i.e.: > > > > Out of context and not what I meant, but ok. > > > > > > a) It only keeps track of a count to clk_get(), which means that users have > > > > to manually call disable() and unprepare(), or a variation of those, like > > > > disable_unprepare(). > > > > > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > > > of how often these were called, i.e., it's currently legal to write the > > > > following: > > > > > > > > clk.prepare(); > > > > clk.prepare(); > > > > clk.enable(); > > > > clk.enable(); > > > > > > > > And nothing gets undone on drop(). > > > > > > IMHO, what we have here is an improvement that has been long overdue. > > > > Nothing is absolute. It is indeed an improvement on the refcounting side > > of things and general safety of the API for the general case. I don't > > think I ever questionned that. > > > > However, for the use-cases we've been discussing (and dozens of drivers > > implementing it), it also comes with a regression in the amount of code > > to create and maintain. They used to be able to only deal with the Clk > > structure, and now they can't anymore. > > > > You might find that neglible, you might have a plan to address that in > > the future, etc. and that's fine, but if you can't acknowledge that it's > > indeed happening, there's no point in me raising the issue and > > continuing the discussion. > > > Okay, let's see if I can sum-up the use case you'd like to support. You > have some PM hooks, which I'm assuming are (or will be) written in > rust. It will probably take the form of some Device{Rpm,Pm} trait to > implement for your XxxDeviceData (Xxx being the bus under which is > device is) object (since I've only recently joined the R4L effort, I > wouldn't be surprised if what I'm describing already exists or is > currently being proposed/reviewed somewhere, so please excuse my > ignorance if that's the case :-)). > > The way I see it, rather than having one enum per clk/regulator/xxx > where we keep track of each state individually, what we could have is a > > trait DevicePm { > type ResumedState; > type SuspendedState; > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>>; > fn suspend(&self, state: SuspendedState) -> Result<SuspendedState, Error<ResumedState>>; > }; > > enum DeviceState<T: DevicePm> { > Resumed(T::ResumedState), > Suspended(T::SuspendedState), > }; > > and then in your driver: > > MySuspendedDeviceResources { > xxx_clk: Clk<Unprepared>, > }; > > MyResumedDeviceResources { > xxx_clk: Clk<Enabled>, > }; > > implem DevicePm for MyDevice { > type ResumedState = MyResumedDeviceResources; > type SuspendedState = MySuspendedDeviceResources; > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>> { > // FIXME: error propagation not handled > let enabled_clk = state.xxx_clk.clone().prepare()?.enable()?; > > Ok(ResumedState { > xxx_clk: enabled_clk, > }); > } > > fn suspend(&self, state: ResumedState) -> Result<SuspendedState, Error<ResumedState>> { > // FIXME: error propagation not handled > let unprep_clk = state.xxx_clk.clone().disable().unprepare(); > > Ok(SuspendedState { > xxx_clk: unprep_clk, > }); > } > }; I'm not sure we need to associate this with the suspend/resume state either. > With this model, I don't think Daniel's refactor goes in the way of more > generalization at the core level, it's just expressed differently than > it would be if it was written in C. And I say that as someone who struggles > with his C developer bias every time I'm looking at or trying to write > rust code. > > As others have said in this thread (Danilo and Gary), and after having > played myself with both approaches in Tyr, I do see this shift from manual > prepare/enable to an RAII approach as an improvement, so I hope we can > find a middle-ground where every one is happy. I do think we can find a compromise though. Miguel suggested for example to make the current enable/prepare/disable/unprepare function unsafe, and that's totally reasonable to me. Then we can implement the "managed" clock version on that unsafe API, and we would end up with a "raw", unsafe, version kind of equivalent to the one we have today, and where callers would have to justify why their usage of the API is actually safe, or the new, managed, variant that is safe and can be easily used by most drivers. And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. How does that sound? Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-11 16:37 ` Maxime Ripard @ 2026-02-11 16:47 ` Danilo Krummrich 2026-02-12 7:59 ` Maxime Ripard 2026-02-12 8:16 ` Alice Ryhl 1 sibling, 1 reply; 68+ messages in thread From: Danilo Krummrich @ 2026-02-11 16:47 UTC (permalink / raw) To: Maxime Ripard Cc: Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Wed Feb 11, 2026 at 5:37 PM CET, Maxime Ripard wrote: > I do think we can find a compromise though. Miguel suggested for example > to make the current enable/prepare/disable/unprepare function unsafe, > and that's totally reasonable to me. > > Then we can implement the "managed" clock version on that unsafe API, What do you mean with "managed" clock? Do you mean devres managed? If so, I don't think there is any reason to switch to the unsafe API to be able to implement devres managed APIs (see also [1]). [1] https://lore.kernel.org/all/DFVW9MS5YLON.CVJDBYQKJ0P6@kernel.org/ > and we would end up with a "raw", unsafe, version kind of equivalent to > the one we have today, and where callers would have to justify why their > usage of the API is actually safe, or the new, managed, variant that is > safe and can be easily used by most drivers. > > And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. > > How does that sound? What about we just wait until we have a user that really requires an unsafe API for some reason? And if it never appears, even better. :) ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-11 16:47 ` Danilo Krummrich @ 2026-02-12 7:59 ` Maxime Ripard 2026-02-12 8:52 ` Alice Ryhl ` (2 more replies) 0 siblings, 3 replies; 68+ messages in thread From: Maxime Ripard @ 2026-02-12 7:59 UTC (permalink / raw) To: Danilo Krummrich Cc: Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 1747 bytes --] On Wed, Feb 11, 2026 at 05:47:09PM +0100, Danilo Krummrich wrote: > On Wed Feb 11, 2026 at 5:37 PM CET, Maxime Ripard wrote: > > I do think we can find a compromise though. Miguel suggested for example > > to make the current enable/prepare/disable/unprepare function unsafe, > > and that's totally reasonable to me. > > > > Then we can implement the "managed" clock version on that unsafe API, > > What do you mean with "managed" clock? Do you mean devres managed? If so, I > don't think there is any reason to switch to the unsafe API to be able to > implement devres managed APIs (see also [1]). > > [1] https://lore.kernel.org/all/DFVW9MS5YLON.CVJDBYQKJ0P6@kernel.org/ By that, I mean what Daniel has been proposing to achieve with this series. > > and we would end up with a "raw", unsafe, version kind of equivalent to > > the one we have today, and where callers would have to justify why their > > usage of the API is actually safe, or the new, managed, variant that is > > safe and can be easily used by most drivers. > > > > And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. > > > > How does that sound? > > What about we just wait until we have a user that really requires an unsafe API > for some reason? And if it never appears, even better. :) It works *today*. And the "oh but driver is using the API" is kind of ironic in the context of the Rust bindings which have globally been in that situation for years. You can't argue it both ways. Either way, I'm not sure what the point of that submission was if you will just dismiss diverging opinions, including attempts to compromise. Do whatever you want, but it's really hard to root for you some times. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 7:59 ` Maxime Ripard @ 2026-02-12 8:52 ` Alice Ryhl 2026-02-12 9:23 ` Danilo Krummrich 2026-02-12 11:45 ` Miguel Ojeda 2 siblings, 0 replies; 68+ messages in thread From: Alice Ryhl @ 2026-02-12 8:52 UTC (permalink / raw) To: Maxime Ripard Cc: Danilo Krummrich, Boris Brezillon, Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu, Feb 12, 2026 at 8:59 AM Maxime Ripard <mripard@kernel.org> wrote: > It works *today*. The code we have today is both safe and unsound. That is a bug, and it *must* be fixed. > And the "oh but driver is using the API" is kind of ironic in the > context of the Rust bindings which have globally been in that situation > for years. You can't argue it both ways. I don't really know what is meant by this. This API is for real Rust drivers that have already started landing upstream. Sometimes we merge APIs *before* their user lands, but not without a user. We generally are quite consistent that Rust APIs must have a real Rust driver that uses it. It's the usual no-dead-code rule in the kernel. > Either way, I'm not sure what the point of that submission was if you > will just dismiss diverging opinions, including attempts to compromise. It is true that we are unwilling to compromise on the requirement that APIs must be sound. It really does not matter how convenient the API is when it's this easy to get it wrong and decrement the refcount when you did not increment it. I'm sorry, but that's the way it is. In your latest email, the suggestion came up to make the API unsafe. That's more acceptable, but see my other email from half an hour ago. Alice ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 7:59 ` Maxime Ripard 2026-02-12 8:52 ` Alice Ryhl @ 2026-02-12 9:23 ` Danilo Krummrich 2026-02-12 14:01 ` Danilo Krummrich 2026-02-12 11:45 ` Miguel Ojeda 2 siblings, 1 reply; 68+ messages in thread From: Danilo Krummrich @ 2026-02-12 9:23 UTC (permalink / raw) To: Maxime Ripard Cc: Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu Feb 12, 2026 at 8:59 AM CET, Maxime Ripard wrote: > On Wed, Feb 11, 2026 at 05:47:09PM +0100, Danilo Krummrich wrote: >> On Wed Feb 11, 2026 at 5:37 PM CET, Maxime Ripard wrote: >> > I do think we can find a compromise though. Miguel suggested for example >> > to make the current enable/prepare/disable/unprepare function unsafe, >> > and that's totally reasonable to me. >> > >> > Then we can implement the "managed" clock version on that unsafe API, >> >> What do you mean with "managed" clock? Do you mean devres managed? If so, I >> don't think there is any reason to switch to the unsafe API to be able to >> implement devres managed APIs (see also [1]). >> >> [1] https://lore.kernel.org/all/DFVW9MS5YLON.CVJDBYQKJ0P6@kernel.org/ > > By that, I mean what Daniel has been proposing to achieve with this series. > >> > and we would end up with a "raw", unsafe, version kind of equivalent to >> > the one we have today, and where callers would have to justify why their >> > usage of the API is actually safe, or the new, managed, variant that is >> > safe and can be easily used by most drivers. >> > >> > And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. >> > >> > How does that sound? >> >> What about we just wait until we have a user that really requires an unsafe API >> for some reason? And if it never appears, even better. :) > > It works *today*. > > And the "oh but driver is using the API" is kind of ironic in the > context of the Rust bindings which have globally been in that situation > for years. You can't argue it both ways. I can't remember ever advocating for merging code that does not have at least a user in prospect. > Either way, I'm not sure what the point of that submission was if you > will just dismiss diverging opinions, including attempts to compromise. Sorry -- I'm a bit confused here, since I did not submit this code. I'm also not dismissing your opinion; I just have a different one. In particular, I don't think we need an unsafe API until we see a concrete example where the proposed safe API does not work (and no other safe API would work either). Framing a difference in opinion as "dismissing diverging opinions" doesn't feel fair to me. > Do whatever you want, but it's really hard to root for you some times. I'm starting to wonder if the mail is addressed to me in the first place. Thanks, Danilo ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 9:23 ` Danilo Krummrich @ 2026-02-12 14:01 ` Danilo Krummrich 2026-02-12 16:50 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Danilo Krummrich @ 2026-02-12 14:01 UTC (permalink / raw) To: Maxime Ripard Cc: Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu Feb 12, 2026 at 10:23 AM CET, Danilo Krummrich wrote: > In particular, I don't think we need an unsafe API until we see a concrete > example where the proposed safe API does not work (and no other safe API would > work either). One additional note for clarification, I'm not saying that I'm against an unsafe API if it is necessary. In fact, I have added an unsafe API for drivers myself with the dma::Device trait [1]. This was not an easy decision and I discussed this back and forth with a lot of people and, unfortunately, we had to come to the conclusion that any attempt to make this safe from the Rust side of things would cause unreasonable overhead and can't be considered an overall improvement. But as I said, I am convinced that need clear evidence that an unsafe API is actually needed and that there is no reasonable alternative. [1] https://rust.docs.kernel.org/kernel/dma/trait.Device.html ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 14:01 ` Danilo Krummrich @ 2026-02-12 16:50 ` Maxime Ripard 0 siblings, 0 replies; 68+ messages in thread From: Maxime Ripard @ 2026-02-12 16:50 UTC (permalink / raw) To: Danilo Krummrich Cc: Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 1077 bytes --] On Thu, Feb 12, 2026 at 03:01:31PM +0100, Danilo Krummrich wrote: > On Thu Feb 12, 2026 at 10:23 AM CET, Danilo Krummrich wrote: > > In particular, I don't think we need an unsafe API until we see a concrete > > example where the proposed safe API does not work (and no other safe API would > > work either). > > One additional note for clarification, I'm not saying that I'm against an unsafe > API if it is necessary. > > In fact, I have added an unsafe API for drivers myself with the dma::Device > trait [1]. This was not an easy decision and I discussed this back and forth > with a lot of people and, unfortunately, we had to come to the conclusion that > any attempt to make this safe from the Rust side of things would cause > unreasonable overhead and can't be considered an overall improvement. > > But as I said, I am convinced that need clear evidence that an unsafe API is > actually needed and that there is no reasonable alternative. > > [1] https://rust.docs.kernel.org/kernel/dma/trait.Device.html Ok, it works for me then. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 7:59 ` Maxime Ripard 2026-02-12 8:52 ` Alice Ryhl 2026-02-12 9:23 ` Danilo Krummrich @ 2026-02-12 11:45 ` Miguel Ojeda 2 siblings, 0 replies; 68+ messages in thread From: Miguel Ojeda @ 2026-02-12 11:45 UTC (permalink / raw) To: Maxime Ripard Cc: Danilo Krummrich, Boris Brezillon, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu, Feb 12, 2026 at 8:59 AM Maxime Ripard <mripard@kernel.org> wrote: > > And the "oh but driver is using the API" is kind of ironic in the > context of the Rust bindings which have globally been in that situation > for years. You can't argue it both ways. I don't think this is true, if I understand you correctly. To give some context, when Rust was close to land in mainline, we were explicitly asked to cut down what we had out-of-tree to a minimum of APIs, which was fair. So I did exactly that, to a point where you could essentially only declare a module for x86_64 and use `pr_info!` in it (pretty much). I even considered dropping the `pr_info!` too... :) Then we started upstreaming bits piece by piece, getting agreement and input from the relevant maintainers for each bit, and so on, which took years for several reasons, one of which was precisely waiting for actual users for APIs. [ Others were getting maintainers engaged and involved for some of the core APIs/subsystems, getting authors of the original code to submit it upstream via patches was yet another, reworking and cleaning the code with the new, better approaches we found meanwhile (like pin-init), and so on and so forth. ] Cheers, Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-11 16:37 ` Maxime Ripard 2026-02-11 16:47 ` Danilo Krummrich @ 2026-02-12 8:16 ` Alice Ryhl 2026-02-12 13:38 ` Maxime Ripard 1 sibling, 1 reply; 68+ messages in thread From: Alice Ryhl @ 2026-02-12 8:16 UTC (permalink / raw) To: Maxime Ripard Cc: Boris Brezillon, Daniel Almeida, Danilo Krummrich, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Wed, Feb 11, 2026 at 5:37 PM Maxime Ripard <mripard@kernel.org> wrote: > > On Mon, Feb 09, 2026 at 10:50:47AM +0100, Boris Brezillon wrote: > > Hi Maxime, > > > > On Wed, 4 Feb 2026 15:34:29 +0100 > > Maxime Ripard <mripard@kernel.org> wrote: > > > > > On Wed, Feb 04, 2026 at 09:43:55AM -0300, Daniel Almeida wrote: > > > > > I'm probably missing something then, but let's assume you have a driver > > > > > that wants its clock prepared and enabled in an hypothetical enable() > > > > > callback, and disabled / unprepared in a disable() callback. > > > > > > > > > > From a PM management perspective, this usecase makes total sense, is a > > > > > valid usecase, is widely used in the kernel, and is currently supported > > > > > by both the C and Rust clk APIs. > > > > > > > > > > The only solution to this you suggested so far (I think?) to implement > > > > > this on top of the new clk API you propose is to have a driver specific > > > > > enum that would store each of the possible state transition. > > > > > > > > Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you > > > > only need two variants to implement the pattern you described. I do not > > > > consider this “boilerplate”, but rather a small cost to pay. > > > > > > A maintenance cost to pay by every driver is kind of the textbook > > > definition of boilerplate to me. > > > > > > > I would understand if this was some elaborate pattern that had to be > > > > implemented by all drivers, but a two-variant enum is as > > > > straightforward as it gets. > > > > > > And yet, that framework has dozens of helpers that do not remove > > > anything from drivers but a couple of lines. So surely its users must > > > find value in reducing that boilerplate as much as possible. And you do > > > implement some of them, so you must find value in that too. > > > > > > > > That's the boilerplate I'm talking about. If every driver wanting to > > > > > implement that pattern has to make such an enum, with all the relevant > > > > > traits implementation that might come with it, we go from an API where > > > > > everything works at no-cost from a code-size perspective to a situation > > > > > where every driver has to develop and maintain that enum. > > > > > > > > There are no "traits that come with it". It's just an enum, with two > > > > variants. > > > > > > > > > API where everything works at no-cost > > > > > > > > The previous API was far from “everything works”. It was fundamentally > > > > broken by design in multiple ways, i.e.: > > > > > > Out of context and not what I meant, but ok. > > > > > > > > a) It only keeps track of a count to clk_get(), which means that users have > > > > > to manually call disable() and unprepare(), or a variation of those, like > > > > > disable_unprepare(). > > > > > > > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > > > > of how often these were called, i.e., it's currently legal to write the > > > > > following: > > > > > > > > > > clk.prepare(); > > > > > clk.prepare(); > > > > > clk.enable(); > > > > > clk.enable(); > > > > > > > > > > And nothing gets undone on drop(). > > > > > > > > IMHO, what we have here is an improvement that has been long overdue. > > > > > > Nothing is absolute. It is indeed an improvement on the refcounting side > > > of things and general safety of the API for the general case. I don't > > > think I ever questionned that. > > > > > > However, for the use-cases we've been discussing (and dozens of drivers > > > implementing it), it also comes with a regression in the amount of code > > > to create and maintain. They used to be able to only deal with the Clk > > > structure, and now they can't anymore. > > > > > > You might find that neglible, you might have a plan to address that in > > > the future, etc. and that's fine, but if you can't acknowledge that it's > > > indeed happening, there's no point in me raising the issue and > > > continuing the discussion. > > > > > > Okay, let's see if I can sum-up the use case you'd like to support. You > > have some PM hooks, which I'm assuming are (or will be) written in > > rust. It will probably take the form of some Device{Rpm,Pm} trait to > > implement for your XxxDeviceData (Xxx being the bus under which is > > device is) object (since I've only recently joined the R4L effort, I > > wouldn't be surprised if what I'm describing already exists or is > > currently being proposed/reviewed somewhere, so please excuse my > > ignorance if that's the case :-)). > > > > The way I see it, rather than having one enum per clk/regulator/xxx > > where we keep track of each state individually, what we could have is a > > > > trait DevicePm { > > type ResumedState; > > type SuspendedState; > > > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>>; > > fn suspend(&self, state: SuspendedState) -> Result<SuspendedState, Error<ResumedState>>; > > }; > > > > enum DeviceState<T: DevicePm> { > > Resumed(T::ResumedState), > > Suspended(T::SuspendedState), > > }; > > > > and then in your driver: > > > > MySuspendedDeviceResources { > > xxx_clk: Clk<Unprepared>, > > }; > > > > MyResumedDeviceResources { > > xxx_clk: Clk<Enabled>, > > }; > > > > implem DevicePm for MyDevice { > > type ResumedState = MyResumedDeviceResources; > > type SuspendedState = MySuspendedDeviceResources; > > > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>> { > > // FIXME: error propagation not handled > > let enabled_clk = state.xxx_clk.clone().prepare()?.enable()?; > > > > Ok(ResumedState { > > xxx_clk: enabled_clk, > > }); > > } > > > > fn suspend(&self, state: ResumedState) -> Result<SuspendedState, Error<ResumedState>> { > > // FIXME: error propagation not handled > > let unprep_clk = state.xxx_clk.clone().disable().unprepare(); > > > > Ok(SuspendedState { > > xxx_clk: unprep_clk, > > }); > > } > > }; > > I'm not sure we need to associate this with the suspend/resume state either. > > > With this model, I don't think Daniel's refactor goes in the way of more > > generalization at the core level, it's just expressed differently than > > it would be if it was written in C. And I say that as someone who struggles > > with his C developer bias every time I'm looking at or trying to write > > rust code. > > > > As others have said in this thread (Danilo and Gary), and after having > > played myself with both approaches in Tyr, I do see this shift from manual > > prepare/enable to an RAII approach as an improvement, so I hope we can > > find a middle-ground where every one is happy. > > I do think we can find a compromise though. Miguel suggested for example > to make the current enable/prepare/disable/unprepare function unsafe, > and that's totally reasonable to me. > > Then we can implement the "managed" clock version on that unsafe API, > and we would end up with a "raw", unsafe, version kind of equivalent to > the one we have today, and where callers would have to justify why their > usage of the API is actually safe, or the new, managed, variant that is > safe and can be easily used by most drivers. > > And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. > > How does that sound? If you make the raw API unsafe, then that's okay but any use of an unsafe API from a driver will receive very hard scrutiny. Yes, there are occasionally good reasons to use unsafe from drivers, but the entire point of this Rust exercise is to isolate unsafe code outside of drivers as much as possible. If Daniel's proposal is inconvenient for some drivers, it would be far better to have a third API that is both safe and convenient for those drivers. Alice ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 8:16 ` Alice Ryhl @ 2026-02-12 13:38 ` Maxime Ripard 2026-02-12 14:02 ` Alice Ryhl 0 siblings, 1 reply; 68+ messages in thread From: Maxime Ripard @ 2026-02-12 13:38 UTC (permalink / raw) To: Alice Ryhl Cc: Boris Brezillon, Daniel Almeida, Danilo Krummrich, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 9257 bytes --] Hi Alice, On Thu, Feb 12, 2026 at 09:16:51AM +0100, Alice Ryhl wrote: > On Wed, Feb 11, 2026 at 5:37 PM Maxime Ripard <mripard@kernel.org> wrote: > > On Mon, Feb 09, 2026 at 10:50:47AM +0100, Boris Brezillon wrote: > > > On Wed, 4 Feb 2026 15:34:29 +0100 > > > Maxime Ripard <mripard@kernel.org> wrote: > > > > > > > On Wed, Feb 04, 2026 at 09:43:55AM -0300, Daniel Almeida wrote: > > > > > > I'm probably missing something then, but let's assume you have a driver > > > > > > that wants its clock prepared and enabled in an hypothetical enable() > > > > > > callback, and disabled / unprepared in a disable() callback. > > > > > > > > > > > > From a PM management perspective, this usecase makes total sense, is a > > > > > > valid usecase, is widely used in the kernel, and is currently supported > > > > > > by both the C and Rust clk APIs. > > > > > > > > > > > > The only solution to this you suggested so far (I think?) to implement > > > > > > this on top of the new clk API you propose is to have a driver specific > > > > > > enum that would store each of the possible state transition. > > > > > > > > > > Yes, you need an enum _if_ you want to model transitions at runtime. IIUC you > > > > > only need two variants to implement the pattern you described. I do not > > > > > consider this “boilerplate”, but rather a small cost to pay. > > > > > > > > A maintenance cost to pay by every driver is kind of the textbook > > > > definition of boilerplate to me. > > > > > > > > > I would understand if this was some elaborate pattern that had to be > > > > > implemented by all drivers, but a two-variant enum is as > > > > > straightforward as it gets. > > > > > > > > And yet, that framework has dozens of helpers that do not remove > > > > anything from drivers but a couple of lines. So surely its users must > > > > find value in reducing that boilerplate as much as possible. And you do > > > > implement some of them, so you must find value in that too. > > > > > > > > > > That's the boilerplate I'm talking about. If every driver wanting to > > > > > > implement that pattern has to make such an enum, with all the relevant > > > > > > traits implementation that might come with it, we go from an API where > > > > > > everything works at no-cost from a code-size perspective to a situation > > > > > > where every driver has to develop and maintain that enum. > > > > > > > > > > There are no "traits that come with it". It's just an enum, with two > > > > > variants. > > > > > > > > > > > API where everything works at no-cost > > > > > > > > > > The previous API was far from “everything works”. It was fundamentally > > > > > broken by design in multiple ways, i.e.: > > > > > > > > Out of context and not what I meant, but ok. > > > > > > > > > > a) It only keeps track of a count to clk_get(), which means that users have > > > > > > to manually call disable() and unprepare(), or a variation of those, like > > > > > > disable_unprepare(). > > > > > > > > > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > > > > > of how often these were called, i.e., it's currently legal to write the > > > > > > following: > > > > > > > > > > > > clk.prepare(); > > > > > > clk.prepare(); > > > > > > clk.enable(); > > > > > > clk.enable(); > > > > > > > > > > > > And nothing gets undone on drop(). > > > > > > > > > > IMHO, what we have here is an improvement that has been long overdue. > > > > > > > > Nothing is absolute. It is indeed an improvement on the refcounting side > > > > of things and general safety of the API for the general case. I don't > > > > think I ever questionned that. > > > > > > > > However, for the use-cases we've been discussing (and dozens of drivers > > > > implementing it), it also comes with a regression in the amount of code > > > > to create and maintain. They used to be able to only deal with the Clk > > > > structure, and now they can't anymore. > > > > > > > > You might find that neglible, you might have a plan to address that in > > > > the future, etc. and that's fine, but if you can't acknowledge that it's > > > > indeed happening, there's no point in me raising the issue and > > > > continuing the discussion. > > > > > > > > > Okay, let's see if I can sum-up the use case you'd like to support. You > > > have some PM hooks, which I'm assuming are (or will be) written in > > > rust. It will probably take the form of some Device{Rpm,Pm} trait to > > > implement for your XxxDeviceData (Xxx being the bus under which is > > > device is) object (since I've only recently joined the R4L effort, I > > > wouldn't be surprised if what I'm describing already exists or is > > > currently being proposed/reviewed somewhere, so please excuse my > > > ignorance if that's the case :-)). > > > > > > The way I see it, rather than having one enum per clk/regulator/xxx > > > where we keep track of each state individually, what we could have is a > > > > > > trait DevicePm { > > > type ResumedState; > > > type SuspendedState; > > > > > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>>; > > > fn suspend(&self, state: SuspendedState) -> Result<SuspendedState, Error<ResumedState>>; > > > }; > > > > > > enum DeviceState<T: DevicePm> { > > > Resumed(T::ResumedState), > > > Suspended(T::SuspendedState), > > > }; > > > > > > and then in your driver: > > > > > > MySuspendedDeviceResources { > > > xxx_clk: Clk<Unprepared>, > > > }; > > > > > > MyResumedDeviceResources { > > > xxx_clk: Clk<Enabled>, > > > }; > > > > > > implem DevicePm for MyDevice { > > > type ResumedState = MyResumedDeviceResources; > > > type SuspendedState = MySuspendedDeviceResources; > > > > > > fn resume(&self, state: SuspendedState) -> Result<ResumedState, Error<SuspendedState>> { > > > // FIXME: error propagation not handled > > > let enabled_clk = state.xxx_clk.clone().prepare()?.enable()?; > > > > > > Ok(ResumedState { > > > xxx_clk: enabled_clk, > > > }); > > > } > > > > > > fn suspend(&self, state: ResumedState) -> Result<SuspendedState, Error<ResumedState>> { > > > // FIXME: error propagation not handled > > > let unprep_clk = state.xxx_clk.clone().disable().unprepare(); > > > > > > Ok(SuspendedState { > > > xxx_clk: unprep_clk, > > > }); > > > } > > > }; > > > > I'm not sure we need to associate this with the suspend/resume state either. > > > > > With this model, I don't think Daniel's refactor goes in the way of more > > > generalization at the core level, it's just expressed differently than > > > it would be if it was written in C. And I say that as someone who struggles > > > with his C developer bias every time I'm looking at or trying to write > > > rust code. > > > > > > As others have said in this thread (Danilo and Gary), and after having > > > played myself with both approaches in Tyr, I do see this shift from manual > > > prepare/enable to an RAII approach as an improvement, so I hope we can > > > find a middle-ground where every one is happy. > > > > I do think we can find a compromise though. Miguel suggested for example > > to make the current enable/prepare/disable/unprepare function unsafe, > > and that's totally reasonable to me. > > > > Then we can implement the "managed" clock version on that unsafe API, > > and we would end up with a "raw", unsafe, version kind of equivalent to > > the one we have today, and where callers would have to justify why their > > usage of the API is actually safe, or the new, managed, variant that is > > safe and can be easily used by most drivers. > > > > And we can call these RawClk vs Clk, or Clk vs ManagedClk, or whatever. > > > > How does that sound? > > If you make the raw API unsafe, then that's okay but any use of an > unsafe API from a driver will receive very hard scrutiny. And that's totally fair to me. If drivers want to have a more optimal but potentially unsafe use of the API, then it should be flagged, documented and scrutinized. > Yes, there are occasionally good reasons to use unsafe from drivers, > but the entire point of this Rust exercise is to isolate unsafe code > outside of drivers as much as possible. So, aside from the risk of fuckups, are you concerned about something here? Do you expect that scrutiny to be constly on the maintenance side of things? I guess what I'm asking is: except for the obvious "review" cost associated with it, why would that be a probleme if we have, say, a few dozen drivers using that unsafe API? > If Daniel's proposal is inconvenient for some drivers, it would be far > better to have a third API that is both safe and convenient for those > drivers. Yeah, I guess I was expecting that one to come after we have a few unsafe drivers using it and we do need to consolidate / make it safe. Anyway, thanks for your answer, Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 13:38 ` Maxime Ripard @ 2026-02-12 14:02 ` Alice Ryhl 2026-02-12 16:48 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Alice Ryhl @ 2026-02-12 14:02 UTC (permalink / raw) To: Maxime Ripard Cc: Boris Brezillon, Daniel Almeida, Danilo Krummrich, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu, Feb 12, 2026 at 2:38 PM Maxime Ripard <mripard@kernel.org> wrote: > > Hi Alice, > > On Thu, Feb 12, 2026 at 09:16:51AM +0100, Alice Ryhl wrote: > > If you make the raw API unsafe, then that's okay but any use of an > > unsafe API from a driver will receive very hard scrutiny. > > And that's totally fair to me. If drivers want to have a more optimal > but potentially unsafe use of the API, then it should be flagged, > documented and scrutinized. > > > Yes, there are occasionally good reasons to use unsafe from drivers, > > but the entire point of this Rust exercise is to isolate unsafe code > > outside of drivers as much as possible. > > So, aside from the risk of fuckups, are you concerned about something > here? Do you expect that scrutiny to be constly on the maintenance side > of things? Well I do think it's mostly the risk of mistakes, yes. > I guess what I'm asking is: except for the obvious "review" cost > associated with it, why would that be a probleme if we have, say, a few > dozen drivers using that unsafe API? The reason I wouldn't really suggest the unsafe API is that, if I'm the reviewer of said driver, then my review will be "just use a safe API instead". For example, if you really want explicit inc/dec calls for convenience, we can make a safe API with a counter that returns an error if you decrement more times than you have previously incremented. Or if you prefer something else, I can think of several other safe APIs. > > If Daniel's proposal is inconvenient for some drivers, it would be far > > better to have a third API that is both safe and convenient for those > > drivers. > > Yeah, I guess I was expecting that one to come after we have a few > unsafe drivers using it and we do need to consolidate / make it safe. For most things, we implemented and used the safe API from the very start. I'm not going to say there are never exceptions to that because there *are* exceptions. But I don't really see why clk should be one of them. Alice ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-12 14:02 ` Alice Ryhl @ 2026-02-12 16:48 ` Maxime Ripard 0 siblings, 0 replies; 68+ messages in thread From: Maxime Ripard @ 2026-02-12 16:48 UTC (permalink / raw) To: Alice Ryhl Cc: Boris Brezillon, Daniel Almeida, Danilo Krummrich, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 785 bytes --] On Thu, Feb 12, 2026 at 03:02:09PM +0100, Alice Ryhl wrote: > On Thu, Feb 12, 2026 at 2:38 PM Maxime Ripard <mripard@kernel.org> wrote: > > > If Daniel's proposal is inconvenient for some drivers, it would be far > > > better to have a third API that is both safe and convenient for those > > > drivers. > > > > Yeah, I guess I was expecting that one to come after we have a few > > unsafe drivers using it and we do need to consolidate / make it safe. > > For most things, we implemented and used the safe API from the very > start. I'm not going to say there are never exceptions to that because > there *are* exceptions. But I don't really see why clk should be one > of them. Ack. As long as we keep the door open for such an API, I'm ok with it then. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-22 13:44 ` Maxime Ripard 2026-01-23 0:29 ` Daniel Almeida @ 2026-01-23 10:25 ` Danilo Krummrich 1 sibling, 0 replies; 68+ messages in thread From: Danilo Krummrich @ 2026-01-23 10:25 UTC (permalink / raw) To: Maxime Ripard Cc: Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Thu Jan 22, 2026 at 2:44 PM CET, Maxime Ripard wrote: > On Mon, Jan 19, 2026 at 03:37:17PM +0100, Danilo Krummrich wrote: >> I don't see the issue with devm_regmap_init_mmio_clk()? It takes a reference >> count of the clock and prepares it when called and unprepares the clk in drops >> its reference in regmap_mmio_free_context() called from the devres callback. >> >> That something we can easily do with the current API, no? > > The current one, yes. Doing that in the API suggested here would involve > some boilerplate in all those drivers they don't have right now. No, I did mean the API suggested here. If you would implement something like devm_regmap_init_mmio_clk() in Rust with this API, you'd have some object like struct RegmapResource<T: Backend, R: Resource> { map: Regmap<T>, res: R, } and a concrete instance could have the following type RegmapResource<MmIo, Clk<Prepared>> So, eventually you could have: fn devm_regmap_init_mmio_clk(dev: &Device<Bound>, name: &CStr, ...) -> ... { let clk: Clk<Prepared> = Clk::get(dev, name)?; let regmap = RegmapResource::new(..., clk); Devres::new(dev, regmap) } Of course, we would never design the API in this way, as we have generic I/O backends and register abstractions, and we'd also not have devm_regmap_init_mmio_clk() as a constructor for a RegmapResource type, but you get the idea. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 12:35 ` Alice Ryhl 2026-01-19 12:54 ` Daniel Almeida @ 2026-01-19 12:57 ` Gary Guo 2026-01-19 14:27 ` Maxime Ripard 2026-02-03 10:39 ` Boris Brezillon 3 siblings, 0 replies; 68+ messages in thread From: Gary Guo @ 2026-01-19 12:57 UTC (permalink / raw) To: Alice Ryhl, Maxime Ripard Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 12:35 PM GMT, Alice Ryhl wrote: > On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: >> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >> > > For example, it's quite typical to have (at least) one clock for the bus >> > > interface that drives the register, and one that drives the main >> > > component logic. The former needs to be enabled only when you're >> > > accessing the registers (and can be abstracted with >> > > regmap_mmio_attach_clk for example), and the latter needs to be enabled >> > > only when the device actually starts operating. >> > > >> > > You have a similar thing for the prepare vs enable thing. The difference >> > > between the two is that enable can be called into atomic context but >> > > prepare can't. >> > > >> > > So for drivers that would care about this, you would create your device >> > > with an unprepared clock, and then at various times during the driver >> > > lifetime, you would mutate that state. > > The case where you're doing it only while accessing registers is > interesting, because that means the Enable bit may be owned by a local > variable. We may imagine an: > > let enabled = self.prepared_clk.enable_scoped(); > ... use registers > drop(enabled); > > Now ... this doesn't quite work with the current API - the current > Enabled stated owns both a prepare and enable count, but the above keeps > the prepare count in `self` and the enabled count in a local variable. > But it could be done with a fourth state, or by a closure method: > > self.prepared_clk.with_enabled(|| { > ... use registers > }); > > All of this would work with an immutable variable of type Clk<Prepared>. > >> > > AFAIU, encoding the state of the clock into the Clk type (and thus >> > > forcing the structure that holds it) prevents that mutation. If not, we >> > > should make it clearer (by expanding the doc maybe?) how such a pattern >> > > can be supported. >> > > >> > > Maxime >> > >> > IIUC, your main point seems to be about mutating the state at runtime? This is >> > possible with this code. You can just have an enum, for example: >> > >> > enum MyClocks { >> > Unprepared(Clk<Unprepared>), >> > Prepared(Clk<Prepared>), >> > Enabled(Clk<Enabled>), >> > } > > I believe you need an extra state if the state is not bound to the scope > of a function: > > enum MyClocks { > Unprepared(Clk<Unprepared>), > Prepared(Clk<Prepared>), > Enabled(Clk<Enabled>), > Transitioning, > } > > since mem::replace() needs a new value before you can take ownership of > the existing Clk value. We can provide `replace_with` in the kernel, it's fine as we don't have unwinding panics. Best, Gary ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 12:35 ` Alice Ryhl 2026-01-19 12:54 ` Daniel Almeida 2026-01-19 12:57 ` Gary Guo @ 2026-01-19 14:27 ` Maxime Ripard 2026-02-03 10:39 ` Boris Brezillon 3 siblings, 0 replies; 68+ messages in thread From: Maxime Ripard @ 2026-01-19 14:27 UTC (permalink / raw) To: Alice Ryhl Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 1468 bytes --] On Mon, Jan 19, 2026 at 12:35:21PM +0000, Alice Ryhl wrote: > > > In fact, I specifically wanted to ensure that this was possible when writing > > > these patches, as it’s needed by drivers. If you want to, I can cover that in > > > the examples, no worries. > > > > Yes, that would be great. I do wonder though if it wouldn't make sense > > to turn it the other way around. It creates a fair share of boilerplate > > for a number of drivers. Can't we keep Clk the way it is as a > > lower-level type, and crate a ManagedClk (or whatever name you prefer) > > that drivers can use, and would be returned by higher-level helpers, if > > they so choose? > > > > That way, we do have the typestate API for whoever wants to, without > > creating too much boilerplate for everybody else. > > I think that if you still want an API where you just call enable/disable > directly on it with no protection against unbalanced calls, then that > should be the special API. Probably called RawClk and functions marked > unsafe. Unbalanced calls seem really dangerous and use should not be > encouraged. Sure, that makes sense to me. > The current type-state based API is the least-boilerplate option for > drivers that exist today. I wasn't saying that we should add boilerplate to the typestate API either. I was saying that the non-typestated API was common enough that we probably didn't want boilerplate for it either if possible. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 12:35 ` Alice Ryhl ` (2 preceding siblings ...) 2026-01-19 14:27 ` Maxime Ripard @ 2026-02-03 10:39 ` Boris Brezillon 2026-02-03 11:26 ` Boris Brezillon 2026-02-03 13:33 ` Daniel Almeida 3 siblings, 2 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 10:39 UTC (permalink / raw) To: Alice Ryhl Cc: Maxime Ripard, Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon, 19 Jan 2026 12:35:21 +0000 Alice Ryhl <aliceryhl@google.com> wrote: > On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > > > > For example, it's quite typical to have (at least) one clock for the bus > > > > interface that drives the register, and one that drives the main > > > > component logic. The former needs to be enabled only when you're > > > > accessing the registers (and can be abstracted with > > > > regmap_mmio_attach_clk for example), and the latter needs to be enabled > > > > only when the device actually starts operating. > > > > > > > > You have a similar thing for the prepare vs enable thing. The difference > > > > between the two is that enable can be called into atomic context but > > > > prepare can't. > > > > > > > > So for drivers that would care about this, you would create your device > > > > with an unprepared clock, and then at various times during the driver > > > > lifetime, you would mutate that state. > > The case where you're doing it only while accessing registers is > interesting, because that means the Enable bit may be owned by a local > variable. We may imagine an: > > let enabled = self.prepared_clk.enable_scoped(); > ... use registers > drop(enabled); > > Now ... this doesn't quite work with the current API - the current > Enabled stated owns both a prepare and enable count, but the above keeps > the prepare count in `self` and the enabled count in a local variable. > But it could be done with a fourth state, or by a closure method: > > self.prepared_clk.with_enabled(|| { > ... use registers > }); > > All of this would work with an immutable variable of type Clk<Prepared>. Hm, maybe it'd make sense to implement Clone so we can have a temporary clk variable that has its own prepare/enable refs and releases them as it goes out of scope. This implies wrapping *mut bindings::clk in an Arc<> because bindings::clk is not ARef, but should be relatively easy to do. Posting the quick experiment I did with this approach, in case you're interested [1] [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 10:39 ` Boris Brezillon @ 2026-02-03 11:26 ` Boris Brezillon 2026-02-03 14:53 ` Boris Brezillon 2026-02-03 13:33 ` Daniel Almeida 1 sibling, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 11:26 UTC (permalink / raw) To: Alice Ryhl Cc: Maxime Ripard, Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 11:39:02 +0100 Boris Brezillon <boris.brezillon@collabora.com> wrote: > On Mon, 19 Jan 2026 12:35:21 +0000 > Alice Ryhl <aliceryhl@google.com> wrote: > > > On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > > > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > > > > > For example, it's quite typical to have (at least) one clock for the bus > > > > > interface that drives the register, and one that drives the main > > > > > component logic. The former needs to be enabled only when you're > > > > > accessing the registers (and can be abstracted with > > > > > regmap_mmio_attach_clk for example), and the latter needs to be enabled > > > > > only when the device actually starts operating. > > > > > > > > > > You have a similar thing for the prepare vs enable thing. The difference > > > > > between the two is that enable can be called into atomic context but > > > > > prepare can't. > > > > > > > > > > So for drivers that would care about this, you would create your device > > > > > with an unprepared clock, and then at various times during the driver > > > > > lifetime, you would mutate that state. > > > > The case where you're doing it only while accessing registers is > > interesting, because that means the Enable bit may be owned by a local > > variable. We may imagine an: > > > > let enabled = self.prepared_clk.enable_scoped(); > > ... use registers > > drop(enabled); > > > > Now ... this doesn't quite work with the current API - the current > > Enabled stated owns both a prepare and enable count, but the above keeps > > the prepare count in `self` and the enabled count in a local variable. > > But it could be done with a fourth state, or by a closure method: > > > > self.prepared_clk.with_enabled(|| { > > ... use registers > > }); > > > > All of this would work with an immutable variable of type Clk<Prepared>. > > Hm, maybe it'd make sense to implement Clone so we can have a temporary > clk variable that has its own prepare/enable refs and releases them > as it goes out of scope. This implies wrapping *mut bindings::clk in an > Arc<> because bindings::clk is not ARef, but should be relatively easy > to do. Posting the quick experiment I did with this approach, in case > you're interested [1] This time with a proper RawClk(*mut bindings::clk) wrapper, so we can clk_put() called in RawClk::drop() instead of in Clk::drop(). [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/6fa6cb72f14373b276c61d038bc2b16f49c78f74 ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 11:26 ` Boris Brezillon @ 2026-02-03 14:53 ` Boris Brezillon 0 siblings, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 14:53 UTC (permalink / raw) To: Alice Ryhl Cc: Maxime Ripard, Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 12:26:31 +0100 Boris Brezillon <boris.brezillon@collabora.com> wrote: > On Tue, 3 Feb 2026 11:39:02 +0100 > Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > On Mon, 19 Jan 2026 12:35:21 +0000 > > Alice Ryhl <aliceryhl@google.com> wrote: > > > > > On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > > > > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > > > > > > For example, it's quite typical to have (at least) one clock for the bus > > > > > > interface that drives the register, and one that drives the main > > > > > > component logic. The former needs to be enabled only when you're > > > > > > accessing the registers (and can be abstracted with > > > > > > regmap_mmio_attach_clk for example), and the latter needs to be enabled > > > > > > only when the device actually starts operating. > > > > > > > > > > > > You have a similar thing for the prepare vs enable thing. The difference > > > > > > between the two is that enable can be called into atomic context but > > > > > > prepare can't. > > > > > > > > > > > > So for drivers that would care about this, you would create your device > > > > > > with an unprepared clock, and then at various times during the driver > > > > > > lifetime, you would mutate that state. > > > > > > The case where you're doing it only while accessing registers is > > > interesting, because that means the Enable bit may be owned by a local > > > variable. We may imagine an: > > > > > > let enabled = self.prepared_clk.enable_scoped(); > > > ... use registers > > > drop(enabled); > > > > > > Now ... this doesn't quite work with the current API - the current > > > Enabled stated owns both a prepare and enable count, but the above keeps > > > the prepare count in `self` and the enabled count in a local variable. > > > But it could be done with a fourth state, or by a closure method: > > > > > > self.prepared_clk.with_enabled(|| { > > > ... use registers > > > }); > > > > > > All of this would work with an immutable variable of type Clk<Prepared>. > > > > Hm, maybe it'd make sense to implement Clone so we can have a temporary > > clk variable that has its own prepare/enable refs and releases them > > as it goes out of scope. This implies wrapping *mut bindings::clk in an > > Arc<> because bindings::clk is not ARef, but should be relatively easy > > to do. Posting the quick experiment I did with this approach, in case > > you're interested [1] > > This time with a proper RawClk(*mut bindings::clk) wrapper, so we can > clk_put() called in RawClk::drop() instead of in Clk::drop(). > > [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/6fa6cb72f14373b276c61d038bc2b16f49c78f74 And I forgot to drop the ManuallyDrop in that one, but I bet you get the idea. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 10:39 ` Boris Brezillon 2026-02-03 11:26 ` Boris Brezillon @ 2026-02-03 13:33 ` Daniel Almeida 2026-02-03 13:42 ` Gary Guo 2026-02-03 14:08 ` Boris Brezillon 1 sibling, 2 replies; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 13:33 UTC (permalink / raw) To: Boris Brezillon Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hi Boris, > On 3 Feb 2026, at 07:39, Boris Brezillon <boris.brezillon@collabora.com> wrote: > > On Mon, 19 Jan 2026 12:35:21 +0000 > Alice Ryhl <aliceryhl@google.com> wrote: > >> On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: >>> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >>>>> For example, it's quite typical to have (at least) one clock for the bus >>>>> interface that drives the register, and one that drives the main >>>>> component logic. The former needs to be enabled only when you're >>>>> accessing the registers (and can be abstracted with >>>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled >>>>> only when the device actually starts operating. >>>>> >>>>> You have a similar thing for the prepare vs enable thing. The difference >>>>> between the two is that enable can be called into atomic context but >>>>> prepare can't. >>>>> >>>>> So for drivers that would care about this, you would create your device >>>>> with an unprepared clock, and then at various times during the driver >>>>> lifetime, you would mutate that state. >> >> The case where you're doing it only while accessing registers is >> interesting, because that means the Enable bit may be owned by a local >> variable. We may imagine an: >> >> let enabled = self.prepared_clk.enable_scoped(); >> ... use registers >> drop(enabled); >> >> Now ... this doesn't quite work with the current API - the current >> Enabled stated owns both a prepare and enable count, but the above keeps >> the prepare count in `self` and the enabled count in a local variable. >> But it could be done with a fourth state, or by a closure method: >> >> self.prepared_clk.with_enabled(|| { >> ... use registers >> }); >> >> All of this would work with an immutable variable of type Clk<Prepared>. > > Hm, maybe it'd make sense to implement Clone so we can have a temporary > clk variable that has its own prepare/enable refs and releases them > as it goes out of scope. This implies wrapping *mut bindings::clk in an > Arc<> because bindings::clk is not ARef, but should be relatively easy > to do. Posting the quick experiment I did with this approach, in case > you're interested [1] > > [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 The problem with what you have suggested is that the previous state is not consumed if you can clone it, and consuming the previous state is a pretty key element in ensuring you cannot misuse it. For example, here: let enabled_clk = prepared_clk.clone().enable()?; // do stuff // enabled_clk goes out of scope and releases the enable // ref it had prepared_clk is still alive. Now, this may not be the end of the world in this particular case, but for API consistency, I'd say we should probably avoid this behavior. I see that Alice suggested a closure approach. IMHO, we should use that instead. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 13:33 ` Daniel Almeida @ 2026-02-03 13:42 ` Gary Guo 2026-02-03 13:55 ` Daniel Almeida 2026-02-03 14:08 ` Boris Brezillon 1 sibling, 1 reply; 68+ messages in thread From: Gary Guo @ 2026-02-03 13:42 UTC (permalink / raw) To: Daniel Almeida, Boris Brezillon Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue Feb 3, 2026 at 1:33 PM GMT, Daniel Almeida wrote: > Hi Boris, > >> On 3 Feb 2026, at 07:39, Boris Brezillon <boris.brezillon@collabora.com> wrote: >> >> On Mon, 19 Jan 2026 12:35:21 +0000 >> Alice Ryhl <aliceryhl@google.com> wrote: >> >>> On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: >>>> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >>>>>> For example, it's quite typical to have (at least) one clock for the bus >>>>>> interface that drives the register, and one that drives the main >>>>>> component logic. The former needs to be enabled only when you're >>>>>> accessing the registers (and can be abstracted with >>>>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled >>>>>> only when the device actually starts operating. >>>>>> >>>>>> You have a similar thing for the prepare vs enable thing. The difference >>>>>> between the two is that enable can be called into atomic context but >>>>>> prepare can't. >>>>>> >>>>>> So for drivers that would care about this, you would create your device >>>>>> with an unprepared clock, and then at various times during the driver >>>>>> lifetime, you would mutate that state. >>> >>> The case where you're doing it only while accessing registers is >>> interesting, because that means the Enable bit may be owned by a local >>> variable. We may imagine an: >>> >>> let enabled = self.prepared_clk.enable_scoped(); >>> ... use registers >>> drop(enabled); >>> >>> Now ... this doesn't quite work with the current API - the current >>> Enabled stated owns both a prepare and enable count, but the above keeps >>> the prepare count in `self` and the enabled count in a local variable. >>> But it could be done with a fourth state, or by a closure method: >>> >>> self.prepared_clk.with_enabled(|| { >>> ... use registers >>> }); >>> >>> All of this would work with an immutable variable of type Clk<Prepared>. >> >> Hm, maybe it'd make sense to implement Clone so we can have a temporary >> clk variable that has its own prepare/enable refs and releases them >> as it goes out of scope. This implies wrapping *mut bindings::clk in an >> Arc<> because bindings::clk is not ARef, but should be relatively easy >> to do. Posting the quick experiment I did with this approach, in case >> you're interested [1] >> >> [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 > > The problem with what you have suggested is that the previous state is not > consumed if you can clone it, and consuming the previous state is a pretty key > element in ensuring you cannot misuse it. For example, here: > > let enabled_clk = prepared_clk.clone().enable()?; > // do stuff > // enabled_clk goes out of scope and releases the enable > // ref it had > > prepared_clk is still alive. Now, this may not be the end of the world in this > particular case, but for API consistency, I'd say we should probably avoid this > behavior. Is this an issue though? You cannot mistakenly own `Clk<Enabled>` while the clk is not enabled, (and similarly for `Prepared`), and that should be sufficient. Having `Clk<Prepared>` makes no guarantee on if the clk is enabled or not anyway as you can have another user do `Clk<Unprepared>::get().enable()`. The only guarantee is that the state the clk have is going to be greater than or equal to the type state, so allowing cloning an intermediate state is no problem. Best, Gary > > I see that Alice suggested a closure approach. IMHO, we should use that > instead. > > — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 13:42 ` Gary Guo @ 2026-02-03 13:55 ` Daniel Almeida 2026-02-03 14:33 ` Boris Brezillon 0 siblings, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 13:55 UTC (permalink / raw) To: Gary Guo Cc: Boris Brezillon, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 3 Feb 2026, at 10:42, Gary Guo <gary@garyguo.net> wrote: > > On Tue Feb 3, 2026 at 1:33 PM GMT, Daniel Almeida wrote: >> Hi Boris, >> >>> On 3 Feb 2026, at 07:39, Boris Brezillon <boris.brezillon@collabora.com> wrote: >>> >>> On Mon, 19 Jan 2026 12:35:21 +0000 >>> Alice Ryhl <aliceryhl@google.com> wrote: >>> >>>> On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: >>>>> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >>>>>>> For example, it's quite typical to have (at least) one clock for the bus >>>>>>> interface that drives the register, and one that drives the main >>>>>>> component logic. The former needs to be enabled only when you're >>>>>>> accessing the registers (and can be abstracted with >>>>>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled >>>>>>> only when the device actually starts operating. >>>>>>> >>>>>>> You have a similar thing for the prepare vs enable thing. The difference >>>>>>> between the two is that enable can be called into atomic context but >>>>>>> prepare can't. >>>>>>> >>>>>>> So for drivers that would care about this, you would create your device >>>>>>> with an unprepared clock, and then at various times during the driver >>>>>>> lifetime, you would mutate that state. >>>> >>>> The case where you're doing it only while accessing registers is >>>> interesting, because that means the Enable bit may be owned by a local >>>> variable. We may imagine an: >>>> >>>> let enabled = self.prepared_clk.enable_scoped(); >>>> ... use registers >>>> drop(enabled); >>>> >>>> Now ... this doesn't quite work with the current API - the current >>>> Enabled stated owns both a prepare and enable count, but the above keeps >>>> the prepare count in `self` and the enabled count in a local variable. >>>> But it could be done with a fourth state, or by a closure method: >>>> >>>> self.prepared_clk.with_enabled(|| { >>>> ... use registers >>>> }); >>>> >>>> All of this would work with an immutable variable of type Clk<Prepared>. >>> >>> Hm, maybe it'd make sense to implement Clone so we can have a temporary >>> clk variable that has its own prepare/enable refs and releases them >>> as it goes out of scope. This implies wrapping *mut bindings::clk in an >>> Arc<> because bindings::clk is not ARef, but should be relatively easy >>> to do. Posting the quick experiment I did with this approach, in case >>> you're interested [1] >>> >>> [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 >> >> The problem with what you have suggested is that the previous state is not >> consumed if you can clone it, and consuming the previous state is a pretty key >> element in ensuring you cannot misuse it. For example, here: >> >> let enabled_clk = prepared_clk.clone().enable()?; >> // do stuff >> // enabled_clk goes out of scope and releases the enable >> // ref it had >> >> prepared_clk is still alive. Now, this may not be the end of the world in this >> particular case, but for API consistency, I'd say we should probably avoid this >> behavior. > > Is this an issue though? You cannot mistakenly own `Clk<Enabled>` while the clk > is not enabled, (and similarly for `Prepared`), and that should be sufficient. It is not an issue. However, I just find it a bit confusing. With a typestate, one usually expects state transitions where a new state fully consumes the previous one, and that assumption is “broken” in a way when you add clone(). > > Having `Clk<Prepared>` makes no guarantee on if the clk is enabled or not anyway > as you can have another user do `Clk<Unprepared>::get().enable()`. Although you’re right here, I find this less confusing than clone(). You have to explicitly craft a new Clk<Enabled>, where a clone() is a shorter way to basically get around the “state transition” idea on an _existing_ Clk reference. This is a bit pedantic on my side though, so I have no problem in adding clone() if it's the consensus of the majority. > > The only guarantee is that the state the clk have is going to be greater than or > equal to the type state, so allowing cloning an intermediate state is no > problem. > > Best, > Gary > >> >> I see that Alice suggested a closure approach. IMHO, we should use that >> instead. >> >> — Daniel Is there any pushback on the closure approach? If so, mind sharing why? — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 13:55 ` Daniel Almeida @ 2026-02-03 14:33 ` Boris Brezillon 0 siblings, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 14:33 UTC (permalink / raw) To: Daniel Almeida Cc: Gary Guo, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 10:55:05 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > > On 3 Feb 2026, at 10:42, Gary Guo <gary@garyguo.net> wrote: > > > > On Tue Feb 3, 2026 at 1:33 PM GMT, Daniel Almeida wrote: > >> Hi Boris, > >> > >>> On 3 Feb 2026, at 07:39, Boris Brezillon <boris.brezillon@collabora.com> wrote: > >>> > >>> On Mon, 19 Jan 2026 12:35:21 +0000 > >>> Alice Ryhl <aliceryhl@google.com> wrote: > >>> > >>>> On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > >>>>> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > >>>>>>> For example, it's quite typical to have (at least) one clock for the bus > >>>>>>> interface that drives the register, and one that drives the main > >>>>>>> component logic. The former needs to be enabled only when you're > >>>>>>> accessing the registers (and can be abstracted with > >>>>>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled > >>>>>>> only when the device actually starts operating. > >>>>>>> > >>>>>>> You have a similar thing for the prepare vs enable thing. The difference > >>>>>>> between the two is that enable can be called into atomic context but > >>>>>>> prepare can't. > >>>>>>> > >>>>>>> So for drivers that would care about this, you would create your device > >>>>>>> with an unprepared clock, and then at various times during the driver > >>>>>>> lifetime, you would mutate that state. > >>>> > >>>> The case where you're doing it only while accessing registers is > >>>> interesting, because that means the Enable bit may be owned by a local > >>>> variable. We may imagine an: > >>>> > >>>> let enabled = self.prepared_clk.enable_scoped(); > >>>> ... use registers > >>>> drop(enabled); > >>>> > >>>> Now ... this doesn't quite work with the current API - the current > >>>> Enabled stated owns both a prepare and enable count, but the above keeps > >>>> the prepare count in `self` and the enabled count in a local variable. > >>>> But it could be done with a fourth state, or by a closure method: > >>>> > >>>> self.prepared_clk.with_enabled(|| { > >>>> ... use registers > >>>> }); > >>>> > >>>> All of this would work with an immutable variable of type Clk<Prepared>. > >>> > >>> Hm, maybe it'd make sense to implement Clone so we can have a temporary > >>> clk variable that has its own prepare/enable refs and releases them > >>> as it goes out of scope. This implies wrapping *mut bindings::clk in an > >>> Arc<> because bindings::clk is not ARef, but should be relatively easy > >>> to do. Posting the quick experiment I did with this approach, in case > >>> you're interested [1] > >>> > >>> [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 > >> > >> The problem with what you have suggested is that the previous state is not > >> consumed if you can clone it, and consuming the previous state is a pretty key > >> element in ensuring you cannot misuse it. For example, here: > >> > >> let enabled_clk = prepared_clk.clone().enable()?; > >> // do stuff > >> // enabled_clk goes out of scope and releases the enable > >> // ref it had > >> > >> prepared_clk is still alive. Now, this may not be the end of the world in this > >> particular case, but for API consistency, I'd say we should probably avoid this > >> behavior. > > > > Is this an issue though? You cannot mistakenly own `Clk<Enabled>` while the clk > > is not enabled, (and similarly for `Prepared`), and that should be sufficient. > > It is not an issue. However, I just find it a bit confusing. With a typestate, one > usually expects state transitions where a new state fully consumes the previous > one, and that assumption is “broken” in a way when you add clone(). It's just the way clks work in practice: you having a Clk<Unprepared> doesn't mean the underlying clk_hw (the C object) is in an unprepared state, because some other users might point to the same clk_hw and have it enabled already. What Clk<State> means here is that you have a local view of a clk that's in at least this State. In order to guarantee that the clk is at least OtherState, you'll have to transition your view to this OtherState. Clone here just means you're cloning a view of this clone in its original view state. Then you're free to do whatever you want on this new view. So is the original owner of the object you clone from. > > > > > Having `Clk<Prepared>` makes no guarantee on if the clk is enabled or not anyway > > as you can have another user do `Clk<Unprepared>::get().enable()`. > > Although you’re right here, I find this less confusing than clone(). You > have to explicitly craft a new Clk<Enabled>, where a clone() is a shorter way > to basically get around the “state transition” idea on an _existing_ Clk > reference. The idea behind the clone() is that you can transition from one state to an higher state (prepared -> enabled for instance) for a shorter period of time than the cloned clk lifetime. Something like that, for instance: let MyDevice { prepared_clk: Clk::get(...)?.prepare()?, } implem MyDevice { fn do_stuff(&self) { let enabled_clk = self.prepared_clk.clone(); // do stuff that need to be guaranteed that clk // is enabled self.do_other_stuff(enabled_clk); // the enabled_clk object is dropped, but the // clk remains prepared because // self.prepared_clk is still there } } ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 13:33 ` Daniel Almeida 2026-02-03 13:42 ` Gary Guo @ 2026-02-03 14:08 ` Boris Brezillon 2026-02-03 16:28 ` Daniel Almeida 1 sibling, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 14:08 UTC (permalink / raw) To: Daniel Almeida Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 10:33:34 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > Hi Boris, > > > On 3 Feb 2026, at 07:39, Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > > On Mon, 19 Jan 2026 12:35:21 +0000 > > Alice Ryhl <aliceryhl@google.com> wrote: > > > >> On Mon, Jan 19, 2026 at 11:45:57AM +0100, Maxime Ripard wrote: > >>> On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: > >>>>> For example, it's quite typical to have (at least) one clock for the bus > >>>>> interface that drives the register, and one that drives the main > >>>>> component logic. The former needs to be enabled only when you're > >>>>> accessing the registers (and can be abstracted with > >>>>> regmap_mmio_attach_clk for example), and the latter needs to be enabled > >>>>> only when the device actually starts operating. > >>>>> > >>>>> You have a similar thing for the prepare vs enable thing. The difference > >>>>> between the two is that enable can be called into atomic context but > >>>>> prepare can't. > >>>>> > >>>>> So for drivers that would care about this, you would create your device > >>>>> with an unprepared clock, and then at various times during the driver > >>>>> lifetime, you would mutate that state. > >> > >> The case where you're doing it only while accessing registers is > >> interesting, because that means the Enable bit may be owned by a local > >> variable. We may imagine an: > >> > >> let enabled = self.prepared_clk.enable_scoped(); > >> ... use registers > >> drop(enabled); > >> > >> Now ... this doesn't quite work with the current API - the current > >> Enabled stated owns both a prepare and enable count, but the above keeps > >> the prepare count in `self` and the enabled count in a local variable. > >> But it could be done with a fourth state, or by a closure method: > >> > >> self.prepared_clk.with_enabled(|| { > >> ... use registers > >> }); > >> > >> All of this would work with an immutable variable of type Clk<Prepared>. > > > > Hm, maybe it'd make sense to implement Clone so we can have a temporary > > clk variable that has its own prepare/enable refs and releases them > > as it goes out of scope. This implies wrapping *mut bindings::clk in an > > Arc<> because bindings::clk is not ARef, but should be relatively easy > > to do. Posting the quick experiment I did with this approach, in case > > you're interested [1] > > > > [1]https://gitlab.freedesktop.org/bbrezillon/linux/-/commit/d5d04da4f4f6192b6e6760d5f861c69596c7d837 > > The problem with what you have suggested is that the previous state is not > consumed if you can clone it, and consuming the previous state is a pretty key > element in ensuring you cannot misuse it. For example, here: > > let enabled_clk = prepared_clk.clone().enable()?; > // do stuff > // enabled_clk goes out of scope and releases the enable > // ref it had > > prepared_clk is still alive. That was intentional in this example. Think about a prepared_clk that's stored in some driver-internal object, because you want to keep the clk prepared at all times between the probe() and unbind(). Then you have some sections where you want to briefly enable the clk to access registers, and immediately disable it when you're done. The clone() here guarantees that the initial prepared_clk stays valid. If you were to disable, unprepare and put the clk when enabled_clk goes out of scope, you'd go let enabled_clk = prepared_clk.enable()?; and that would still work, it's just not the same use-case. > Now, this may not be the end of the world in this > particular case, but for API consistency, I'd say we should probably avoid this > behavior. > > I see that Alice suggested a closure approach. IMHO, we should use that > instead. The closure, while being useful for the above local clk-enablement example, doesn't allow for passing some Clk<Enabled> guard around, like you would do with a lock Guard, and I believe that's a useful thing to have. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 14:08 ` Boris Brezillon @ 2026-02-03 16:28 ` Daniel Almeida 2026-02-03 16:55 ` Boris Brezillon 2026-02-03 16:59 ` Gary Guo 0 siblings, 2 replies; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 16:28 UTC (permalink / raw) To: Boris Brezillon Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux <snip> >> >> The problem with what you have suggested is that the previous state is not >> consumed if you can clone it, and consuming the previous state is a pretty key >> element in ensuring you cannot misuse it. For example, here: >> >> let enabled_clk = prepared_clk.clone().enable()?; >> // do stuff >> // enabled_clk goes out of scope and releases the enable >> // ref it had >> >> prepared_clk is still alive. > > That was intentional in this example. Think about a prepared_clk that's > stored in some driver-internal object, because you want to keep the clk > prepared at all times between the probe() and unbind(). Then you have > some sections where you want to briefly enable the clk to access > registers, and immediately disable it when you're done. The clone() > here guarantees that the initial prepared_clk stays valid. > > If you were to disable, unprepare and put the clk when enabled_clk goes > out of scope, you'd go > > let enabled_clk = prepared_clk.enable()?; > > and that would still work, it's just not the same use-case. > Ok, let’s have clone() then. >> Now, this may not be the end of the world in this >> particular case, but for API consistency, I'd say we should probably avoid this >> behavior. >> >> I see that Alice suggested a closure approach. IMHO, we should use that >> instead. > > The closure, while being useful for the above local clk-enablement > example, doesn't allow for passing some Clk<Enabled> guard around, like > you would do with a lock Guard, and I believe that's a useful thing to > have. Wdym? You’d still get a &Clk<Enabled> that you can pass around, i.e.: self.prepared_clk.with_enabled(|clk: &Clk<Enabled> | { ... use registers, pass &Clk<Enabled> as needed }); This is now not about clone() vs not clone(), but more about limiting the scope of the Enabled state, which would cater to the use-case you mentioned IIUC. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 16:28 ` Daniel Almeida @ 2026-02-03 16:55 ` Boris Brezillon 2026-02-03 16:59 ` Gary Guo 1 sibling, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 16:55 UTC (permalink / raw) To: Daniel Almeida Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 13:28:15 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > >> Now, this may not be the end of the world in this > >> particular case, but for API consistency, I'd say we should probably avoid this > >> behavior. > >> > >> I see that Alice suggested a closure approach. IMHO, we should use that > >> instead. > > > > The closure, while being useful for the above local clk-enablement > > example, doesn't allow for passing some Clk<Enabled> guard around, like > > you would do with a lock Guard, and I believe that's a useful thing to > > have. > > > Wdym? You’d still get a &Clk<Enabled> that you can pass around, i.e.: > > self.prepared_clk.with_enabled(|clk: &Clk<Enabled> | { > ... use registers, pass &Clk<Enabled> as needed > }); > > This is now not about clone() vs not clone(), but more about limiting the scope of the > Enabled state, which would cater to the use-case you mentioned IIUC. Fair enough. I guess it's more a matter of taste for that particular case, and I'm not fundamentally opposed to adding this closure approach. What the clone approach allows that's not doable with the closure AFAICT, is something like: let prep_clk = Clk::get(...)?.prepare()?; let comp_a = MyComponentA { prepared_clk: prep_clk.clone(), } let comp_b = MyComponentB { enabled_clk: prep_clk.enable()?, } and have the guarantee that, as long as comp_a is alive the underlying clk is at-least-Prepared, and as long as comp_b is alive the underlying clk is Enabled. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 16:28 ` Daniel Almeida 2026-02-03 16:55 ` Boris Brezillon @ 2026-02-03 16:59 ` Gary Guo 2026-02-03 19:26 ` Daniel Almeida 1 sibling, 1 reply; 68+ messages in thread From: Gary Guo @ 2026-02-03 16:59 UTC (permalink / raw) To: Daniel Almeida, Boris Brezillon Cc: Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue Feb 3, 2026 at 4:28 PM GMT, Daniel Almeida wrote: > <snip> > >>> >>> The problem with what you have suggested is that the previous state is not >>> consumed if you can clone it, and consuming the previous state is a pretty key >>> element in ensuring you cannot misuse it. For example, here: >>> >>> let enabled_clk = prepared_clk.clone().enable()?; >>> // do stuff >>> // enabled_clk goes out of scope and releases the enable >>> // ref it had >>> >>> prepared_clk is still alive. >> >> That was intentional in this example. Think about a prepared_clk that's >> stored in some driver-internal object, because you want to keep the clk >> prepared at all times between the probe() and unbind(). Then you have >> some sections where you want to briefly enable the clk to access >> registers, and immediately disable it when you're done. The clone() >> here guarantees that the initial prepared_clk stays valid. >> >> If you were to disable, unprepare and put the clk when enabled_clk goes >> out of scope, you'd go > >> >> let enabled_clk = prepared_clk.enable()?; >> >> and that would still work, it's just not the same use-case. >> > > Ok, let’s have clone() then. > > >>> Now, this may not be the end of the world in this >>> particular case, but for API consistency, I'd say we should probably avoid this >>> behavior. >>> >>> I see that Alice suggested a closure approach. IMHO, we should use that >>> instead. >> >> The closure, while being useful for the above local clk-enablement >> example, doesn't allow for passing some Clk<Enabled> guard around, like >> you would do with a lock Guard, and I believe that's a useful thing to >> have. > > > Wdym? You’d still get a &Clk<Enabled> that you can pass around, i.e.: > > self.prepared_clk.with_enabled(|clk: &Clk<Enabled> | { > ... use registers, pass &Clk<Enabled> as needed > }); > > This is now not about clone() vs not clone(), but more about limiting the scope of the > Enabled state, which would cater to the use-case you mentioned IIUC. I think it's fine to have all of these: * `Clone` impl * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` * `with_enabled` that gives `&Clk<Enabled>` This way, if you only want to enable in short time, you can do `with_enabled`. If the closure callback wants to keep clock enabled for longer, it can just do `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. If the user just have a reference and want to enable the callback they can do `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? Best, Gary > > — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 16:59 ` Gary Guo @ 2026-02-03 19:26 ` Daniel Almeida 2026-02-03 19:43 ` Boris Brezillon 2026-02-03 20:36 ` Gary Guo 0 siblings, 2 replies; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 19:26 UTC (permalink / raw) To: Gary Guo Cc: Boris Brezillon, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > > I think it's fine to have all of these: > * `Clone` impl > * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` > * `with_enabled` that gives `&Clk<Enabled>` > > This way, if you only want to enable in short time, you can do `with_enabled`. > If the closure callback wants to keep clock enabled for longer, it can just do > `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. > > If the user just have a reference and want to enable the callback they can do > `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? > > Best, > Gary I’m ok with what you proposed above. The only problem is that implementing clone() is done through an Arc<*mut bindings::clk> in Boris’ current design, so this requires an extra allocation. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 19:26 ` Daniel Almeida @ 2026-02-03 19:43 ` Boris Brezillon 2026-02-03 20:36 ` Gary Guo 1 sibling, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 19:43 UTC (permalink / raw) To: Daniel Almeida Cc: Gary Guo, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 16:26:22 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > > > > I think it's fine to have all of these: > > * `Clone` impl > > * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` > > * `with_enabled` that gives `&Clk<Enabled>` > > > > This way, if you only want to enable in short time, you can do `with_enabled`. > > If the closure callback wants to keep clock enabled for longer, it can just do > > `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. > > > > If the user just have a reference and want to enable the callback they can do > > `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? > > > > Best, > > Gary > > > I’m ok with what you proposed above. The only problem is that implementing > clone() is done through an Arc<*mut bindings::clk> in Boris’ current > design, It's actually Arc<RawClk> with struct RawClk(*mut bindings::clk); impl Drop for RawClk { fn drop(&mut self) { // SAFETY: By the type invariants, self.as_raw() is a valid argument for // [`clk_put`]. unsafe { bindings::clk_put(self.0) }; } } This is because struct clk is not refcounted, so cloning implies wrapping this object in an Arc, and only calling clk_put() when the Arc refcnt reaches zero. > so this requires an extra allocation. That's true. But the memory overhead should be pretty negligible, and I don't think the extra indirection makes any noticeable difference for an actual clk implementation (one that's not a NOP), since we have indirections all over the place already (clk -> clk_hw, clk_ops, ...). So I think I'd value ease of use over this small perfs/mem-usage hit. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 19:26 ` Daniel Almeida 2026-02-03 19:43 ` Boris Brezillon @ 2026-02-03 20:36 ` Gary Guo 2026-02-04 8:11 ` Boris Brezillon 1 sibling, 1 reply; 68+ messages in thread From: Gary Guo @ 2026-02-03 20:36 UTC (permalink / raw) To: Daniel Almeida, Gary Guo Cc: Boris Brezillon, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue Feb 3, 2026 at 7:26 PM GMT, Daniel Almeida wrote: > >> >> I think it's fine to have all of these: >> * `Clone` impl >> * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` >> * `with_enabled` that gives `&Clk<Enabled>` >> >> This way, if you only want to enable in short time, you can do `with_enabled`. >> If the closure callback wants to keep clock enabled for longer, it can just do >> `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. >> >> If the user just have a reference and want to enable the callback they can do >> `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? >> >> Best, >> Gary > > > I’m ok with what you proposed above. The only problem is that implementing > clone() is done through an Arc<*mut bindings::clk> in Boris’ current > design, so this requires an extra allocation. Hmm, that's a very good point. `struct clk` is already a reference into clk_core, so having to put another level of indirection over is not ideal. However, if we're going to keep C code unchanged and do a zero-cost abstraction on the Rust side, then we won't be able to have have multiple prepare/enable to the same `struct clk` with the current design. It feels like we can to do a trade-off and choose from: * Not be able to have multiple prepare/enable calls on the same `clk` (this can limit users that need dynamically enable/disable clocks, with the very limited exception that closure-callback is fine). * Do an extra allocation * Put lifetime on types that represent a prepared/enabled `Clk` * Change C to make `struct clk` refcounted. Best, Gary > > — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 20:36 ` Gary Guo @ 2026-02-04 8:11 ` Boris Brezillon 2026-02-04 9:18 ` Maxime Ripard 0 siblings, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-04 8:11 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Alice Ryhl, Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hi Gary, Daniel, On Tue, 03 Feb 2026 20:36:30 +0000 "Gary Guo" <gary@garyguo.net> wrote: > On Tue Feb 3, 2026 at 7:26 PM GMT, Daniel Almeida wrote: > > > >> > >> I think it's fine to have all of these: > >> * `Clone` impl > >> * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` > >> * `with_enabled` that gives `&Clk<Enabled>` > >> > >> This way, if you only want to enable in short time, you can do `with_enabled`. > >> If the closure callback wants to keep clock enabled for longer, it can just do > >> `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. > >> > >> If the user just have a reference and want to enable the callback they can do > >> `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? > >> > >> Best, > >> Gary > > > > > > I’m ok with what you proposed above. The only problem is that implementing > > clone() is done through an Arc<*mut bindings::clk> in Boris’ current > > design, so this requires an extra allocation. > > Hmm, that's a very good point. `struct clk` is already a reference into > clk_core, so having to put another level of indirection over is not ideal. > However, if we're going to keep C code unchanged and do a zero-cost abstraction > on the Rust side, then we won't be able to have have multiple prepare/enable to > the same `struct clk` with the current design. > > It feels like we can to do a trade-off and choose from: > 1. Not be able to have multiple prepare/enable calls on the same `clk` (this can > limit users that need dynamically enable/disable clocks, with the very limited > exception that closure-callback is fine). > 2. Do an extra allocation > 3. Put lifetime on types that represent a prepared/enabled `Clk` > 4. Change C to make `struct clk` refcounted. It probably comes to no surprise that I'd be more in favor of option 2 or 4. Maybe option 2 first, so we can get the user-facing API merged without too much churn, and then we can see if the clk maintainers are happy adding a refcnt to struct clk to optimize things. If we really feel that the indirection/memory overhead is going to hurt us, we can also start with option 1, and extend it to 2 and/or 4 (needed to add a Clone support) when it becomes evident we can't do without it. But as I was saying in my previous reply to Daniel, I expect the extra indirection/memory overhead to be negligible since: 1. clks are usually not {prepared,enabled}/{disabled,unprepared} in a hot path 2. in the rare occasions where they might be ({dev,cpu}freq ?), this clk state change is usually one operation in an ocean of other slower operations (regulator reconfiguration, for instance, which usually goes over a slow I2C bus, or a relatively-faster-but-still-slow SPI one, at least when we compare it to an IoMem access for in-SoCs clks). So overall, the clk state change might account for a very small portion of the CPU cycles spent in this bigger operation 3. if I focus solely on the clk aspect, and look at the existing indirections in the clk framework (clk -> clk_core -> clk_{hw,ops} -> clk_methods), I'd expect the Arc indirection to be just noise in this pre-existing overhead 4. in term of memory, we're talking about 16 more bytes allocated per Clk on a 64-bit architecture (refcount is an int, but the alignment for the clk pointer forces 4 bytes of padding on most architectures). On a 64 bit arch, struct clk is 72 bytes if my math is correct, so that's a 22% overhead, compared to 11% overhead if the refcount was in struct clk (or in a struct refcounted_clk variant if we don't want C users to pay the price). Not great, but not terrible either So yeah my gut feeling is that we might be overthinking this extra allocation/indirection issue. This being said, one thing I'd really like to avoid is us being dragged into infinite discussions about a perfect implementation causing the merging of these changes to be delayed and other contributions being blocked on this (perfect is the enemy of good). I mean, option #1 is already an improvement compared to the raw functions we have at the moment, so if that's the middle-ground we agree on, I'm happy to give it my R-b. Regards, Boris ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-04 8:11 ` Boris Brezillon @ 2026-02-04 9:18 ` Maxime Ripard 0 siblings, 0 replies; 68+ messages in thread From: Maxime Ripard @ 2026-02-04 9:18 UTC (permalink / raw) To: Boris Brezillon Cc: Gary Guo, Daniel Almeida, Alice Ryhl, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux [-- Attachment #1: Type: text/plain, Size: 3544 bytes --] On Wed, Feb 04, 2026 at 09:11:04AM +0100, Boris Brezillon wrote: > Hi Gary, Daniel, > > On Tue, 03 Feb 2026 20:36:30 +0000 > "Gary Guo" <gary@garyguo.net> wrote: > > > On Tue Feb 3, 2026 at 7:26 PM GMT, Daniel Almeida wrote: > > > > > >> > > >> I think it's fine to have all of these: > > >> * `Clone` impl > > >> * `enable` which consumes `Clk<Prepared>` by value and spit out `Clk<Enabled>` > > >> * `with_enabled` that gives `&Clk<Enabled>` > > >> > > >> This way, if you only want to enable in short time, you can do `with_enabled`. > > >> If the closure callback wants to keep clock enabled for longer, it can just do > > >> `.clone()` inside the closure and obtain an owned `Clk<Enabled>`. > > >> > > >> If the user just have a reference and want to enable the callback they can do > > >> `prepared_clk.clone().enable()` which gives an owned `Clk<Enabled>`. Thoughts? > > >> > > >> Best, > > >> Gary > > > > > > > > > I’m ok with what you proposed above. The only problem is that implementing > > > clone() is done through an Arc<*mut bindings::clk> in Boris’ current > > > design, so this requires an extra allocation. > > > > Hmm, that's a very good point. `struct clk` is already a reference into > > clk_core, so having to put another level of indirection over is not ideal. > > However, if we're going to keep C code unchanged and do a zero-cost abstraction > > on the Rust side, then we won't be able to have have multiple prepare/enable to > > the same `struct clk` with the current design. > > > > It feels like we can to do a trade-off and choose from: > > 1. Not be able to have multiple prepare/enable calls on the same `clk` (this can > > limit users that need dynamically enable/disable clocks, with the very limited > > exception that closure-callback is fine). > > 2. Do an extra allocation > > 3. Put lifetime on types that represent a prepared/enabled `Clk` > > 4. Change C to make `struct clk` refcounted. > > It probably comes to no surprise that I'd be more in favor of option 2 > or 4. Maybe option 2 first, so we can get the user-facing API merged > without too much churn, and then we can see if the clk maintainers are > happy adding a refcnt to struct clk to optimize things. > > If we really feel that the indirection/memory overhead is going to > hurt us, we can also start with option 1, and extend it to 2 and/or 4 > (needed to add a Clone support) when it becomes evident we can't do > without it. But as I was saying in my previous reply to Daniel, I > expect the extra indirection/memory overhead to be negligible since: > > 1. clks are usually not {prepared,enabled}/{disabled,unprepared} in a > hot path > 2. in the rare occasions where they might be ({dev,cpu}freq ?), this > clk state change is usually one operation in an ocean of other > slower operations (regulator reconfiguration, for instance, which > usually goes over a slow I2C bus, or a > relatively-faster-but-still-slow SPI one, at least when we compare > it to an IoMem access for in-SoCs clks). So overall, the clk state > change might account for a very small portion of the CPU cycles > spent in this bigger operation I'm not even too worried about that one. devfreq and cpufreq will typically adjust the clock rate while device is active, and thus the clock is enabled. So we shouldn't have a prepared -> enabled transition in the path that adjust the device / cpu rate, it would have happened before. Maxime [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 273 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 10:45 ` Maxime Ripard 2026-01-19 12:13 ` Daniel Almeida 2026-01-19 12:35 ` Alice Ryhl @ 2026-01-19 14:26 ` Gary Guo 2026-01-19 15:44 ` Daniel Almeida 2 siblings, 1 reply; 68+ messages in thread From: Gary Guo @ 2026-01-19 14:26 UTC (permalink / raw) To: Maxime Ripard, Daniel Almeida Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 10:45 AM GMT, Maxime Ripard wrote: > On Thu, Jan 08, 2026 at 11:14:37AM -0300, Daniel Almeida wrote: >> Hi Maxime :) >> >> > >> > I don't know the typestate pattern that well, but I wonder if we don't >> > paint ourselves into a corner by introducing it. >> > >> > While it's pretty common to get your clock from the get go into a state, >> > and then don't modify it (like what devm_clk_get_enabled provides for >> > example), and the typestate pattern indeed works great for those, we >> >> Minor correction, devm_clk_get_enabled is not handled by the typestate >> pattern. The next patch does include this function for convenience, but >> you get a Result<()>. The typestate pattern is used when you want more >> control. >> >> > also have a significant number of drivers that will have a finer-grained >> > control over the clock enablement for PM. >> > >> > For example, it's quite typical to have (at least) one clock for the bus >> > interface that drives the register, and one that drives the main >> > component logic. The former needs to be enabled only when you're >> > accessing the registers (and can be abstracted with >> > regmap_mmio_attach_clk for example), and the latter needs to be enabled >> > only when the device actually starts operating. >> > >> > You have a similar thing for the prepare vs enable thing. The difference >> > between the two is that enable can be called into atomic context but >> > prepare can't. >> > >> > So for drivers that would care about this, you would create your device >> > with an unprepared clock, and then at various times during the driver >> > lifetime, you would mutate that state. >> > >> > AFAIU, encoding the state of the clock into the Clk type (and thus >> > forcing the structure that holds it) prevents that mutation. If not, we >> > should make it clearer (by expanding the doc maybe?) how such a pattern >> > can be supported. >> > >> > Maxime >> >> IIUC, your main point seems to be about mutating the state at runtime? This is >> possible with this code. You can just have an enum, for example: >> >> enum MyClocks { >> Unprepared(Clk<Unprepared>), >> Prepared(Clk<Prepared>), >> Enabled(Clk<Enabled>), >> } >> >> In fact, I specifically wanted to ensure that this was possible when writing >> these patches, as it’s needed by drivers. If you want to, I can cover that in >> the examples, no worries. > > Yes, that would be great. I do wonder though if it wouldn't make sense > to turn it the other way around. It creates a fair share of boilerplate > for a number of drivers. Can't we keep Clk the way it is as a > lower-level type, and crate a ManagedClk (or whatever name you prefer) > that drivers can use, and would be returned by higher-level helpers, if > they so choose? > > That way, we do have the typestate API for whoever wants to, without > creating too much boilerplate for everybody else. One solution is to have a new typestate `Dynamic` which opts to track things using variables. struct Dynamic { enabled: bool, prepared: bool, } trait ClkState { // Change to methods fn disable_on_drop(&self) -> bool; } struct Clk<State> { ... // Keep an instance, which is zero-sized for everything except `Dynamic` state: State, } this way we can have runtime-checked state conversions. Best, Gary ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 14:26 ` Gary Guo @ 2026-01-19 15:44 ` Daniel Almeida 0 siblings, 0 replies; 68+ messages in thread From: Daniel Almeida @ 2026-01-19 15:44 UTC (permalink / raw) To: Gary Guo Cc: Maxime Ripard, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Ren Guo, Wei Fu, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux, Gary Guo >> Yes, that would be great. I do wonder though if it wouldn't make sense >> to turn it the other way around. It creates a fair share of boilerplate >> for a number of drivers. Can't we keep Clk the way it is as a >> lower-level type, and crate a ManagedClk (or whatever name you prefer) >> that drivers can use, and would be returned by higher-level helpers, if >> they so choose? >> >> That way, we do have the typestate API for whoever wants to, without >> creating too much boilerplate for everybody else. > > One solution is to have a new typestate `Dynamic` which opts to track things > using variables. > > struct Dynamic { > enabled: bool, > prepared: bool, > } > > trait ClkState { > // Change to methods > fn disable_on_drop(&self) -> bool; > } > > struct Clk<State> { > ... > // Keep an instance, which is zero-sized for everything except `Dynamic` > state: State, > } > > this way we can have runtime-checked state conversions. > > Best, > Gary There used to be a Dynamic state in the past in a similar setting. That was removed after some thorough discussion. I’d say we should refrain from going back to this. Specially considering that the current design works fine. I can remove the turbofish if you want, even though I think they’re useful so that we have the same API for all states. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida 2026-01-08 8:07 ` Maxime Ripard @ 2026-01-19 14:20 ` Gary Guo 2026-01-19 15:22 ` Miguel Ojeda 2026-02-02 16:10 ` Boris Brezillon 2026-02-03 9:17 ` Boris Brezillon 2 siblings, 2 replies; 68+ messages in thread From: Gary Guo @ 2026-01-19 14:20 UTC (permalink / raw) To: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Wed Jan 7, 2026 at 3:09 PM GMT, Daniel Almeida wrote: > The current Clk abstraction can still be improved on the following issues: > > a) It only keeps track of a count to clk_get(), which means that users have > to manually call disable() and unprepare(), or a variation of those, like > disable_unprepare(). > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > of how often these were called, i.e., it's currently legal to write the > following: > > clk.prepare(); > clk.prepare(); > clk.enable(); > clk.enable(); > > And nothing gets undone on drop(). > > c) It adds a OptionalClk type that is probably not needed. There is no > "struct optional_clk" in C and we should probably not add one. > > d) It does not let a user express the state of the clk through the > type system. For example, there is currently no way to encode that a Clk is > enabled via the type system alone. > > In light of the Regulator abstraction that was recently merged, switch this > abstraction to use the type-state pattern instead. It solves both a) and b) > by establishing a number of states and the valid ways to transition between > them. It also automatically undoes any call to clk_get(), clk_prepare() and > clk_enable() as applicable on drop(), so users do not have to do anything > special before Clk goes out of scope. > > It solves c) by removing the OptionalClk type, which is now simply encoded > as a Clk whose inner pointer is NULL. > > It solves d) by directly encoding the state of the Clk into the type, e.g.: > Clk<Enabled> is now known to be a Clk that is enabled. > > The INVARIANTS section for Clk is expanded to highlight the relationship > between the states and the respective reference counts that are owned by > each of them. > > The examples are expanded to highlight how a user can transition between > states, as well as highlight some of the shortcuts built into the API. > > The current implementation is also more flexible, in the sense that it > allows for more states to be added in the future. This lets us implement > different strategies for handling clocks, including one that mimics the > current API, allowing for multiple calls to prepare() and enable(). > > The users (cpufreq.rs/ rcpufreq_dt.rs) were updated by this patch (and not > a separate one) to reflect the new changes. This is needed, because > otherwise this patch would break the build. > > Link: https://crates.io/crates/sealed [1] > Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> > --- > drivers/cpufreq/rcpufreq_dt.rs | 2 +- > drivers/gpu/drm/tyr/driver.rs | 31 +--- > drivers/pwm/pwm_th1520.rs | 17 +- > rust/kernel/clk.rs | 399 +++++++++++++++++++++++++++-------------- > rust/kernel/cpufreq.rs | 8 +- > 5 files changed, 281 insertions(+), 176 deletions(-) > > diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs > index 31e07f0279db..f1bd7d71ed54 100644 > --- a/drivers/cpufreq/rcpufreq_dt.rs > +++ b/drivers/cpufreq/rcpufreq_dt.rs > @@ -41,7 +41,7 @@ struct CPUFreqDTDevice { > freq_table: opp::FreqTable, > _mask: CpumaskVar, > _token: Option<opp::ConfigToken>, > - _clk: Clk, > + _clk: Clk<kernel::clk::Unprepared>, > } > > #[derive(Default)] > diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs > index 09711fb7fe0b..5692def25621 100644 > --- a/drivers/gpu/drm/tyr/driver.rs > +++ b/drivers/gpu/drm/tyr/driver.rs > @@ -2,7 +2,7 @@ > > use kernel::c_str; > use kernel::clk::Clk; > -use kernel::clk::OptionalClk; > +use kernel::clk::Enabled; > use kernel::device::Bound; > use kernel::device::Core; > use kernel::device::Device; > @@ -37,7 +37,7 @@ pub(crate) struct TyrDriver { > device: ARef<TyrDevice>, > } > > -#[pin_data(PinnedDrop)] > +#[pin_data] > pub(crate) struct TyrData { > pub(crate) pdev: ARef<platform::Device>, > > @@ -92,13 +92,9 @@ fn probe( > pdev: &platform::Device<Core>, > _info: Option<&Self::IdInfo>, > ) -> impl PinInit<Self, Error> { > - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; > - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; > - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; > - > - core_clk.prepare_enable()?; > - stacks_clk.prepare_enable()?; > - coregroup_clk.prepare_enable()?; > + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; Ah, more turbofish.. I'd really want to avoid them if possible. Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This way it is also clear that some action is performed. Alternatively, I think function names that mimick C API is also fine, e.g. `Clk::get_enabled`. > + let stacks_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("stacks")))?; > + let coregroup_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("coregroup")))?; > > let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("mali"))?; > let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("sram"))?; > @@ -145,17 +141,6 @@ impl PinnedDrop for TyrDriver { > fn drop(self: Pin<&mut Self>) {} > } > > -#[pinned_drop] > -impl PinnedDrop for TyrData { > - fn drop(self: Pin<&mut Self>) { > - // TODO: the type-state pattern for Clks will fix this. > - let clks = self.clks.lock(); > - clks.core.disable_unprepare(); > - clks.stacks.disable_unprepare(); > - clks.coregroup.disable_unprepare(); > - } > -} > - > // We need to retain the name "panthor" to achieve drop-in compatibility with > // the C driver in the userspace stack. > const INFO: drm::DriverInfo = drm::DriverInfo { > @@ -181,9 +166,9 @@ impl drm::Driver for TyrDriver { > > #[pin_data] > struct Clocks { > - core: Clk, > - stacks: OptionalClk, > - coregroup: OptionalClk, > + core: Clk<Enabled>, > + stacks: Clk<Enabled>, > + coregroup: Clk<Enabled>, > } > > #[pin_data] > diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs > index 043dc4dbc623..f4d03b988533 100644 > --- a/drivers/pwm/pwm_th1520.rs > +++ b/drivers/pwm/pwm_th1520.rs > @@ -23,7 +23,7 @@ > use core::ops::Deref; > use kernel::{ > c_str, > - clk::Clk, > + clk::{Clk, Enabled}, > device::{Bound, Core, Device}, > devres, > io::mem::IoMem, > @@ -90,11 +90,11 @@ struct Th1520WfHw { > } > > /// The driver's private data struct. It holds all necessary devres managed resources. > -#[pin_data(PinnedDrop)] > +#[pin_data] > struct Th1520PwmDriverData { > #[pin] > iomem: devres::Devres<IoMem<TH1520_PWM_REG_SIZE>>, > - clk: Clk, > + clk: Clk<Enabled>, > } > > impl pwm::PwmOps for Th1520PwmDriverData { > @@ -299,13 +299,6 @@ fn write_waveform( > } > } > > -#[pinned_drop] > -impl PinnedDrop for Th1520PwmDriverData { > - fn drop(self: Pin<&mut Self>) { > - self.clk.disable_unprepare(); > - } > -} > - > struct Th1520PwmPlatformDriver; > > kernel::of_device_table!( > @@ -326,9 +319,7 @@ fn probe( > let dev = pdev.as_ref(); > let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; > > - let clk = Clk::get(dev, None)?; > - > - clk.prepare_enable()?; > + let clk = Clk::<Enabled>::get(dev, None)?; > > // TODO: Get exclusive ownership of the clock to prevent rate changes. > // The Rust equivalent of `clk_rate_exclusive_get()` is not yet available. > diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs > index d192fbd97861..6323b40dc7ba 100644 > --- a/rust/kernel/clk.rs > +++ b/rust/kernel/clk.rs > @@ -80,17 +80,78 @@ fn from(freq: Hertz) -> Self { > mod common_clk { > use super::Hertz; > use crate::{ > - device::Device, > + device::{Bound, Device}, > error::{from_err_ptr, to_result, Result}, > prelude::*, > }; > > - use core::{ops::Deref, ptr}; > + use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; > + > + mod private { > + pub trait Sealed {} > + > + impl Sealed for super::Unprepared {} > + impl Sealed for super::Prepared {} > + impl Sealed for super::Enabled {} > + } I guess it's time for me to work on a `#[sealed]` macro... > + > + /// A trait representing the different states that a [`Clk`] can be in. > + pub trait ClkState: private::Sealed { > + /// Whether the clock should be disabled when dropped. > + const DISABLE_ON_DROP: bool; > + > + /// Whether the clock should be unprepared when dropped. > + const UNPREPARE_ON_DROP: bool; > + } > + > + /// A state where the [`Clk`] is not prepared and not enabled. Do we want to make it explicit that it's "not known to be prepared or enabled"? > + pub struct Unprepared; > + > + /// A state where the [`Clk`] is prepared but not enabled. > + pub struct Prepared; > + > + /// A state where the [`Clk`] is both prepared and enabled. > + pub struct Enabled; > + > + impl ClkState for Unprepared { > + const DISABLE_ON_DROP: bool = false; > + const UNPREPARE_ON_DROP: bool = false; > + } > + > + impl ClkState for Prepared { > + const DISABLE_ON_DROP: bool = false; > + const UNPREPARE_ON_DROP: bool = true; > + } > + > + impl ClkState for Enabled { > + const DISABLE_ON_DROP: bool = true; > + const UNPREPARE_ON_DROP: bool = true; > + } > + > + /// An error that can occur when trying to convert a [`Clk`] between states. > + pub struct Error<State: ClkState> { > + /// The error that occurred. > + pub error: kernel::error::Error, > + > + /// The [`Clk`] that caused the error, so that the operation may be > + /// retried. > + pub clk: Clk<State>, > + } I wonder if it makes sense to add a general `ErrorWith` type for errors that carries error code + data. Best, Gary ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 14:20 ` Gary Guo @ 2026-01-19 15:22 ` Miguel Ojeda 2026-01-19 15:36 ` Gary Guo 2026-02-02 16:10 ` Boris Brezillon 1 sibling, 1 reply; 68+ messages in thread From: Miguel Ojeda @ 2026-01-19 15:22 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon, Jan 19, 2026 at 3:20 PM Gary Guo <gary@garyguo.net> wrote: > > I guess it's time for me to work on a `#[sealed]` macro... ...and perhaps pinging upstream for the language feature... :) I added https://github.com/rust-lang/rust/issues/105077 to our usual list of wishes at https://github.com/Rust-for-Linux/linux/issues/354. Do you think using the linked crate in the commit message would make sense? It seems to be a couple pages of code, using `syn` 2.0, which should be fine now. Another option is a "good first issue" of medium difficulty if you wish. > I wonder if it makes sense to add a general `ErrorWith` type for errors that > carries error code + data. Sounds reasonable... Cheers, Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 15:22 ` Miguel Ojeda @ 2026-01-19 15:36 ` Gary Guo 2026-01-19 15:46 ` Miguel Ojeda 0 siblings, 1 reply; 68+ messages in thread From: Gary Guo @ 2026-01-19 15:36 UTC (permalink / raw) To: Miguel Ojeda, Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 3:22 PM GMT, Miguel Ojeda wrote: > On Mon, Jan 19, 2026 at 3:20 PM Gary Guo <gary@garyguo.net> wrote: >> >> I guess it's time for me to work on a `#[sealed]` macro... > > ...and perhaps pinging upstream for the language feature... :) I added > https://github.com/rust-lang/rust/issues/105077 to our usual list of > wishes at https://github.com/Rust-for-Linux/linux/issues/354. > > Do you think using the linked crate in the commit message would make > sense? It seems to be a couple pages of code, using `syn` 2.0, which > should be fine now. Which crate are you talking about? I can't find a linked crate in the issue. Best, Gary > > Another option is a "good first issue" of medium difficulty if you wish. > >> I wonder if it makes sense to add a general `ErrorWith` type for errors that >> carries error code + data. > > Sounds reasonable... > > Cheers, > Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 15:36 ` Gary Guo @ 2026-01-19 15:46 ` Miguel Ojeda 2026-01-19 16:10 ` Gary Guo 0 siblings, 1 reply; 68+ messages in thread From: Miguel Ojeda @ 2026-01-19 15:46 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon, Jan 19, 2026 at 4:36 PM Gary Guo <gary@garyguo.net> wrote: > > Which crate are you talking about? I can't find a linked crate in the issue. The commit message (i.e. not the issue) has an (unused) link with the `sealed` crate: Link: https://crates.io/crates/sealed [1] Cheers, Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 15:46 ` Miguel Ojeda @ 2026-01-19 16:10 ` Gary Guo 0 siblings, 0 replies; 68+ messages in thread From: Gary Guo @ 2026-01-19 16:10 UTC (permalink / raw) To: Miguel Ojeda, Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon Jan 19, 2026 at 3:46 PM GMT, Miguel Ojeda wrote: > On Mon, Jan 19, 2026 at 4:36 PM Gary Guo <gary@garyguo.net> wrote: >> >> Which crate are you talking about? I can't find a linked crate in the issue. > > The commit message (i.e. not the issue) has an (unused) link with the > `sealed` crate: > > Link: https://crates.io/crates/sealed [1] Yeah, some thing similar. Probably an even simpler version with only things that we need. Best, Gary > > Cheers, > Miguel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-19 14:20 ` Gary Guo 2026-01-19 15:22 ` Miguel Ojeda @ 2026-02-02 16:10 ` Boris Brezillon 2026-02-03 9:09 ` Boris Brezillon 1 sibling, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-02 16:10 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Mon, 19 Jan 2026 14:20:43 +0000 "Gary Guo" <gary@garyguo.net> wrote: > On Wed Jan 7, 2026 at 3:09 PM GMT, Daniel Almeida wrote: > > The current Clk abstraction can still be improved on the following issues: > > > > a) It only keeps track of a count to clk_get(), which means that users have > > to manually call disable() and unprepare(), or a variation of those, like > > disable_unprepare(). > > > > b) It allows repeated calls to prepare() or enable(), but it keeps no track > > of how often these were called, i.e., it's currently legal to write the > > following: > > > > clk.prepare(); > > clk.prepare(); > > clk.enable(); > > clk.enable(); > > > > And nothing gets undone on drop(). > > > > c) It adds a OptionalClk type that is probably not needed. There is no > > "struct optional_clk" in C and we should probably not add one. > > > > d) It does not let a user express the state of the clk through the > > type system. For example, there is currently no way to encode that a Clk is > > enabled via the type system alone. > > > > In light of the Regulator abstraction that was recently merged, switch this > > abstraction to use the type-state pattern instead. It solves both a) and b) > > by establishing a number of states and the valid ways to transition between > > them. It also automatically undoes any call to clk_get(), clk_prepare() and > > clk_enable() as applicable on drop(), so users do not have to do anything > > special before Clk goes out of scope. > > > > It solves c) by removing the OptionalClk type, which is now simply encoded > > as a Clk whose inner pointer is NULL. > > > > It solves d) by directly encoding the state of the Clk into the type, e.g.: > > Clk<Enabled> is now known to be a Clk that is enabled. > > > > The INVARIANTS section for Clk is expanded to highlight the relationship > > between the states and the respective reference counts that are owned by > > each of them. > > > > The examples are expanded to highlight how a user can transition between > > states, as well as highlight some of the shortcuts built into the API. > > > > The current implementation is also more flexible, in the sense that it > > allows for more states to be added in the future. This lets us implement > > different strategies for handling clocks, including one that mimics the > > current API, allowing for multiple calls to prepare() and enable(). > > > > The users (cpufreq.rs/ rcpufreq_dt.rs) were updated by this patch (and not > > a separate one) to reflect the new changes. This is needed, because > > otherwise this patch would break the build. > > > > Link: https://crates.io/crates/sealed [1] > > Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> > > --- > > drivers/cpufreq/rcpufreq_dt.rs | 2 +- > > drivers/gpu/drm/tyr/driver.rs | 31 +--- > > drivers/pwm/pwm_th1520.rs | 17 +- > > rust/kernel/clk.rs | 399 +++++++++++++++++++++++++++-------------- > > rust/kernel/cpufreq.rs | 8 +- > > 5 files changed, 281 insertions(+), 176 deletions(-) > > > > diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs > > index 31e07f0279db..f1bd7d71ed54 100644 > > --- a/drivers/cpufreq/rcpufreq_dt.rs > > +++ b/drivers/cpufreq/rcpufreq_dt.rs > > @@ -41,7 +41,7 @@ struct CPUFreqDTDevice { > > freq_table: opp::FreqTable, > > _mask: CpumaskVar, > > _token: Option<opp::ConfigToken>, > > - _clk: Clk, > > + _clk: Clk<kernel::clk::Unprepared>, > > } > > > > #[derive(Default)] > > diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs > > index 09711fb7fe0b..5692def25621 100644 > > --- a/drivers/gpu/drm/tyr/driver.rs > > +++ b/drivers/gpu/drm/tyr/driver.rs > > @@ -2,7 +2,7 @@ > > > > use kernel::c_str; > > use kernel::clk::Clk; > > -use kernel::clk::OptionalClk; > > +use kernel::clk::Enabled; > > use kernel::device::Bound; > > use kernel::device::Core; > > use kernel::device::Device; > > @@ -37,7 +37,7 @@ pub(crate) struct TyrDriver { > > device: ARef<TyrDevice>, > > } > > > > -#[pin_data(PinnedDrop)] > > +#[pin_data] > > pub(crate) struct TyrData { > > pub(crate) pdev: ARef<platform::Device>, > > > > @@ -92,13 +92,9 @@ fn probe( > > pdev: &platform::Device<Core>, > > _info: Option<&Self::IdInfo>, > > ) -> impl PinInit<Self, Error> { > > - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; > > - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; > > - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; > > - > > - core_clk.prepare_enable()?; > > - stacks_clk.prepare_enable()?; > > - coregroup_clk.prepare_enable()?; > > + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; > > Ah, more turbofish.. I'd really want to avoid them if possible. > > Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This > way it is also clear that some action is performed. I've just disc > > Alternatively, I think function names that mimick C API is also fine, e.g. > `Clk::get_enabled`. > > > + let stacks_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("stacks")))?; > > + let coregroup_clk = Clk::<Enabled>::get_optional(pdev.as_ref(), Some(c_str!("coregroup")))?; > > > > let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("mali"))?; > > let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c_str!("sram"))?; > > @@ -145,17 +141,6 @@ impl PinnedDrop for TyrDriver { > > fn drop(self: Pin<&mut Self>) {} > > } > > > > -#[pinned_drop] > > -impl PinnedDrop for TyrData { > > - fn drop(self: Pin<&mut Self>) { > > - // TODO: the type-state pattern for Clks will fix this. > > - let clks = self.clks.lock(); > > - clks.core.disable_unprepare(); > > - clks.stacks.disable_unprepare(); > > - clks.coregroup.disable_unprepare(); > > - } > > -} > > - > > // We need to retain the name "panthor" to achieve drop-in compatibility with > > // the C driver in the userspace stack. > > const INFO: drm::DriverInfo = drm::DriverInfo { > > @@ -181,9 +166,9 @@ impl drm::Driver for TyrDriver { > > > > #[pin_data] > > struct Clocks { > > - core: Clk, > > - stacks: OptionalClk, > > - coregroup: OptionalClk, > > + core: Clk<Enabled>, > > + stacks: Clk<Enabled>, > > + coregroup: Clk<Enabled>, > > } > > > > #[pin_data] > > diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs > > index 043dc4dbc623..f4d03b988533 100644 > > --- a/drivers/pwm/pwm_th1520.rs > > +++ b/drivers/pwm/pwm_th1520.rs > > @@ -23,7 +23,7 @@ > > use core::ops::Deref; > > use kernel::{ > > c_str, > > - clk::Clk, > > + clk::{Clk, Enabled}, > > device::{Bound, Core, Device}, > > devres, > > io::mem::IoMem, > > @@ -90,11 +90,11 @@ struct Th1520WfHw { > > } > > > > /// The driver's private data struct. It holds all necessary devres managed resources. > > -#[pin_data(PinnedDrop)] > > +#[pin_data] > > struct Th1520PwmDriverData { > > #[pin] > > iomem: devres::Devres<IoMem<TH1520_PWM_REG_SIZE>>, > > - clk: Clk, > > + clk: Clk<Enabled>, > > } > > > > impl pwm::PwmOps for Th1520PwmDriverData { > > @@ -299,13 +299,6 @@ fn write_waveform( > > } > > } > > > > -#[pinned_drop] > > -impl PinnedDrop for Th1520PwmDriverData { > > - fn drop(self: Pin<&mut Self>) { > > - self.clk.disable_unprepare(); > > - } > > -} > > - > > struct Th1520PwmPlatformDriver; > > > > kernel::of_device_table!( > > @@ -326,9 +319,7 @@ fn probe( > > let dev = pdev.as_ref(); > > let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; > > > > - let clk = Clk::get(dev, None)?; > > - > > - clk.prepare_enable()?; > > + let clk = Clk::<Enabled>::get(dev, None)?; > > > > // TODO: Get exclusive ownership of the clock to prevent rate changes. > > // The Rust equivalent of `clk_rate_exclusive_get()` is not yet available. > > diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs > > index d192fbd97861..6323b40dc7ba 100644 > > --- a/rust/kernel/clk.rs > > +++ b/rust/kernel/clk.rs > > @@ -80,17 +80,78 @@ fn from(freq: Hertz) -> Self { > > mod common_clk { > > use super::Hertz; > > use crate::{ > > - device::Device, > > + device::{Bound, Device}, > > error::{from_err_ptr, to_result, Result}, > > prelude::*, > > }; > > > > - use core::{ops::Deref, ptr}; > > + use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; > > + > > + mod private { > > + pub trait Sealed {} > > + > > + impl Sealed for super::Unprepared {} > > + impl Sealed for super::Prepared {} > > + impl Sealed for super::Enabled {} > > + } > > I guess it's time for me to work on a `#[sealed]` macro... > > > + > > + /// A trait representing the different states that a [`Clk`] can be in. > > + pub trait ClkState: private::Sealed { > > + /// Whether the clock should be disabled when dropped. > > + const DISABLE_ON_DROP: bool; > > + > > + /// Whether the clock should be unprepared when dropped. > > + const UNPREPARE_ON_DROP: bool; > > + } > > + > > + /// A state where the [`Clk`] is not prepared and not enabled. > > Do we want to make it explicit that it's "not known to be prepared or > enabled"? > > > + pub struct Unprepared; > > + > > + /// A state where the [`Clk`] is prepared but not enabled. > > + pub struct Prepared; > > + > > + /// A state where the [`Clk`] is both prepared and enabled. > > + pub struct Enabled; > > + > > + impl ClkState for Unprepared { > > + const DISABLE_ON_DROP: bool = false; > > + const UNPREPARE_ON_DROP: bool = false; > > + } > > + > > + impl ClkState for Prepared { > > + const DISABLE_ON_DROP: bool = false; > > + const UNPREPARE_ON_DROP: bool = true; > > + } > > + > > + impl ClkState for Enabled { > > + const DISABLE_ON_DROP: bool = true; > > + const UNPREPARE_ON_DROP: bool = true; > > + } > > + > > + /// An error that can occur when trying to convert a [`Clk`] between states. > > + pub struct Error<State: ClkState> { > > + /// The error that occurred. > > + pub error: kernel::error::Error, > > + > > + /// The [`Clk`] that caused the error, so that the operation may be > > + /// retried. > > + pub clk: Clk<State>, > > + } > > I wonder if it makes sense to add a general `ErrorWith` type for errors that > carries error code + data. > > Best, > Gary ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-02 16:10 ` Boris Brezillon @ 2026-02-03 9:09 ` Boris Brezillon 2026-02-03 9:47 ` Boris Brezillon 2026-02-03 13:37 ` Daniel Almeida 0 siblings, 2 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 9:09 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hello Daniel, On Mon, 2 Feb 2026 17:10:38 +0100 Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > -#[pin_data(PinnedDrop)] > > > +#[pin_data] > > > pub(crate) struct TyrData { > > > pub(crate) pdev: ARef<platform::Device>, > > > > > > @@ -92,13 +92,9 @@ fn probe( > > > pdev: &platform::Device<Core>, > > > _info: Option<&Self::IdInfo>, > > > ) -> impl PinInit<Self, Error> { > > > - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; > > > - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; > > > - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; > > > - > > > - core_clk.prepare_enable()?; > > > - stacks_clk.prepare_enable()?; > > > - coregroup_clk.prepare_enable()?; > > > + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; > > > > Ah, more turbofish.. I'd really want to avoid them if possible. > > > > Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This > > way it is also clear that some action is performed. > > I've just disc Sorry, I've hit the reply button before I had finished writing my answer. So I was about to say that I had started writing something similar without knowing this series existed, and I feel like we'd don't really need those prepare_enable() shortcuts that exist in C. We might has well just go: Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; and have the following variant-specofoc functions - Clk<Unprepared>::get[_optional]() (no get on Prepared and Enabled variants) - Clk<Unprepared>::prepare() - Clk<Prepared>::{enable,unprepare}() - Clk<Enabled>::{disable}() Regards, Boris ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 9:09 ` Boris Brezillon @ 2026-02-03 9:47 ` Boris Brezillon 2026-02-03 13:37 ` Daniel Almeida 1 sibling, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 9:47 UTC (permalink / raw) To: Gary Guo Cc: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 10:09:13 +0100 Boris Brezillon <boris.brezillon@collabora.com> wrote: > Hello Daniel, > > On Mon, 2 Feb 2026 17:10:38 +0100 > Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > > > -#[pin_data(PinnedDrop)] > > > > +#[pin_data] > > > > pub(crate) struct TyrData { > > > > pub(crate) pdev: ARef<platform::Device>, > > > > > > > > @@ -92,13 +92,9 @@ fn probe( > > > > pdev: &platform::Device<Core>, > > > > _info: Option<&Self::IdInfo>, > > > > ) -> impl PinInit<Self, Error> { > > > > - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; > > > > - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; > > > > - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; > > > > - > > > > - core_clk.prepare_enable()?; > > > > - stacks_clk.prepare_enable()?; > > > > - coregroup_clk.prepare_enable()?; > > > > + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; > > > > > > Ah, more turbofish.. I'd really want to avoid them if possible. > > > > > > Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This > > > way it is also clear that some action is performed. > > > > I've just disc > > Sorry, I've hit the reply button before I had finished writing my > answer. So I was about to say that I had started writing something > similar without knowing this series existed, and I feel like we'd don't > really need those prepare_enable() shortcuts that exist in C. We might > has well just go: > > Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; If we want this pattern to work, we also need: impl<State: ClkState> From<Error<State>> for kernel::error::Error { fn from(e: Error<State>) -> kernel::error::Error { e.error } } > > and have the following variant-specofoc functions > > - Clk<Unprepared>::get[_optional]() (no get on Prepared and Enabled > variants) > - Clk<Unprepared>::prepare() > - Clk<Prepared>::{enable,unprepare}() > - Clk<Enabled>::{disable}() > > Regards, > > Boris > ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 9:09 ` Boris Brezillon 2026-02-03 9:47 ` Boris Brezillon @ 2026-02-03 13:37 ` Daniel Almeida 2026-02-03 14:18 ` Boris Brezillon 1 sibling, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 13:37 UTC (permalink / raw) To: Boris Brezillon Cc: Gary Guo, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux > On 3 Feb 2026, at 06:09, Boris Brezillon <boris.brezillon@collabora.com> wrote: > > Hello Daniel, > > On Mon, 2 Feb 2026 17:10:38 +0100 > Boris Brezillon <boris.brezillon@collabora.com> wrote: > >>>> -#[pin_data(PinnedDrop)] >>>> +#[pin_data] >>>> pub(crate) struct TyrData { >>>> pub(crate) pdev: ARef<platform::Device>, >>>> >>>> @@ -92,13 +92,9 @@ fn probe( >>>> pdev: &platform::Device<Core>, >>>> _info: Option<&Self::IdInfo>, >>>> ) -> impl PinInit<Self, Error> { >>>> - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; >>>> - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; >>>> - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; >>>> - >>>> - core_clk.prepare_enable()?; >>>> - stacks_clk.prepare_enable()?; >>>> - coregroup_clk.prepare_enable()?; >>>> + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; >>> >>> Ah, more turbofish.. I'd really want to avoid them if possible. >>> >>> Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This >>> way it is also clear that some action is performed. >> >> I've just disc > > Sorry, I've hit the reply button before I had finished writing my > answer. So I was about to say that I had started writing something > similar without knowing this series existed, and I feel like we'd don't > really need those prepare_enable() shortcuts that exist in C. We might > has well just go: > > Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; > > and have the following variant-specofoc functions > > - Clk<Unprepared>::get[_optional]() (no get on Prepared and Enabled > variants) > - Clk<Unprepared>::prepare() > - Clk<Prepared>::{enable,unprepare}() > - Clk<Enabled>::{disable}() > > Regards, > > Boris > > I don’t understand how is this better than the turbofish we currently have. In other words, how is this: Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; Better than this: Clk::<Enabled>::get(/*…*/); — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 13:37 ` Daniel Almeida @ 2026-02-03 14:18 ` Boris Brezillon 0 siblings, 0 replies; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 14:18 UTC (permalink / raw) To: Daniel Almeida Cc: Gary Guo, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Tue, 3 Feb 2026 10:37:15 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > > On 3 Feb 2026, at 06:09, Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > > Hello Daniel, > > > > On Mon, 2 Feb 2026 17:10:38 +0100 > > Boris Brezillon <boris.brezillon@collabora.com> wrote: > > > >>>> -#[pin_data(PinnedDrop)] > >>>> +#[pin_data] > >>>> pub(crate) struct TyrData { > >>>> pub(crate) pdev: ARef<platform::Device>, > >>>> > >>>> @@ -92,13 +92,9 @@ fn probe( > >>>> pdev: &platform::Device<Core>, > >>>> _info: Option<&Self::IdInfo>, > >>>> ) -> impl PinInit<Self, Error> { > >>>> - let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; > >>>> - let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; > >>>> - let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; > >>>> - > >>>> - core_clk.prepare_enable()?; > >>>> - stacks_clk.prepare_enable()?; > >>>> - coregroup_clk.prepare_enable()?; > >>>> + let core_clk = Clk::<Enabled>::get(pdev.as_ref(), Some(c_str!("core")))?; > >>> > >>> Ah, more turbofish.. I'd really want to avoid them if possible. > >>> > >>> Any disadvantage on just ask the user to chain `.get().prepare_enable()?`? This > >>> way it is also clear that some action is performed. > >> > >> I've just disc > > > > Sorry, I've hit the reply button before I had finished writing my > > answer. So I was about to say that I had started writing something > > similar without knowing this series existed, and I feel like we'd don't > > really need those prepare_enable() shortcuts that exist in C. We might > > has well just go: > > > > Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; > > > > and have the following variant-specofoc functions > > > > - Clk<Unprepared>::get[_optional]() (no get on Prepared and Enabled > > variants) > > - Clk<Unprepared>::prepare() > > - Clk<Prepared>::{enable,unprepare}() > > - Clk<Enabled>::{disable}() > > > > Regards, > > > > Boris > > > > > > > I don’t understand how is this better than the turbofish we currently have. > > In other words, how is this: > > Clk::get(dev, Some(c_str!("core"))).prepare()?.enable()?; > > Better than this: > > Clk::<Enabled>::get(/*…*/); For one, it doesn't force you to expose multiple functions in the implementation (::get[_optional]() is only present in the Unprepared impl variant, no shortcut to combine state transition, ...) which means less code to maintain overall. But I also prefer the fact this clearly reflects the state transitions that exist to get an Enabled clk (first you get an Unprepared clk that you have to prepare and enable to turn that into an Enabled clk). That's a matter of taste of course, just saying that if we get rid of the turbofish syntax like Gary suggested at some point, I think I'd find it clearer to also just expose the transitions between two consecutive states, and let the caller go through all the steps. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida 2026-01-08 8:07 ` Maxime Ripard 2026-01-19 14:20 ` Gary Guo @ 2026-02-03 9:17 ` Boris Brezillon 2026-02-03 13:35 ` Daniel Almeida 2 siblings, 1 reply; 68+ messages in thread From: Boris Brezillon @ 2026-02-03 9:17 UTC (permalink / raw) To: Daniel Almeida Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hello Daniel, On Wed, 07 Jan 2026 12:09:52 -0300 Daniel Almeida <daniel.almeida@collabora.com> wrote: > - /// Disable and unprepare the clock. > + impl Clk<Enabled> { > + /// Gets [`Clk`] corresponding to a bound [`Device`] and a connection id > + /// and then prepares and enables it. > /// > - /// Equivalent to calling [`Clk::disable`] followed by [`Clk::unprepare`]. > + /// Equivalent to calling [`Clk::get`], followed by [`Clk::prepare`], > + /// followed by [`Clk::enable`]. > #[inline] > - pub fn disable_unprepare(&self) { > - // SAFETY: By the type invariants, self.as_raw() is a valid argument for > - // [`clk_disable_unprepare`]. > - unsafe { bindings::clk_disable_unprepare(self.as_raw()) }; > + pub fn get(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { > + Clk::<Prepared>::get(dev, name)? > + .enable() > + .map_err(|error| error.error) > + } > + > + /// Behaves the same as [`Self::get`], except when there is no clock > + /// producer. In this case, instead of returning [`ENOENT`], it returns > + /// a dummy [`Clk`]. > + #[inline] > + pub fn get_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { > + Clk::<Prepared>::get_optional(dev, name)? > + .enable() > + .map_err(|error| error.error) > + } > + > + /// Attempts to disable the [`Clk`] and convert it to the [`Prepared`] > + /// state. > + #[inline] > + pub fn disable(self) -> Result<Clk<Prepared>, Error<Enabled>> { > + // We will be transferring the ownership of our `clk_get()` and > + // `clk_enable()` counts to `Clk<Prepared>`. > + let clk = ManuallyDrop::new(self); > + > + // SAFETY: By the type invariants, `self.0` is a valid argument for > + // [`clk_disable`]. > + unsafe { bindings::clk_disable(clk.as_raw()) }; > + > + Ok(Clk { > + inner: clk.inner, > + _phantom: PhantomData, > + }) > } > > /// Get clock's rate. Dunno if this has been mentioned already, but I belive the rate getter/setter should be in the generic implementation. Indeed, it's quite common for clock users to change the rate when the clk is disabled to avoid unstable transitional state. The usual pattern for that is: - clk_set_parent(my_clk, secondary_parent) - clk_disable[_unprepare](primary_parent) // (usually a PLL) - clk_set_rate(primary_parent) - clk[_prepare]_enable(primary_parent) - clk_set_parent(my_clk, primary_parent) The case where the clk rate is changed while the clk is active is also valid (usually fine when it's just a divider that's changed, because there's no stabilization period). > @@ -252,83 +429,31 @@ pub fn set_rate(&self, rate: Hertz) -> Result { > } > } ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v3 1/3] rust: clk: use the type-state pattern 2026-02-03 9:17 ` Boris Brezillon @ 2026-02-03 13:35 ` Daniel Almeida 0 siblings, 0 replies; 68+ messages in thread From: Daniel Almeida @ 2026-02-03 13:35 UTC (permalink / raw) To: Boris Brezillon Cc: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross, linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux Hi Boris, > On 3 Feb 2026, at 06:17, Boris Brezillon <boris.brezillon@collabora.com> wrote: > > Hello Daniel, > > On Wed, 07 Jan 2026 12:09:52 -0300 > Daniel Almeida <daniel.almeida@collabora.com> wrote: > >> - /// Disable and unprepare the clock. >> + impl Clk<Enabled> { >> + /// Gets [`Clk`] corresponding to a bound [`Device`] and a connection id >> + /// and then prepares and enables it. >> /// >> - /// Equivalent to calling [`Clk::disable`] followed by [`Clk::unprepare`]. >> + /// Equivalent to calling [`Clk::get`], followed by [`Clk::prepare`], >> + /// followed by [`Clk::enable`]. >> #[inline] >> - pub fn disable_unprepare(&self) { >> - // SAFETY: By the type invariants, self.as_raw() is a valid argument for >> - // [`clk_disable_unprepare`]. >> - unsafe { bindings::clk_disable_unprepare(self.as_raw()) }; >> + pub fn get(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { >> + Clk::<Prepared>::get(dev, name)? >> + .enable() >> + .map_err(|error| error.error) >> + } >> + >> + /// Behaves the same as [`Self::get`], except when there is no clock >> + /// producer. In this case, instead of returning [`ENOENT`], it returns >> + /// a dummy [`Clk`]. >> + #[inline] >> + pub fn get_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result<Clk<Enabled>> { >> + Clk::<Prepared>::get_optional(dev, name)? >> + .enable() >> + .map_err(|error| error.error) >> + } >> + >> + /// Attempts to disable the [`Clk`] and convert it to the [`Prepared`] >> + /// state. >> + #[inline] >> + pub fn disable(self) -> Result<Clk<Prepared>, Error<Enabled>> { >> + // We will be transferring the ownership of our `clk_get()` and >> + // `clk_enable()` counts to `Clk<Prepared>`. >> + let clk = ManuallyDrop::new(self); >> + >> + // SAFETY: By the type invariants, `self.0` is a valid argument for >> + // [`clk_disable`]. >> + unsafe { bindings::clk_disable(clk.as_raw()) }; >> + >> + Ok(Clk { >> + inner: clk.inner, >> + _phantom: PhantomData, >> + }) >> } >> >> /// Get clock's rate. > > Dunno if this has been mentioned already, but I belive the rate > getter/setter should be in the generic implementation. Indeed, it's > quite common for clock users to change the rate when the clk is > disabled to avoid unstable transitional state. The usual pattern for > that is: > > - clk_set_parent(my_clk, secondary_parent) > - clk_disable[_unprepare](primary_parent) // (usually a PLL) > - clk_set_rate(primary_parent) > - clk[_prepare]_enable(primary_parent) > - clk_set_parent(my_clk, primary_parent) > > The case where the clk rate is changed while the clk is active is also > valid (usually fine when it's just a divider that's changed, because > there's no stabilization period). > >> @@ -252,83 +429,31 @@ pub fn set_rate(&self, rate: Hertz) -> Result { >> } >> } > I’m ok with this. I just assumed that these operations were only valid on enabled clks. Will change this in the next version. — Daniel ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v3 2/3] rust: clk: add devres-managed clks 2026-01-07 15:09 [PATCH v3 0/3] Clk improvements Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida @ 2026-01-07 15:09 ` Daniel Almeida 2026-01-19 14:33 ` Gary Guo 2026-01-07 15:09 ` [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports Daniel Almeida 2 siblings, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-01-07 15:09 UTC (permalink / raw) To: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux, Daniel Almeida The clk API allows fine-grained control, but some drivers might be more interested in a "set and forget" API. Expand the current API to support this. The clock will automatically be disabled, unprepared and freed when the device is unbound from the bus without further intervention by the driver. Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> --- rust/kernel/clk.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index 6323b40dc7ba..e840e7c20af7 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -95,6 +95,49 @@ impl Sealed for super::Prepared {} impl Sealed for super::Enabled {} } + /// Obtains and enables a [`devres`]-managed [`Clk`] for a bound device. + /// + /// [`devres`]: crate::devres::Devres + pub fn devm_enable(dev: &Device<Bound>, name: Option<&CStr>) -> Result { + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); + + // SAFETY: It is safe to call [`devm_clk_get_enabled`] with a valid + // device pointer. + from_err_ptr(unsafe { bindings::devm_clk_get_enabled(dev.as_raw(), name) })?; + Ok(()) + } + + /// Obtains and enables a [`devres`]-managed [`Clk`] for a bound device. + /// + /// This does not print any error messages if the clock is not found. + /// + /// [`devres`]: crate::devres::Devres + pub fn devm_enable_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result { + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); + + // SAFETY: It is safe to call [`devm_clk_get_optional_enabled`] with a + // valid device pointer. + from_err_ptr(unsafe { bindings::devm_clk_get_optional_enabled(dev.as_raw(), name) })?; + Ok(()) + } + + /// Same as [`devm_enable_optional`], but also sets the rate. + pub fn devm_enable_optional_with_rate( + dev: &Device, + name: Option<&CStr>, + rate: Hertz, + ) -> Result { + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); + + // SAFETY: It is safe to call + // [`devm_clk_get_optional_enabled_with_rate`] with a valid device + // pointer. + from_err_ptr(unsafe { + bindings::devm_clk_get_optional_enabled_with_rate(dev.as_raw(), name, rate.as_hz()) + })?; + Ok(()) + } + /// A trait representing the different states that a [`Clk`] can be in. pub trait ClkState: private::Sealed { /// Whether the clock should be disabled when dropped. -- 2.52.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v3 2/3] rust: clk: add devres-managed clks 2026-01-07 15:09 ` [PATCH v3 2/3] rust: clk: add devres-managed clks Daniel Almeida @ 2026-01-19 14:33 ` Gary Guo 0 siblings, 0 replies; 68+ messages in thread From: Gary Guo @ 2026-01-19 14:33 UTC (permalink / raw) To: Daniel Almeida, Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux On Wed Jan 7, 2026 at 3:09 PM GMT, Daniel Almeida wrote: > The clk API allows fine-grained control, but some drivers might be > more interested in a "set and forget" API. > > Expand the current API to support this. The clock will automatically be > disabled, unprepared and freed when the device is unbound from the bus > without further intervention by the driver. > > Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> > --- > rust/kernel/clk.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 43 insertions(+) > > diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs > index 6323b40dc7ba..e840e7c20af7 100644 > --- a/rust/kernel/clk.rs > +++ b/rust/kernel/clk.rs > @@ -95,6 +95,49 @@ impl Sealed for super::Prepared {} > impl Sealed for super::Enabled {} > } > > + /// Obtains and enables a [`devres`]-managed [`Clk`] for a bound device. > + /// > + /// [`devres`]: crate::devres::Devres > + pub fn devm_enable(dev: &Device<Bound>, name: Option<&CStr>) -> Result { > + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); > + > + // SAFETY: It is safe to call [`devm_clk_get_enabled`] with a valid > + // device pointer. > + from_err_ptr(unsafe { bindings::devm_clk_get_enabled(dev.as_raw(), name) })?; > + Ok(()) > + } Would it make sense to have them as assoc functions instead of standalone? Regardless, the code looks correct to me. Reviewed-by: Gary Guo <gary@garyguo.net> Best, Gary > + > + /// Obtains and enables a [`devres`]-managed [`Clk`] for a bound device. > + /// > + /// This does not print any error messages if the clock is not found. > + /// > + /// [`devres`]: crate::devres::Devres > + pub fn devm_enable_optional(dev: &Device<Bound>, name: Option<&CStr>) -> Result { > + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); > + > + // SAFETY: It is safe to call [`devm_clk_get_optional_enabled`] with a > + // valid device pointer. > + from_err_ptr(unsafe { bindings::devm_clk_get_optional_enabled(dev.as_raw(), name) })?; > + Ok(()) > + } > + > + /// Same as [`devm_enable_optional`], but also sets the rate. > + pub fn devm_enable_optional_with_rate( > + dev: &Device, > + name: Option<&CStr>, > + rate: Hertz, > + ) -> Result { > + let name = name.map_or(ptr::null(), |n| n.as_char_ptr()); > + > + // SAFETY: It is safe to call > + // [`devm_clk_get_optional_enabled_with_rate`] with a valid device > + // pointer. > + from_err_ptr(unsafe { > + bindings::devm_clk_get_optional_enabled_with_rate(dev.as_raw(), name, rate.as_hz()) > + })?; > + Ok(()) > + } > + > /// A trait representing the different states that a [`Clk`] can be in. > pub trait ClkState: private::Sealed { > /// Whether the clock should be disabled when dropped. ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports 2026-01-07 15:09 [PATCH v3 0/3] Clk improvements Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 2/3] rust: clk: add devres-managed clks Daniel Almeida @ 2026-01-07 15:09 ` Daniel Almeida 2026-01-08 7:53 ` Maxime Ripard 2 siblings, 1 reply; 68+ messages in thread From: Daniel Almeida @ 2026-01-07 15:09 UTC (permalink / raw) To: Rafael J. Wysocki, Viresh Kumar, Danilo Krummrich, Alice Ryhl, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Drew Fustini, Guo Ren, Fu Wei, Uwe Kleine-König, Michael Turquette, Stephen Boyd, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Trevor Gross Cc: linux-pm, linux-kernel, dri-devel, linux-riscv, linux-pwm, linux-clk, rust-for-linux, Daniel Almeida Convert all imports to use the new import style. This will make it easier to land new changes in the future. No change of functionality implied. Link: https://docs.kernel.org/rust/coding-guidelines.html#imports Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> --- rust/kernel/clk.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index e840e7c20af7..73a2b51414a1 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -80,12 +80,23 @@ fn from(freq: Hertz) -> Self { mod common_clk { use super::Hertz; use crate::{ - device::{Bound, Device}, - error::{from_err_ptr, to_result, Result}, - prelude::*, + device::{ + Bound, + Device, // + }, + error::{ + from_err_ptr, + to_result, + Result, // + }, + prelude::*, // }; - use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; + use core::{ + marker::PhantomData, + mem::ManuallyDrop, + ptr, // + }; mod private { pub trait Sealed {} @@ -216,8 +227,17 @@ pub struct Error<State: ClkState> { /// /// ``` /// use kernel::c_str; - /// use kernel::clk::{Clk, Enabled, Hertz, Unprepared, Prepared}; - /// use kernel::device::{Bound, Device}; + /// use kernel::clk::{ + /// Clk, + /// Enabled, + /// Hertz, + /// Prepared, + /// Unprepared, // + /// }; + /// use kernel::device::{ + /// Bound, + /// Device, // + /// }; /// use kernel::error::Result; /// /// fn configure_clk(dev: &Device<Bound>) -> Result { -- 2.52.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports 2026-01-07 15:09 ` [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports Daniel Almeida @ 2026-01-08 7:53 ` Maxime Ripard 0 siblings, 0 replies; 68+ messages in thread From: Maxime Ripard @ 2026-01-08 7:53 UTC (permalink / raw) To: Daniel Almeida Cc: dri-devel, linux-clk, linux-kernel, linux-pm, linux-pwm, linux-riscv, rust-for-linux, Alice Ryhl, Andreas Hindborg, Benno Lossin, Björn Roy Baron, Boqun Feng, Danilo Krummrich, David Airlie, Drew Fustini, Fu Wei, Gary Guo, Guo Ren, Maarten Lankhorst, Maxime Ripard, Michael Turquette, Miguel Ojeda, "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"Rafael J. Wysocki\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"", Simona Vetter, Stephen Boyd, Thomas Zimmermann, Trevor Gross, Uwe Kleine-König, Viresh Kumar On Wed, 7 Jan 2026 12:09:54 -0300, Daniel Almeida wrote: > Convert all imports to use the new import style. This will make it easier > to land new changes in the future. > > No change of functionality implied. > > > [ ... ] Reviewed-by: Maxime Ripard <mripard@kernel.org> Thanks! Maxime ^ permalink raw reply [flat|nested] 68+ messages in thread
end of thread, other threads:[~2026-02-12 16:50 UTC | newest] Thread overview: 68+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-07 15:09 [PATCH v3 0/3] Clk improvements Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 1/3] rust: clk: use the type-state pattern Daniel Almeida 2026-01-08 8:07 ` Maxime Ripard 2026-01-08 13:57 ` Miguel Ojeda 2026-01-08 14:18 ` Daniel Almeida 2026-01-08 14:14 ` Daniel Almeida 2026-01-19 10:45 ` Maxime Ripard 2026-01-19 12:13 ` Daniel Almeida 2026-01-19 12:35 ` Alice Ryhl 2026-01-19 12:54 ` Daniel Almeida 2026-01-19 13:13 ` Danilo Krummrich 2026-01-19 14:18 ` Maxime Ripard 2026-01-19 14:37 ` Danilo Krummrich 2026-01-22 13:44 ` Maxime Ripard 2026-01-23 0:29 ` Daniel Almeida 2026-02-04 9:15 ` Maxime Ripard 2026-02-04 12:43 ` Daniel Almeida 2026-02-04 14:34 ` Maxime Ripard 2026-02-09 9:50 ` Boris Brezillon 2026-02-11 16:37 ` Maxime Ripard 2026-02-11 16:47 ` Danilo Krummrich 2026-02-12 7:59 ` Maxime Ripard 2026-02-12 8:52 ` Alice Ryhl 2026-02-12 9:23 ` Danilo Krummrich 2026-02-12 14:01 ` Danilo Krummrich 2026-02-12 16:50 ` Maxime Ripard 2026-02-12 11:45 ` Miguel Ojeda 2026-02-12 8:16 ` Alice Ryhl 2026-02-12 13:38 ` Maxime Ripard 2026-02-12 14:02 ` Alice Ryhl 2026-02-12 16:48 ` Maxime Ripard 2026-01-23 10:25 ` Danilo Krummrich 2026-01-19 12:57 ` Gary Guo 2026-01-19 14:27 ` Maxime Ripard 2026-02-03 10:39 ` Boris Brezillon 2026-02-03 11:26 ` Boris Brezillon 2026-02-03 14:53 ` Boris Brezillon 2026-02-03 13:33 ` Daniel Almeida 2026-02-03 13:42 ` Gary Guo 2026-02-03 13:55 ` Daniel Almeida 2026-02-03 14:33 ` Boris Brezillon 2026-02-03 14:08 ` Boris Brezillon 2026-02-03 16:28 ` Daniel Almeida 2026-02-03 16:55 ` Boris Brezillon 2026-02-03 16:59 ` Gary Guo 2026-02-03 19:26 ` Daniel Almeida 2026-02-03 19:43 ` Boris Brezillon 2026-02-03 20:36 ` Gary Guo 2026-02-04 8:11 ` Boris Brezillon 2026-02-04 9:18 ` Maxime Ripard 2026-01-19 14:26 ` Gary Guo 2026-01-19 15:44 ` Daniel Almeida 2026-01-19 14:20 ` Gary Guo 2026-01-19 15:22 ` Miguel Ojeda 2026-01-19 15:36 ` Gary Guo 2026-01-19 15:46 ` Miguel Ojeda 2026-01-19 16:10 ` Gary Guo 2026-02-02 16:10 ` Boris Brezillon 2026-02-03 9:09 ` Boris Brezillon 2026-02-03 9:47 ` Boris Brezillon 2026-02-03 13:37 ` Daniel Almeida 2026-02-03 14:18 ` Boris Brezillon 2026-02-03 9:17 ` Boris Brezillon 2026-02-03 13:35 ` Daniel Almeida 2026-01-07 15:09 ` [PATCH v3 2/3] rust: clk: add devres-managed clks Daniel Almeida 2026-01-19 14:33 ` Gary Guo 2026-01-07 15:09 ` [PATCH v3 3/3] rust: clk: use 'kernel vertical style' for imports Daniel Almeida 2026-01-08 7:53 ` Maxime Ripard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox