From: Benno Lossin <benno.lossin@proton.me>
To: FUJITA Tomonori <fujita.tomonori@gmail.com>
Cc: netdev@vger.kernel.org, rust-for-linux@vger.kernel.org,
andrew@lunn.ch, miguel.ojeda.sandonis@gmail.com,
tmgross@umich.edu, boqun.feng@gmail.com, wedsonaf@gmail.com,
greg@kroah.com
Subject: Re: [PATCH net-next v5 1/5] rust: core abstractions for network PHY drivers
Date: Thu, 19 Oct 2023 13:45:27 +0000 [thread overview]
Message-ID: <0e8d2538-284b-4811-a2e7-99151338c255@proton.me> (raw)
In-Reply-To: <20231019.092436.1433321157817125498.fujita.tomonori@gmail.com>
On 19.10.23 02:24, FUJITA Tomonori wrote:
> On Wed, 18 Oct 2023 15:07:52 +0000
> Benno Lossin <benno.lossin@proton.me> wrote:
>
>>> diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
>>> new file mode 100644
>>> index 000000000000..7d4927ece32f
>>> --- /dev/null
>>> +++ b/rust/kernel/net/phy.rs
>>> @@ -0,0 +1,701 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +
>>> +// Copyright (C) 2023 FUJITA Tomonori <fujita.tomonori@gmail.com>
>>> +
>>> +//! Network PHY device.
>>> +//!
>>> +//! C headers: [`include/linux/phy.h`](../../../../include/linux/phy.h).
>>> +//!
>>
>> Add a new section "# Abstraction Overview" or similar.
>
> With the rest of comments on this secsion addressed, how about the following?
>
> //! Network PHY device.
> //!
> //! C headers: [`include/linux/phy.h`](../../../../include/linux/phy.h).
> //!
> //! # Abstraction Overview
> //!
> //! "During the calls to most functions in [`Driver`], the C side (`PHYLIB`) holds a lock that is unique
Please remove the quotes ", they were intended to separate my comments
from my suggestion.
> //! for every instance of [`Device`]". `PHYLIB` uses a different serialization technique for
> //! [`Driver::resume`] and [`Driver::suspend`]: `PHYLIB` updates `phy_device`'s state with the lock hold,
hold -> held
> //! to guarantee that [`Driver::resume`] accesses to the instance exclusively. [`Driver::resume`] and
to guarantee -> thus guaranteeing
accesses to the instance exclusively. -> has exclusive access to the instance.
> //! [`Driver::suspend`] also are called where only one thread can access to the instance.
> //!
> //! All the PHYLIB helper functions for [`Device`] modify some members in [`Device`]. Except for
PHYLIB -> `PHYLIB`
> //! getter functions, [`Device`] methods take `&mut self`. This also applied to `[Device::read]`,
`[Device::read]` -> [`Device::read`]
> //! which reads a hardware register and updates the stats.
Otherwise this looks good.
[...]
>>> +impl Device {
>>> + /// Creates a new [`Device`] instance from a raw pointer.
>>> + ///
>>> + /// # Safety
>>> + ///
>>> + /// This function must only be called from the callbacks in `phy_driver`. PHYLIB guarantees
>>> + /// the exclusive access for the duration of the lifetime `'a`.
>>
>> I would not put the second sentence in the `# Safety` section. Just move it
>> above. The reason behind this is the following: the second sentence is not
>> a precondition needed to call the function.
>
> Where is the `above`? You meant the following?
>
> impl Device {
> /// Creates a new [`Device`] instance from a raw pointer.
> ///
> /// `PHYLIB` guarantees the exclusive access for the duration of the lifetime `'a`.
> ///
> /// # Safety
> ///
> /// This function must only be called from the callbacks in `phy_driver`.
> unsafe fn from_raw<'a>(ptr: *mut bindings::phy_device) -> &'a mut Self {
Yes this is what I had in mind. Although now that I see it in code,
I am not so sure that this comment is needed. If you feel the same
way, just remove it.
That being said, I am not too happy with the safety requirement of this
function. It does not really match with the safety comment in the function
body. Since I have not yet finished my safety standardization, I think we
can defer that problem until it is finished. Unless some other reviewer
wants to change this, you can keep it as is.
>>> + unsafe fn from_raw<'a>(ptr: *mut bindings::phy_device) -> &'a mut Self {
>>> + // CAST: `Self` is a `repr(transparent)` wrapper around `bindings::phy_device`.
>>> + let ptr = ptr.cast::<Self>();
>>> + // SAFETY: by the function requirements the pointer is valid and we have unique access for
>>> + // the duration of `'a`.
>>> + unsafe { &mut *ptr }
>>> + }
>>> +
>>> + /// Gets the id of the PHY.
>>> + pub fn phy_id(&self) -> u32 {
>>> + let phydev = self.0.get();
>>> + // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
>>> + unsafe { (*phydev).phy_id }
>>> + }
>>> +
>>> + /// Gets the state of the PHY.
>>> + pub fn state(&self) -> DeviceState {
>>> + let phydev = self.0.get();
>>> + // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
>>> + let state = unsafe { (*phydev).state };
>>> + // TODO: this conversion code will be replaced with automatically generated code by bindgen
>>> + // when it becomes possible.
>>> + // better to call WARN_ONCE() when the state is out-of-range (needs to add WARN_ONCE support).
>>> + match state {
>>> + bindings::phy_state_PHY_DOWN => DeviceState::Down,
>>> + bindings::phy_state_PHY_READY => DeviceState::Ready,
>>> + bindings::phy_state_PHY_HALTED => DeviceState::Halted,
>>> + bindings::phy_state_PHY_ERROR => DeviceState::Error,
>>> + bindings::phy_state_PHY_UP => DeviceState::Up,
>>> + bindings::phy_state_PHY_RUNNING => DeviceState::Running,
>>> + bindings::phy_state_PHY_NOLINK => DeviceState::NoLink,
>>> + bindings::phy_state_PHY_CABLETEST => DeviceState::CableTest,
>>> + _ => DeviceState::Error,
>>> + }
>>> + }
>>> +
>>> + /// Returns true if the link is up.
>>> + pub fn get_link(&self) -> bool {
>>
>> I still think this name should be changed. My response at [1] has not yet
>> been replied to. This has already been discussed before:
>> - https://lore.kernel.org/rust-for-linux/2023100237-satirical-prance-bd57@gregkh/
>> - https://lore.kernel.org/rust-for-linux/20231004.084644.50784533959398755.fujita.tomonori@gmail.com/
>> - https://lore.kernel.org/rust-for-linux/CALNs47syMxiZBUwKLk3vKxzmCbX0FS5A37FjwUzZO9Fn-iPaoA@mail.gmail.com/
>>
>> And I want to suggest to change it to `is_link_up`.
>>
>> Reasons why I do not like the name:
>> - `get_`/`put_` are used for ref counting on the C side, I would like to
>> avoid confusion.
>> - `get` in Rust is often used to fetch a value from e.g. a datastructure
>> such as a hashmap, so I expect the call to do some computation.
>> - getters in Rust usually are not prefixed with `get_`, but rather are
>> just the name of the field.
>> - in this case I like the name `is_link_up` much better, since code becomes
>> a lot more readable with that.
>> - I do not want this pattern as an example for other drivers.
>>
>> [1]: https://lore.kernel.org/rust-for-linux/f5878806-5ba2-d932-858d-dda3f55ceb67@proton.me/
>
> IIRC, Andrew suggested the current name. If the change is fine by him,
> I'll rename.
>
>
>>> +/// An instance of a PHY driver.
>>> +///
>>> +/// Wraps the kernel's `struct phy_driver`.
>>> +///
>>> +/// # Invariants
>>> +///
>>> +/// `self.0` is always in a valid state.
>>> +#[repr(transparent)]
>>> +pub struct DriverType(Opaque<bindings::phy_driver>);
>>
>> I think `DriverVTable` is a better name.
>
> Renamed.
>
>>> +/// Creates the kernel's `phy_driver` instance.
>>
>> This function returns a `DriverType`, not a `phy_driver`.
>
> How about?
>
> /// Creates the [`DriverVTable`] instance from [`Driver`] trait.
Sounds good, but to this sounds a bit more natural:
/// Creates a [`DriverVTable`] instance from a [`Driver`].
>>> +///
>>> +/// This is used by [`module_phy_driver`] macro to create a static array of `phy_driver`.
>>> +///
>>> +/// [`module_phy_driver`]: crate::module_phy_driver
>>> +pub const fn create_phy_driver<T: Driver>() -> DriverType {
>>> + // All the fields of `struct phy_driver` are initialized properly.
>>> + // It ensures the invariants.
>>
>> Use `// INVARIANT: `.
>
> Oops,
>
> // INVARIANT: All the fields of `struct phy_driver` are initialized properly.
> DriverVTable(Opaque::new(bindings::phy_driver {
> name: T::NAME.as_char_ptr().cast_mut(),
Seems good.
>
>
>>> +/// Registration structure for a PHY driver.
>>> +///
>>> +/// # Invariants
>>> +///
>>> +/// The `drivers` slice are currently registered to the kernel via `phy_drivers_register`.
>>> +pub struct Registration {
>>> + drivers: &'static [DriverType],
>>> +}
>>
>> You did not reply to my suggestion [2] to remove this type,
>> what do you think?
>>
>> [2]: https://lore.kernel.org/rust-for-linux/85d5c498-efbc-4c1a-8d12-f1eca63c45cf@proton.me/
>
> I tried before but I'm not sure it simplifies the implementation.
>
> Firstly, instead of Reservation, we need a public function like
>
> pub fn phy_drivers_register(module: &'static crate::ThisModule, drivers: &[DriverVTable]) -> Result {
> to_result(unsafe {
> bindings::phy_drivers_register(drivers[0].0.get(), drivers.len().try_into()?, module.0)
> })
> }
>
> This is because module.0 is private.
Why can't this be part of the macro?
> Also if we keep DriverVtable.0 private, we need another public function.
>
> pub unsafe fn phy_drivers_unregister(drivers: &'static [DriverVTable])
> {
> unsafe {
> bindings::phy_drivers_unregister(drivers[0].0.get(), drivers.len() as i32)
> };
> }
>
> DriverVTable isn't guaranteed to be registered to the kernel so needs
> to be unsafe, I guesss.
In one of the options I suggest to make that an invariant of `DriverVTable`.
>
> Also Module trait support exit()?
Yes, just implement `Drop` and do the cleanup there.
In the two options that I suggested there is a trade off. I do not know
which option is better, I hoped that you or Andrew would know more:
Option 1:
* advantages:
- manual creation of a phy driver module becomes possible.
- less complex `module_phy_driver` macro.
- no static variable needed.
* disadvantages:
- calls `phy_drivers_register` for every driver on module
initialization.
- calls `phy_drivers_unregister` for every driver on module
exit.
Option 2:
* advantages:
- less complex `module_phy_driver` macro.
- no static variable needed.
- only a single call to
`phy_drivers_register`/`phy_drivers_unregister`.
* disadvantages:
- no safe manual creation of phy drivers possible, the only safe
way is to use the `module_phy_driver` macro.
I suppose that it would be ok to call the register function multiple
times, since it only is on module startup/shutdown and it is not
performance critical.
--
Cheers,
Benno
next prev parent reply other threads:[~2023-10-19 13:45 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-17 11:30 [PATCH net-next v5 0/5] Rust abstractions for network PHY drivers FUJITA Tomonori
2023-10-17 11:30 ` [PATCH net-next v5 1/5] rust: core " FUJITA Tomonori
2023-10-18 15:07 ` Benno Lossin
2023-10-19 0:24 ` FUJITA Tomonori
2023-10-19 13:45 ` Benno Lossin [this message]
2023-10-19 14:42 ` FUJITA Tomonori
2023-10-19 15:20 ` Benno Lossin
2023-10-19 15:32 ` FUJITA Tomonori
2023-10-19 16:37 ` Benno Lossin
2023-10-19 21:51 ` FUJITA Tomonori
2023-10-21 7:21 ` Benno Lossin
2023-10-20 0:34 ` FUJITA Tomonori
2023-10-20 12:54 ` FUJITA Tomonori
2023-10-21 7:25 ` Benno Lossin
2023-10-21 7:30 ` FUJITA Tomonori
2023-10-21 8:37 ` Benno Lossin
2023-10-21 10:27 ` FUJITA Tomonori
2023-10-21 11:21 ` Benno Lossin
2023-10-21 11:36 ` FUJITA Tomonori
2023-10-21 12:13 ` Benno Lossin
2023-10-21 12:38 ` FUJITA Tomonori
2023-10-21 12:50 ` Benno Lossin
2023-10-21 13:00 ` FUJITA Tomonori
2023-10-21 13:05 ` Benno Lossin
2023-10-21 13:31 ` FUJITA Tomonori
2023-10-21 13:35 ` Benno Lossin
2023-10-21 21:45 ` FUJITA Tomonori
2023-10-23 6:35 ` Benno Lossin
2023-10-23 6:37 ` Benno Lossin
2023-10-21 15:57 ` Andrew Lunn
2023-10-21 16:31 ` Benno Lossin
2023-10-21 15:41 ` Andrew Lunn
2023-10-20 18:42 ` Andrew Lunn
2023-10-21 4:44 ` FUJITA Tomonori
2023-10-21 7:36 ` Benno Lossin
2023-10-21 12:47 ` Miguel Ojeda
2023-10-22 9:47 ` FUJITA Tomonori
2023-10-22 11:37 ` Miguel Ojeda
2023-10-22 15:34 ` Andrew Lunn
2023-10-24 1:37 ` FUJITA Tomonori
2023-10-24 8:48 ` Miguel Ojeda
2023-10-18 20:27 ` Andrew Lunn
2023-10-19 0:41 ` FUJITA Tomonori
2023-10-19 13:57 ` Benno Lossin
2023-10-20 19:50 ` Andrew Lunn
2023-10-21 8:01 ` Benno Lossin
2023-10-21 15:35 ` Andrew Lunn
2023-10-20 17:26 ` Andreas Hindborg (Samsung)
2023-10-20 17:56 ` Benno Lossin
2023-10-20 19:59 ` Andrew Lunn
2023-10-20 20:30 ` Andreas Hindborg (Samsung)
2023-10-21 3:49 ` FUJITA Tomonori
2023-10-21 4:01 ` FUJITA Tomonori
2023-10-17 11:30 ` [PATCH net-next v5 2/5] rust: net::phy add module_phy_driver macro FUJITA Tomonori
2023-10-17 11:30 ` [PATCH net-next v5 3/5] WIP rust: add second `bindgen` pass for enum exhaustiveness checking FUJITA Tomonori
2023-10-20 11:37 ` Andreas Hindborg (Samsung)
2023-10-20 12:34 ` Miguel Ojeda
2023-10-20 12:35 ` Miguel Ojeda
2023-10-23 8:57 ` Andreas Hindborg (Samsung)
2023-10-21 3:51 ` FUJITA Tomonori
2023-10-21 12:05 ` Miguel Ojeda
2023-10-22 6:30 ` FUJITA Tomonori
2023-10-23 8:58 ` Andreas Hindborg (Samsung)
2023-10-17 11:30 ` [PATCH net-next v5 4/5] MAINTAINERS: add Rust PHY abstractions for ETHERNET PHY LIBRARY FUJITA Tomonori
2023-10-17 11:30 ` [PATCH net-next v5 5/5] net: phy: add Rust Asix PHY driver FUJITA Tomonori
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=0e8d2538-284b-4811-a2e7-99151338c255@proton.me \
--to=benno.lossin@proton.me \
--cc=andrew@lunn.ch \
--cc=boqun.feng@gmail.com \
--cc=fujita.tomonori@gmail.com \
--cc=greg@kroah.com \
--cc=miguel.ojeda.sandonis@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--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).