linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg KH <gregkh@linuxfoundation.org>
To: Danilo Krummrich <dakr@redhat.com>
Cc: rafael@kernel.org, bhelgaas@google.com, ojeda@kernel.org,
	alex.gaynor@gmail.com, wedsonaf@gmail.com, boqun.feng@gmail.com,
	gary@garyguo.net, bjorn3_gh@protonmail.com,
	benno.lossin@proton.me, a.hindborg@samsung.com,
	aliceryhl@google.com, airlied@gmail.com,
	fujita.tomonori@gmail.com, lina@asahilina.net,
	pstanner@redhat.com, ajanulgu@redhat.com, lyude@redhat.com,
	robh@kernel.org, daniel.almeida@collabora.com,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-pci@vger.kernel.org
Subject: Re: [PATCH v2 02/10] rust: implement generic driver registration
Date: Thu, 20 Jun 2024 16:28:23 +0200	[thread overview]
Message-ID: <2024062025-wrecking-utilize-30cf@gregkh> (raw)
In-Reply-To: <20240618234025.15036-3-dakr@redhat.com>

On Wed, Jun 19, 2024 at 01:39:48AM +0200, Danilo Krummrich wrote:
> Implement the generic `Registration` type and the `DriverOps` trait.

I don't think this is needed, more below...

> The `Registration` structure is the common type that represents a driver
> registration and is typically bound to the lifetime of a module. However,
> it doesn't implement actual calls to the kernel's driver core to register
> drivers itself.

But that's not what normally happens, more below...

> Instead the `DriverOps` trait is provided to subsystems, which have to
> implement `DriverOps::register` and `DrvierOps::unregister`. Subsystems
> have to provide an implementation for both of those methods where the
> subsystem specific variants to register / unregister a driver have to
> implemented.

So you are saying this should be something that a "bus" would do?
Please be explicit as to what you mean by "subsystem" here.

> For instance, the PCI subsystem would call __pci_register_driver() from
> `DriverOps::register` and pci_unregister_driver() from
> `DrvierOps::unregister`.

So this is a BusOps, or more in general, a "subsystem" if it's not a
bus (i.e. it's a class).  Note, we used to use the term "subsystem" a
very long time ago but got rid of them in the driver core, let's not
bring it back unless we REALLY know we want it this time.

So why isn't this just a BusOps?
> This patch is based on previous work from Wedson Almeida Filho.
> 
> Co-developed-by: Wedson Almeida Filho <wedsonaf@gmail.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
> Signed-off-by: Danilo Krummrich <dakr@redhat.com>
> ---
>  rust/kernel/driver.rs | 128 ++++++++++++++++++++++++++++++++++++++++++
>  rust/kernel/lib.rs    |   1 +
>  2 files changed, 129 insertions(+)
>  create mode 100644 rust/kernel/driver.rs
> 
> diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
> new file mode 100644
> index 000000000000..e04406b93b56
> --- /dev/null
> +++ b/rust/kernel/driver.rs
> @@ -0,0 +1,128 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).

See, you think it's a bus, let's call it a bus!  :)

> +//!
> +//! Each bus / subsystem is expected to implement [`DriverOps`], which allows drivers to register
> +//! using the [`Registration`] class.
> +
> +use crate::error::{Error, Result};
> +use crate::{init::PinInit, str::CStr, try_pin_init, types::Opaque, ThisModule};
> +use core::pin::Pin;
> +use macros::{pin_data, pinned_drop};
> +
> +/// The [`DriverOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform, Amba,
> +/// etc.) to privide the corresponding subsystem specific implementation to register / unregister a
> +/// driver of the particular type (`RegType`).
> +///
> +/// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call
> +/// `bindings::__pci_register_driver` from `DriverOps::register` and
> +/// `bindings::pci_unregister_driver` from `DriverOps::unregister`.
> +pub trait DriverOps {
> +    /// The type that holds information about the registration. This is typically a struct defined
> +    /// by the C portion of the kernel.
> +    type RegType: Default;
> +
> +    /// Registers a driver.
> +    ///
> +    /// # Safety
> +    ///
> +    /// `reg` must point to valid, initialised, and writable memory. It may be modified by this
> +    /// function to hold registration state.
> +    ///
> +    /// On success, `reg` must remain pinned and valid until the matching call to
> +    /// [`DriverOps::unregister`].
> +    fn register(
> +        reg: &mut Self::RegType,
> +        name: &'static CStr,
> +        module: &'static ThisModule,
> +    ) -> Result;
> +
> +    /// Unregisters a driver previously registered with [`DriverOps::register`].
> +    ///
> +    /// # Safety
> +    ///
> +    /// `reg` must point to valid writable memory, initialised by a previous successful call to
> +    /// [`DriverOps::register`].
> +    fn unregister(reg: &mut Self::RegType);
> +}

So you are getting into what a bus wants/needs to support here, why is
register/unregister the "big" things to be implemented first?  Why not
just map the current register/unregister bus functions to a bus-specific
trait for now?  And then, if you think it really should be generic, we
can make it that way then.  I don't see why this needs to be generic now
as you aren't implementing a bus in rust at this point in time, right?

> +
> +/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
> +/// `bindings::pci_driver`). Therefore a [`Registration`] is initialized with some type that
> +/// implements the [`DriverOps`] trait, such that the generic `T::register` and `T::unregister`
> +/// calls result in the subsystem specific registration calls.
> +///
> +///Once the `Registration` structure is dropped, the driver is unregistered.
> +#[pin_data(PinnedDrop)]
> +pub struct Registration<T: DriverOps> {
> +    #[pin]
> +    reg: Opaque<T::RegType>,
> +}
> +
> +// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
> +// share references to it with multiple threads as nothing can be done.
> +unsafe impl<T: DriverOps> Sync for Registration<T> {}
> +
> +// SAFETY: Both registration and unregistration are implemented in C and safe to be performed from
> +// any thread, so `Registration` is `Send`.
> +unsafe impl<T: DriverOps> Send for Registration<T> {}
> +
> +impl<T: DriverOps> Registration<T> {
> +    /// Creates a new instance of the registration object.
> +    pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {

Drivers have modules, not busses.  So you are registering a driver with
a bus here, it's not something that a driver itself implements as you
have named here.


> +        try_pin_init!(Self {
> +            reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
> +                // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
> +                unsafe { ptr.write(T::RegType::default()) };
> +
> +                // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
> +                // just been initialised above, so it's also valid for read.
> +                let drv = unsafe { &mut *ptr };
> +
> +                T::register(drv, name, module)
> +            }),
> +        })
> +    }
> +}
> +
> +#[pinned_drop]
> +impl<T: DriverOps> PinnedDrop for Registration<T> {
> +    fn drop(self: Pin<&mut Self>) {
> +        let drv = unsafe { &mut *self.reg.get() };
> +
> +        T::unregister(drv);
> +    }
> +}
> +
> +/// A kernel module that only registers the given driver on init.
> +///
> +/// This is a helper struct to make it easier to define single-functionality modules, in this case,
> +/// modules that offer a single driver.
> +#[pin_data]
> +pub struct Module<T: DriverOps> {
> +    #[pin]
> +    _driver: Registration<T>,
> +}

While these are nice, let's not add them just yet, let's keep it simple
for now until we work out the proper model and see what is, and is not,
common for drivers to do.

That way we keep the review simpler as well, and saves you time
rewriting things as we rename / modify stuff.

> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -29,6 +29,7 @@
>  pub mod alloc;
>  mod build_assert;
>  pub mod device;
> +pub mod driver;

Nope, this is a bus :)

thanks,

greg k-h

  reply	other threads:[~2024-06-20 14:28 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-18 23:39 [PATCH v2 00/10] Device / Driver and PCI Rust abstractions Danilo Krummrich
2024-06-18 23:39 ` [PATCH v2 01/10] rust: pass module name to `Module::init` Danilo Krummrich
2024-06-20 14:19   ` Greg KH
2024-06-20 16:10     ` Danilo Krummrich
2024-06-20 16:36       ` Greg KH
2024-06-20 21:24         ` Danilo Krummrich
2024-06-26 10:29           ` Danilo Krummrich
2024-06-27  7:33             ` Greg KH
2024-06-27  7:41               ` Danilo Krummrich
2024-07-09 10:15           ` Danilo Krummrich
2024-07-10 14:02           ` Greg KH
2024-07-11  2:06             ` Danilo Krummrich
2024-07-22 11:23               ` Danilo Krummrich
2024-07-22 11:35                 ` Greg KH
2024-08-02 12:06               ` Danilo Krummrich
2024-06-18 23:39 ` [PATCH v2 02/10] rust: implement generic driver registration Danilo Krummrich
2024-06-20 14:28   ` Greg KH [this message]
2024-06-20 17:12     ` Danilo Krummrich
2024-07-10 14:10       ` Greg KH
2024-07-11  2:06         ` Danilo Krummrich
2024-06-18 23:39 ` [PATCH v2 03/10] rust: implement `IdArray`, `IdTable` and `RawDeviceId` Danilo Krummrich
2024-06-20 14:31   ` Greg KH
2024-06-18 23:39 ` [PATCH v2 04/10] rust: add rcu abstraction Danilo Krummrich
2024-06-20 14:32   ` Greg KH
2024-06-18 23:39 ` [PATCH v2 05/10] rust: add `Revocable` type Danilo Krummrich
2024-06-20 14:38   ` Greg KH
2024-06-18 23:39 ` [PATCH v2 06/10] rust: add `dev_*` print macros Danilo Krummrich
2024-06-20 14:42   ` Greg KH
2024-06-18 23:39 ` [PATCH v2 07/10] rust: add `io::Io` base type Danilo Krummrich
2024-06-20 14:53   ` Greg KH
2024-06-21  9:43     ` Philipp Stanner
2024-06-21 11:47       ` Danilo Krummrich
2024-06-25 10:59   ` Andreas Hindborg
2024-06-25 13:12     ` Danilo Krummrich
2024-08-24 19:47   ` Daniel Almeida
2024-06-18 23:39 ` [PATCH v2 08/10] rust: add devres abstraction Danilo Krummrich
2024-06-20 14:58   ` Greg KH
2024-06-18 23:39 ` [PATCH v2 09/10] rust: pci: add basic PCI device / driver abstractions Danilo Krummrich
2024-06-20 15:11   ` Greg KH
2024-06-25 10:53   ` Andreas Hindborg
2024-06-25 13:33     ` Danilo Krummrich
2024-06-18 23:39 ` [PATCH v2 10/10] rust: pci: implement I/O mappable `pci::Bar` Danilo Krummrich
2024-06-19 12:04 ` [PATCH v2 00/10] Device / Driver and PCI Rust abstractions Viresh Kumar
2024-06-19 12:17   ` Greg KH
2024-06-19 12:42     ` Danilo Krummrich
2024-06-19 12:36   ` Danilo Krummrich
2024-06-20 10:05     ` Viresh Kumar
2024-06-20 11:09       ` Danilo Krummrich

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=2024062025-wrecking-utilize-30cf@gregkh \
    --to=gregkh@linuxfoundation.org \
    --cc=a.hindborg@samsung.com \
    --cc=airlied@gmail.com \
    --cc=ajanulgu@redhat.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@redhat.com \
    --cc=daniel.almeida@collabora.com \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=lina@asahilina.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=pstanner@redhat.com \
    --cc=rafael@kernel.org \
    --cc=robh@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.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;
as well as URLs for NNTP newsgroup(s).