mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Almeida <daniel.almeida@collabora.com>
To: Mark Brown <broonie@kernel.org>
Cc: lgirdwood@gmail.com, sebastian.reichel@collabora.com,
	sjoerd.simons@collabora.co.uk, ojeda@kernel.org,
	alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net,
	bjorn3_gh@protonmail.com, a.hindborg@kernel.org,
	benno.lossin@proton.me, aliceryhl@google.com, tmgross@umich.edu,
	dakr@kernel.org, rust-for-linux@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] rust: regulator: add a bare minimum regulator abstraction
Date: Wed, 19 Feb 2025 20:35:47 -0300	[thread overview]
Message-ID: <5E354BB7-9CD5-4615-8EAF-98B9F498713A@collabora.com> (raw)
In-Reply-To: <Z7ZjzJ2Rfrt8j0s1@finisterre.sirena.org.uk>

Hi Mark,

> On 19 Feb 2025, at 20:05, Mark Brown <broonie@kernel.org> wrote:
> 
> On Wed, Feb 19, 2025 at 01:25:16PM -0300, Daniel Almeida wrote:
> 
>> Add a bare minimum regulator abstraction to be used by Rust drivers.
>> This abstraction adds a small subset of the regulator API, which is
>> thought to be sufficient for the drivers we have now.
> 
> ...
> 
>> Note that each instance of [`Regulator`] obtained from
>> `Regulator::get()` can only be enabled once. This ensures that the calls
>> to enable and disable are perfectly balanced before `regulator_put()` is
>> called, as mandated by the C API.
> 
> This sounds very wrong, a major use case for consumers is to enable and
> disable regulators at runtime.  I would expect that the Rust code might
> want to have it's own reference counting (and probably should), but not
> being able to disable a regulator after enabling it seems to be a great
> big red flag.
> 
>> +    /// Enable the regulator.
>> +    pub fn enable(&mut self) -> Result {
>> +        if self.enabled {
>> +            return Ok(());
>> +        }
> 
> This isn't what the changelog claimed, it's silently ignoring duplicate
> attempts to enable and...
> 
>> +        // SAFETY: Safe as per the type invariants of `Regulator`.
>> +        let res = to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) });
>> +        if res.is_ok() {
>> +            self.enabled = false;
>> +        }
> 
> ...we actually support disabling and reenabling multiple times, it's
> just that there's a maximum of one enable at once from the consumer and
> we silently ignore duplicated enables and disables.  That's better but
> it's asking for trouble.

Maybe there was a language issue on my end here.

When I say once, I mean exactly what the source code shows, i.e.: it can be
enabled once, and further calls will be ignored. If it is disabled, it can then be
enabled once, with all further calls ignored, etc.

What I wanted to say is that this abstraction does not support exactly what you
suggested, i.e.: a refcount of how many times it was enabled.

I agree that this is not what the word “once” means. Sorry for the confusion.

> 
> If you're going to support both enable and disable (and all things
> considered you probably should TBH) it would be better to just reference
> count the enables like the C code does and then complain about it if
> someone tries to free the regulator object without underwinding their
> enables, or just possibly just clean them up.  Silently ignoring
> duplicate enables or overflowing disables doesn't seem like it plays
> well with the safety goals that Rust has, it's asking for bugs - a big
> part of the reason the C API does things the way it does is that it will
> notice if the enables and disables aren't joined up.  You can easily
> wind up with one part of the code disabling the regulator underneath
> another part that's still trying to use the hardware and things tend not
> to go well when that happens.

I thought about that, something like:

```
  fn drop(&mut self) {

   // someone probably forgot to call disable?
    while self.enabled_count > 0 {

            // Try to disable, this will decrement self.enabled_count
            if let Err(e) = self.disable() {

              // But don’t loop forever if it fails
              break;
            }
        }
  }
```

I asked for a few opinions privately and was told that “if the C API prefers not to do that
why should you?”

> 
> Perhaps an enable should be an object that's allocated and carried about
> by whatever's holding the reference, I don't know if that plays nicely
> with how Rust likes to ensure safety with this stuff?

As I said, this doesn’t work very well, unless someone corrects my reasoning on a
previous email. Having a single type “Regulator” is probably much saner than “Regulator”
and “EnabledRegulator”.

Your “refcount” idea works just fine, though. I’ll send a v2.

— Daniel

  reply	other threads:[~2025-02-19 23:36 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-19 16:25 Daniel Almeida
2025-02-19 16:28 ` Alice Ryhl
2025-02-19 17:10   ` Daniel Almeida
2025-02-20 12:09     ` Mark Brown
2025-02-20 13:48       ` Daniel Almeida
2025-02-20 14:14         ` Mark Brown
2025-02-23  7:58     ` Boqun Feng
2025-03-04 15:36     ` Alice Ryhl
2025-02-19 23:05 ` Mark Brown
2025-02-19 23:35   ` Daniel Almeida [this message]
2025-02-20  1:37     ` Mark Brown
2025-02-20  9:42       ` Daniel Almeida
2025-02-20 11:58         ` Mark Brown

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=5E354BB7-9CD5-4615-8EAF-98B9F498713A@collabora.com \
    --to=daniel.almeida@collabora.com \
    --cc=a.hindborg@kernel.org \
    --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=broonie@kernel.org \
    --cc=dakr@kernel.org \
    --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=sjoerd.simons@collabora.co.uk \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®