From: "Benno Lossin" <lossin@kernel.org>
To: "Alexandre Courbot" <acourbot@nvidia.com>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Boris Brezillon" <boris.brezillon@collabora.com>,
"Sebastian Reichel" <sebastian.reichel@collabora.com>,
"Liam Girdwood" <lgirdwood@gmail.com>,
"Mark Brown" <broonie@kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <rust-for-linux@vger.kernel.org>
Subject: Re: [PATCH v3] rust: regulator: add a bare minimum regulator abstraction
Date: Sun, 18 May 2025 11:57:11 +0200 [thread overview]
Message-ID: <D9Z73XZUSYWO.R0P38ASITWR7@kernel.org> (raw)
In-Reply-To: <D9Z59JWL4BTC.3DTN0LWCJX5AZ@nvidia.com>
On Sun May 18, 2025 at 10:30 AM CEST, Alexandre Courbot wrote:
> On Sun May 18, 2025 at 5:14 PM JST, Alexandre Courbot wrote:
>> On Sun May 18, 2025 at 4:19 PM JST, Benno Lossin wrote:
>>> On Sun May 18, 2025 at 4:28 AM CEST, Alexandre Courbot wrote:
>>>> On Wed May 14, 2025 at 12:44 AM JST, Daniel Almeida wrote:
>>>>> +//! Regulator abstractions, providing a standard kernel interface to control
>>>>> +//! voltage and current regulators.
>>>>> +//!
>>>>> +//! The intention is to allow systems to dynamically control regulator power
>>>>> +//! output in order to save power and prolong battery life. This applies to both
>>>>> +//! voltage regulators (where voltage output is controllable) and current sinks
>>>>> +//! (where current limit is controllable).
>>>>> +//!
>>>>> +//! C header: [`include/linux/regulator/consumer.h`](srctree/include/linux/regulator/consumer.h)
>>>>> +//!
>>>>> +//! Regulators are modeled in Rust with two types: [`Regulator`] and
>>>>> +//! [`EnabledRegulator`].
>>>>> +//!
>>>>> +//! The transition between these types is done by calling
>>>>> +//! [`Regulator::enable()`] and [`EnabledRegulator::disable()`] respectively.
>>>>> +//!
>>>>> +//! Use an enum or [`kernel::types::Either`] to gracefully transition between
>>>>> +//! the two states at runtime if needed. Store [`EnabledRegulator`] directly
>>>>> +//! otherwise.
>>>>
>>>> Having the enabled or disabled state baked into the type is indeed
>>>> valuable for drivers that just need to acquire and enable a regulator at
>>>> probe time. However, there are also more dynamic use cases and I don't
>>>> think the burden of managing this aspect - by either performing a manual
>>>> match to call any method (even the shared ones), or implementing custom
>>>> dispatch types (which will lead to many similar ad-hoc implementations)
>>>> - should fall on the user. Thus I strongly suggest that this module
>>>> provides a solution for this as well.
>>>>
>>>> It has been proposed earlier to use a typestate, and this would indeed
>>>> provide several benefits, the first one being the ability to have shared
>>>> impl blocks (and shared documentation) between the enabled and disabled
>>>> states for methods like set/get_voltage().
>>>>
>>>> But the key benefit I see is that it could also address the
>>>> aforementioned dynamic management problem through the introduction of a
>>>> third state.
>>>>
>>>> Alongside the `Enabled` and `Disabled` states, there would be a third
>>>> state (`Dynamic`?) in which the regulator could either be enabled or
>>>> disabled. This `Dynamic` state is the only one providing `enable` and
>>>> `disable` methods (as well as `is_enabled`) to change its operational
>>>> state without affecting its type.
>>>>
>>>> All three states then implement `set_voltage` and `get_voltage` through
>>>> a common impl block, that could be extended with other methods from the
>>>> C API that are independent of the state, as needed.
>>>>
>>>> To handle typestate transitions:
>>>>
>>>> - The `Disabled` and `Dynamic` states provide a `try_into_enabled()`
>>>> method to transition the regulator to the `Enabled` state.
>>>> - The `Enabled` and `Dynamic` states provide `try_into_disabled()`.
>>>> - `Enabled` and `Disabled` also provide `into_dynamic()` (which cannot
>>>> fail).
>>>>
>>>> Essentially, the `Enabled` and `Disabled` states simply enforce an
>>>> additional operational state invariant on the underlying regulator, and
>>>> do not provide methods to change it.
>>>>
>>>> The `Dynamic` state would be the default for `Regulator`, so by just
>>>> using `Regulator`, the user gets an interface that works very similarly
>>>> to the C API it abstracts, making it intuitive to those familiar with
>>>> it.
>>>
>>> How will the `Dynamic` typestate track the enable refcount? AFAIK one
>>> has to drop all enable refcounts before removing the regulator.
>>
>> I guess a choice has to be made about whether to just proxy the C API
>> as-is (where an unbalanced number of enable/disable calls can result in
>> a dropped regulator still being enabled), or whether to clamp the number
>> of times a Rust consumer can enable a regulator to 0 and 1 and disable
>> an enabled regulator in the destructor.
>>
>> The initial proposal does such clamping by design, but I also suspect
>> the C API behave like it does for good reasons (which I am not familiar
>> enough to be aware of unfortunately).
>
> Well after thinking a bit more about it, it is clear that is does that
> because a single consumer may need to ensure a regulator is on across
> multiple internal states. I suspect we will have Rust drivers complex
> enough to benefit from this behavior sometime soon.
>
> So I'd say the `Dynamic` state should probably mirror the C API as
> closely as possible and not try to outsmart the user. The
> `Enabled`/`Disabled` typestates will cover the simpler use-cases
> perfectly well and ensure a well-controlled enable count.
So just let users ensure that they always match each `enable` call with
a `disable` call in the `Dynamic` typestate?
That is ok, if no memory issues can arise from forgetting to do so,
otherwise those functions need to be `unsafe`. Also we should clearly
document that the `Enabled`/`Disabled` typestates should be preferred if
possible.
---
Cheers,
Benno
> I guess this also means transitions to/from `Dynamic` and the other
> states will have to be limited to the ones where we can clearly infer
> the enable count. That's probably ok anyway because I can't think of a
> reason to switch from one pattern to the other for the same regulator.
> Maybe we don't even need these transitions at all?
next prev parent reply other threads:[~2025-05-18 9:57 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-13 15:44 [PATCH v3] rust: regulator: add a bare minimum regulator abstraction Daniel Almeida
2025-05-13 20:01 ` Benno Lossin
2025-05-14 7:46 ` Mark Brown
2025-05-14 9:37 ` Benno Lossin
2025-05-14 10:16 ` Mark Brown
2025-05-14 10:31 ` Benno Lossin
2025-05-14 11:50 ` Mark Brown
2025-05-14 12:23 ` Benno Lossin
2025-05-14 12:48 ` Mark Brown
2025-05-14 14:06 ` Benno Lossin
2025-05-14 13:01 ` Daniel Almeida
2025-05-14 13:57 ` Benno Lossin
2025-05-14 14:40 ` Daniel Almeida
2025-05-14 15:38 ` Benno Lossin
2025-05-14 15:50 ` Mark Brown
2025-05-14 16:05 ` Benno Lossin
2025-05-14 16:08 ` Mark Brown
2025-05-14 16:19 ` Daniel Almeida
2025-05-14 17:41 ` Benno Lossin
2025-05-14 16:10 ` Daniel Almeida
2025-05-15 8:19 ` Mark Brown
2025-05-14 15:48 ` Mark Brown
2025-05-14 8:27 ` Mark Brown
2025-05-18 2:28 ` Alexandre Courbot
2025-05-18 7:19 ` Benno Lossin
2025-05-18 8:14 ` Alexandre Courbot
2025-05-18 8:30 ` Alexandre Courbot
2025-05-18 9:57 ` Benno Lossin [this message]
2025-05-18 11:12 ` Alexandre Courbot
2025-05-18 14:05 ` Benno Lossin
2025-05-19 0:29 ` Alexandre Courbot
2025-05-18 12:20 ` Mark Brown
2025-05-18 12:51 ` Alexandre Courbot
2025-05-19 9:55 ` Mark Brown
2025-05-18 14:04 ` Benno Lossin
2025-05-19 9:56 ` Mark Brown
2025-05-19 11:25 ` Benno Lossin
2025-05-19 11:46 ` Mark Brown
2025-05-19 12:30 ` Benno Lossin
2025-05-19 12:46 ` Mark Brown
2025-05-18 12:17 ` Mark Brown
2025-05-18 12:49 ` Alexandre Courbot
2025-05-19 9:54 ` Mark Brown
2025-05-18 15:11 ` Daniel Almeida
2025-05-19 1:25 ` Alexandre Courbot
2025-05-19 10:52 ` Daniel Almeida
2025-05-19 11:01 ` Daniel Almeida
2025-05-19 11:54 ` Benno Lossin
2025-05-19 11:59 ` Miguel Ojeda
2025-05-19 14:43 ` Alexandre Courbot
2025-05-20 18:09 ` Benno Lossin
2025-05-19 14:20 ` Alexandre Courbot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=D9Z73XZUSYWO.R0P38ASITWR7@kernel.org \
--to=lossin@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=broonie@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sebastian.reichel@collabora.com \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.