rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Trevor Gross <tmgross@umich.edu>
To: FUJITA Tomonori <fujita.tomonori@gmail.com>
Cc: rust-for-linux@vger.kernel.org, andrew@lunn.ch,
	 Benno Lossin <benno.lossin@proton.me>
Subject: Re: [RFC PATCH v1 0/4] Rust abstractions for network PHY drivers
Date: Mon, 18 Sep 2023 18:23:23 -0400	[thread overview]
Message-ID: <CALNs47uN7GsEVJ5scqwZbzR-Dfk-uWp7EpafCBg0BarLhy+7ig@mail.gmail.com> (raw)
In-Reply-To: <20230913133609.1668758-1-fujita.tomonori@gmail.com>

Some meta design comments - why does registering need to allocate at
all? We should be able to keep the `phy_driver` in statics, like the C
side does.

Also, the size-generic `Registration` seems more complex that is
needed, which Benno was getting at. The C side already provides
`phy_drivers_register` and `phy_drivers_unregister` (drivers plural)
that can handle >1, so I don't think we need to create anything
special here.

I think the API could be simplified quite a bit with these things in
mind. A `Driver` can probably take over the `phy_id`, `phy_id_mask`,
and `name` fields which will more closely mirror `phy_driver` [1]:

    /// Used to do the same thing as `PHY_ID_MATCH_{EXACT, MODEL, VENDOR}`
    enum PhyIdMask {
        Exact,
        Model,
        Vendor,
        Custom(u32)
    }

    trait Driver {
        const PHY_ID: u32,
        const PHY_ID_MASK: PhyIdMask,
        const NAME: &'static CStr;
        // ...
    }

Then you need two const functions that can construct the
`mdio_device_id` table and the `phy_driver` structs (const functions
or macros, but I think functions are easier)

    const fn make_mdio_id<T: Driver>() -> Opaque<bindings::mdio_device_id> {
        let phy_id_mask = /* copy logic from existing C macros */;
        bindings::mdio_device_id { phy_id: T::PHY_ID, phy_id_mask }
    }

    const fn make_phy_device<T: Driver>() -> Opaque<bindings::phy_device> {
        // take this implementation from Adapter::driver
    }

And a type that can be used to unregister the devices on drop. This
doesn't need to be generic over N devices since it only ever needs to
call a single function.

    struct RegisteredHandle {
        unregister: unsafe fn()
    }

    impl Drop for RegisteredHandle {
        fn drop(&mut self) {
            // SAFETY: cannot be called more than once
            unsafe { self.0() };
        }
    }

Then, usage looks like this:

    struct RustAsixPhy {
        _reg: phy::RegisteredHandle,
    }

    impl kernel::Module for RustAsixPhy {
        fn init(module: &'static ThisModule) -> Result<Self> {
            pr_info!("Rust Asix phy driver\n");
            Ok(Self { _reg: register_fn_name()? } )
        }
    }

    // Takes one or more `impl Driver` structs. `modname` would just
be `asix` in real use
    phy_drivers!(modname, register_fn_name,  AsixAx8872a, AsixAx8872c,
AsixAc88796b);

The macro will expand to all of the below:

    /// A function that the user will call to register these modules.
Returns a handle that
    /// will unregister them on drop
    fn register_fn_name(module: &'static ThisModule) ->
Result<RegisteredHandle> {
        // We can use the existing functions that register multiple phys at once
        bindings::phy_drivers_register(
            &__modname_drivers,
            __modname_drivers.len(),
            module
        )?; // <- actually map this error...

        Ok(RegisteredHandle{
            unregister: || bindings::phy_drivers_unregister(
                &__modname_drivers, __modname_drivers.len()
            )
        })
    }

    /// Our `phy_device`s are stored here rather than in an allocation
    /// Don't need to be `#[no_mangle]` since C will never see this directly
    /// Does need to be mutable based on Andrew's comments
    pub static __modname_drivers: [Opaque<bindings::phy_device>; 3] = [
        make_phy_device::<AsixAx8872a>(),
        make_phy_device::<AsixAx8872c>(),
        make_phy_device::<AsixAx88796b>(),
    ];

    /// This will be the same as what exists - I assume this is read by
    /// the C side somehow?
    #[no_mangle]
    pub static __mod_mdio__modname_device_table:
        [Opaque<bindings::mdio_device_id>; 4] = [
        make_mdio_id::<AsixAx8872a>(),
        make_mdio_id::<AsixAx8872c>(),
        make_mdio_id::<AsixAx88796b>(),
        bindings::mdio_device_id { phy_id: 0, phy_id_mask: 0 }
    ];

    /// Bonus: we should be able to write a function that verifies the
phy IDs and
    /// their masks can actually all get matched
    const _: () = assert_correct_phy_ordering(__mod_mdio__modname_device_table);

This eliminates the need for allocation, a const-generic registration
struct, and the `Adapter` type (the associated functions on `Adapter`
could probably move into a `mod adapters` or similar). And
registration gets a bit more straightforward. I think this is a lot
more similar to what happens on the C side.

Any reasons the above wouldn't work?

[1]: @Fujita I know you have mentioned there are times where a driver
does not always have one mask. I can't find anything and am not sure
how this would work since `phy_driver` has `phy_id` and `phy_id_mask`
fields - do you mind linking an example? The above could probably be
adjusted to work with this

  parent reply	other threads:[~2023-09-18 22:23 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-13 13:36 [RFC PATCH v1 0/4] Rust abstractions for network PHY drivers FUJITA Tomonori
2023-09-13 13:36 ` [RFC PATCH v1 1/4] rust: core " FUJITA Tomonori
2023-09-13 20:11   ` Andrew Lunn
2023-09-13 20:49     ` Boqun Feng
2023-09-13 21:05       ` Andrew Lunn
2023-09-13 21:32         ` Boqun Feng
2023-09-14  4:10           ` Trevor Gross
2023-09-13 22:14     ` Miguel Ojeda
2023-09-14  0:30       ` Andrew Lunn
2023-09-14 11:03         ` Miguel Ojeda
2023-09-14 12:24           ` Andrew Lunn
2023-09-17  9:44           ` FUJITA Tomonori
2023-09-17 10:17     ` FUJITA Tomonori
2023-09-17 15:06       ` Andrew Lunn
2023-09-17 18:42         ` Trevor Gross
2023-09-17 19:08           ` Andrew Lunn
2023-09-18  0:49             ` Trevor Gross
2023-09-18  1:18               ` Andrew Lunn
2023-09-18  2:22                 ` Trevor Gross
2023-09-18  3:44                   ` FUJITA Tomonori
2023-09-18 13:13                     ` Andrew Lunn
2023-09-18  6:01         ` FUJITA Tomonori
2023-09-14  5:47   ` Trevor Gross
2023-09-14 10:17     ` Jarkko Sakkinen
2023-09-14 19:46       ` Trevor Gross
2023-09-14 12:39     ` Andrew Lunn
2023-09-14 19:42       ` Trevor Gross
2023-09-14 19:53         ` Trevor Gross
2023-09-18  9:56   ` Finn Behrens
2023-09-18 13:22     ` Andrew Lunn
2023-09-18 10:22   ` Benno Lossin
2023-09-18 13:09     ` FUJITA Tomonori
2023-09-18 15:20       ` Benno Lossin
2023-09-19 10:26         ` FUJITA Tomonori
2023-09-20 13:24           ` Benno Lossin
2023-09-13 13:36 ` [RFC PATCH v1 2/4] rust: phy: add module device table support FUJITA Tomonori
2023-09-14  6:26   ` Trevor Gross
2023-09-14  7:23     ` Trevor Gross
2023-09-17  6:30       ` FUJITA Tomonori
2023-09-17 15:13         ` Andrew Lunn
2023-09-13 13:36 ` [RFC PATCH v1 3/4] MAINTAINERS: add Rust PHY abstractions file to the ETHERNET PHY LIBRARY FUJITA Tomonori
2023-09-13 18:57   ` Andrew Lunn
2023-09-17 12:32     ` FUJITA Tomonori
2023-09-19 12:06       ` Miguel Ojeda
2023-09-19 16:33         ` Andrew Lunn
2023-09-22 23:17           ` Trevor Gross
2023-09-23  0:05           ` Miguel Ojeda
2023-09-23  1:36             ` Andrew Lunn
2023-09-23 10:19               ` Miguel Ojeda
2023-09-23 14:42                 ` Andrew Lunn
2023-10-09 12:26                   ` Miguel Ojeda
2023-09-13 13:36 ` [RFC PATCH v1 4/4] sample: rust: add Asix PHY driver FUJITA Tomonori
2023-09-13 14:11   ` Andrew Lunn
2023-09-13 16:53     ` Greg KH
2023-09-13 18:50       ` Andrew Lunn
2023-09-13 18:59         ` Greg KH
2023-09-13 20:20           ` Andrew Lunn
2023-09-13 20:38             ` Greg KH
2023-09-13 16:56   ` Greg KH
2023-09-13 18:43     ` Andrew Lunn
2023-09-13 19:15   ` Andrew Lunn
2023-09-17 11:28     ` FUJITA Tomonori
2023-09-17 15:46       ` Andrew Lunn
2023-09-18  8:35         ` FUJITA Tomonori
2023-09-18 13:37           ` Andrew Lunn
2023-09-24  9:12             ` FUJITA Tomonori
2023-09-24  9:59               ` Miguel Ojeda
2023-09-24 15:31               ` Andrew Lunn
2023-09-24 17:31                 ` Miguel Ojeda
2023-09-24 17:44                   ` Andrew Lunn
2023-09-24 18:44                     ` Miguel Ojeda
2023-09-18 22:23 ` Trevor Gross [this message]
2023-09-18 22:48   ` [RFC PATCH v1 0/4] Rust abstractions for network PHY drivers Andrew Lunn
2023-09-18 23:46     ` Trevor Gross
2023-09-19  6:24       ` FUJITA Tomonori
2023-09-19  7:41         ` Trevor Gross
2023-09-19 16:12         ` Andrew Lunn
2023-09-19  6:16   ` FUJITA Tomonori
2023-09-19  8:05     ` Trevor Gross

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=CALNs47uN7GsEVJ5scqwZbzR-Dfk-uWp7EpafCBg0BarLhy+7ig@mail.gmail.com \
    --to=tmgross@umich.edu \
    --cc=andrew@lunn.ch \
    --cc=benno.lossin@proton.me \
    --cc=fujita.tomonori@gmail.com \
    --cc=rust-for-linux@vger.kernel.org \
    /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).