mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michal Wilczynski <m.wilczynski@samsung.com>
To: Danilo Krummrich <dakr@kernel.org>
Cc: "Uwe Kleine-König" <ukleinek@kernel.org>,
	"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>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>, "Guo Ren" <guoren@kernel.org>,
	"Fu Wei" <wefu@redhat.com>, "Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Alexandre Ghiti" <alex@ghiti.fr>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Michael Turquette" <mturquette@baylibre.com>,
	"Drew Fustini" <fustini@kernel.org>,
	linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org,
	rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org,
	devicetree@vger.kernel.org
Subject: Re: [PATCH v9 2/6] rust: pwm: Add complete abstraction layer
Date: Mon, 7 Jul 2025 09:30:17 +0200	[thread overview]
Message-ID: <002c8275-f17d-4a4e-b6b8-4dc74c4d510d@samsung.com> (raw)
In-Reply-To: <aGpqqGMTU3a3O8cn@pollux>



On 7/6/25 14:23, Danilo Krummrich wrote:
> On Sun, Jul 06, 2025 at 01:45:13PM +0200, Michal Wilczynski wrote:
>> +/// Trait defining the operations for a PWM driver.
>> +pub trait PwmOps: 'static + Sized {
>> +    /// The type of the owned driver data (e.g., `Pin<KBox<...>>`).
>> +    type DrvData: 'static + ForeignOwnable;
>> +    /// The driver-specific hardware representation of a waveform.
>> +    ///
>> +    /// This type must be [`Copy`], [`Default`], and fit within `PWM_WFHWSIZE`.
>> +    type WfHw: Copy + Default;
>> +
>> +    /// Optional hook for when a PWM device is requested.
>> +    fn request(
>> +        _chip: &Chip<Self::DrvData>,
>> +        _pwm: &Device,
>> +        _parent_dev: &device::Device<Bound>,
>> +    ) -> Result {
>> +        Ok(())
>> +    }
>> +
>> +    /// Optional hook for when a PWM device is freed.
>> +    fn free(_chip: &Chip<Self::DrvData>, _pwm: &Device, _parent_dev: &device::Device<Bound>) {}
> 
> NIT: I can't think of a case providing this callback in Rust is useful. Do you
> have a clear use-case in mind? Otherwise, I'd not provide this callback until
> you have one. Should be trivial to add later on.
> 
>> +impl<T: PwmOps> Adapter<T> {
> 
> <snip>
> 
>> +    /// # Safety
>> +    ///
>> +    /// `dev` must be a valid pointer to a `bindings::device` embedded within a
>> +    /// `bindings::pwm_chip`. This function is called by the device core when the
>> +    /// last reference to the device is dropped.
>> +    unsafe extern "C" fn release_callback(dev: *mut bindings::device) {
>> +        // SAFETY: The function's contract guarantees that `dev` points to a `device`
>> +        // field embedded within a valid `pwm_chip`. `container_of!` can therefore
>> +        // safely calculate the address of the containing struct.
>> +        let c_chip_ptr = unsafe { container_of!(dev, bindings::pwm_chip, dev) };
>> +
>> +        // SAFETY: `c_chip_ptr` is a valid pointer to a `pwm_chip` as established
>> +        // above. Calling this FFI function is safe.
>> +        let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) };
>> +
>> +        if !drvdata_ptr.is_null() {
> 
> Is this check needed? I think one can't create a pwm::Chip instance without
> providing a T, so this pointer can't be NULL I think.
> 
>> +            // SAFETY: `drvdata_ptr` was stored by `Chip::new` from an owned `T::DrvData`
>> +            // and is guaranteed to be valid if non-null. `from_foreign` can safely
>> +            // reclaim ownership to allow Rust to drop and free the data.
>> +            let _owned_drvdata = unsafe { T::DrvData::from_foreign(drvdata_ptr.cast()) };
>> +        }
>> +    }
> 
> If you overwrite this callback (as you do below) you're leaking the memory
> allocated by pwmchip_alloc().
> 
> The simple way to solve this would be to call pwmchip_release() from here.

Thanks, a pwmchip_release() is static though, so it's either expose the
pwmchip_release in the header, or call kfree() here directly on pwmchip.

> 
> <snip>
> 
>> +impl<T: 'static + ForeignOwnable> Chip<T> {
>> +    /// Allocates and wraps a PWM chip using `bindings::pwmchip_alloc`.
>> +    ///
>> +    /// Returns an [`ARef<Chip>`] managing the chip's lifetime via refcounting
>> +    /// on its embedded `struct device`.
>> +    pub fn new<O: PwmOps<DrvData = T>>(
>> +        parent_dev: &device::Device,
>> +        npwm: u32,
>> +        sizeof_priv: usize,
>> +        drvdata: T,
>> +    ) -> Result<ARef<Self>> {
>> +        // SAFETY: `parent_device_for_dev_field.as_raw()` is valid.
>> +        // `bindings::pwmchip_alloc` returns a valid `*mut bindings::pwm_chip` (refcount 1)
>> +        // or an ERR_PTR.
>> +        let c_chip_ptr_raw =
>> +            unsafe { bindings::pwmchip_alloc(parent_dev.as_raw(), npwm, sizeof_priv) };
>> +
>> +        let c_chip_ptr: *mut bindings::pwm_chip = error::from_err_ptr(c_chip_ptr_raw)?;
>> +
>> +        // Set the custom release function on the embedded device. This is the crucial step
>> +        // to ensure `drvdata` is freed when the chip's refcount reaches zero, regardless
>> +        // of whether `Registration::register` was called.
>> +        // SAFETY: `c_chip_ptr` points to a valid chip.
>> +        unsafe { (*c_chip_ptr).dev.release = Some(Adapter::<O>::release_callback); }
> 
> This overwrites [1].
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pwm/core.c?h=v6.16-rc4#n1601
> 

Best regards,
-- 
Michal Wilczynski <m.wilczynski@samsung.com>

  parent reply	other threads:[~2025-07-07  7:30 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20250706114603eucas1p1f2a37072bdbcaa771ba8d822463bf420@eucas1p1.samsung.com>
2025-07-06 11:45 ` [PATCH v9 0/6] Rust Abstractions for PWM subsystem with TH1520 PWM driver Michal Wilczynski
     [not found]   ` <CGME20250706114604eucas1p260108a0f45a8273ae98afe05cc9a1288@eucas1p2.samsung.com>
2025-07-06 11:45     ` [PATCH v9 1/6] rust: pwm: Add Kconfig and basic data structures Michal Wilczynski
     [not found]   ` <CGME20250706114605eucas1p17d1cbd035d14d95f4ad0588c2572b3e2@eucas1p1.samsung.com>
2025-07-06 11:45     ` [PATCH v9 2/6] rust: pwm: Add complete abstraction layer Michal Wilczynski
2025-07-06 12:23       ` Danilo Krummrich
2025-07-07  6:57         ` Uwe Kleine-König
2025-07-07  8:12           ` Michal Wilczynski
2025-07-07  7:30         ` Michal Wilczynski [this message]
2025-07-07  9:15           ` Danilo Krummrich
     [not found]   ` <CGME20250706114606eucas1p12c2d4b4907b309f0d2f7e00828f22ea2@eucas1p1.samsung.com>
2025-07-06 11:45     ` [PATCH v9 3/6] pwm: Add Rust driver for T-HEAD TH1520 SoC Michal Wilczynski
     [not found]   ` <CGME20250706114607eucas1p11b4b9f4ae851d9c251959ef2685eef88@eucas1p1.samsung.com>
2025-07-06 11:45     ` [PATCH v9 4/6] dt-bindings: pwm: thead: Add T-HEAD TH1520 PWM controller Michal Wilczynski
     [not found]   ` <CGME20250706114609eucas1p18598ba94ded6b6ea1664aa8deb552138@eucas1p1.samsung.com>
2025-07-06 11:45     ` [PATCH v9 5/6] riscv: dts: thead: Add PWM controller node Michal Wilczynski
     [not found]   ` <CGME20250706114610eucas1p151c3d14e5626fca708983cb98f22d670@eucas1p1.samsung.com>
2025-07-06 11:45     ` [PATCH v9 6/6] riscv: dts: thead: Add PWM fan and thermal control Michal Wilczynski

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=002c8275-f17d-4a4e-b6b8-4dc74c4d510d@samsung.com \
    --to=m.wilczynski@samsung.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=alex@ghiti.fr \
    --cc=aliceryhl@google.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=dakr@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=fustini@kernel.org \
    --cc=gary@garyguo.net \
    --cc=guoren@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=lossin@kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=mturquette@baylibre.com \
    --cc=ojeda@kernel.org \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=robh@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=ukleinek@kernel.org \
    --cc=wefu@redhat.com \
    /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®