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 09/10] rust: pci: add basic PCI device / driver abstractions
Date: Thu, 20 Jun 2024 17:11:43 +0200 [thread overview]
Message-ID: <2024062011-property-hypnotist-e652@gregkh> (raw)
In-Reply-To: <20240618234025.15036-10-dakr@redhat.com>
On Wed, Jun 19, 2024 at 01:39:55AM +0200, Danilo Krummrich wrote:
> +/// Abstraction for bindings::pci_device_id.
> +#[derive(Clone, Copy)]
> +pub struct DeviceId {
> + /// Vendor ID
> + pub vendor: u32,
> + /// Device ID
> + pub device: u32,
> + /// Subsystem vendor ID
> + pub subvendor: u32,
> + /// Subsystem device ID
> + pub subdevice: u32,
> + /// Device class and subclass
> + pub class: u32,
> + /// Limit which sub-fields of the class
> + pub class_mask: u32,
> +}
Note, this is exported to userspace, why can't you use the C structure
that's already defined for you? This is going to get tricky over time
for the different busses, please use what is already there.
And question, how are you guaranteeing the memory layout of this
structure here? Will rust always do this with no holes and no
re-arranging?
> +impl DeviceId {
> + const PCI_ANY_ID: u32 = !0;
> +
> + /// PCI_DEVICE macro.
> + pub const fn new(vendor: u32, device: u32) -> Self {
> + Self {
> + vendor,
> + device,
> + subvendor: DeviceId::PCI_ANY_ID,
> + subdevice: DeviceId::PCI_ANY_ID,
> + class: 0,
> + class_mask: 0,
> + }
> + }
> +
> + /// PCI_DEVICE_CLASS macro.
> + pub const fn with_class(class: u32, class_mask: u32) -> Self {
> + Self {
> + vendor: DeviceId::PCI_ANY_ID,
> + device: DeviceId::PCI_ANY_ID,
> + subvendor: DeviceId::PCI_ANY_ID,
> + subdevice: DeviceId::PCI_ANY_ID,
> + class,
> + class_mask,
> + }
> + }
Why just these 2 subsets of the normal PCI_DEVICE* macros?
> +
> + /// PCI_DEVICE_ID macro.
> + pub const fn to_rawid(&self, offset: isize) -> bindings::pci_device_id {
PCI_DEVICE_ID is defined to be "0x02" in pci_regs.h, I don't think you
want that duplication here, right?
> + bindings::pci_device_id {
> + vendor: self.vendor,
> + device: self.device,
> + subvendor: self.subvendor,
> + subdevice: self.subdevice,
> + class: self.class,
> + class_mask: self.class_mask,
> + driver_data: offset as _,
> + override_only: 0,
> + }
> + }
> +}
> +
> +// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `pci_device_id::driver_data`.
> +unsafe impl RawDeviceId for DeviceId {
> + type RawType = bindings::pci_device_id;
> +
> + const ZERO: Self::RawType = bindings::pci_device_id {
> + vendor: 0,
> + device: 0,
> + subvendor: 0,
> + subdevice: 0,
> + class: 0,
> + class_mask: 0,
> + driver_data: 0,
> + override_only: 0,
This feels rough, why can't the whole memory chunk be set to 0 for any
non-initialized values? What happens if a new value gets added to the C
side, how will this work here?
> + };
> +}
> +
> +/// Define a const pci device id table
> +///
> +/// # Examples
> +///
> +/// See [`Driver`]
> +///
> +#[macro_export]
> +macro_rules! define_pci_id_table {
> + ($data_type:ty, $($t:tt)*) => {
> + type IdInfo = $data_type;
> + const ID_TABLE: $crate::device_id::IdTable<'static, $crate::pci::DeviceId, $data_type> = {
> + $crate::define_id_array!(ARRAY, $crate::pci::DeviceId, $data_type, $($t)* );
> + ARRAY.as_table()
> + };
> + };
> +}
> +pub use define_pci_id_table;
> +
> +/// The PCI driver trait.
> +///
> +/// # Example
> +///
> +///```
> +/// # use kernel::{bindings, define_pci_id_table, pci, sync::Arc};
> +///
> +/// struct MyDriver;
> +/// struct MyDeviceData;
> +///
> +/// impl pci::Driver for MyDriver {
> +/// type Data = Arc<MyDeviceData>;
> +///
> +/// define_pci_id_table! {
> +/// (),
> +/// [ (pci::DeviceId::new(bindings::PCI_VENDOR_ID_REDHAT,
> +/// bindings::PCI_ANY_ID as u32),
> +/// None)
> +/// ]
> +/// }
> +///
> +/// fn probe(
> +/// _pdev: &mut pci::Device,
> +/// _id_info: Option<&Self::IdInfo>
> +/// ) -> Result<Self::Data> {
> +/// Err(ENODEV)
> +/// }
> +///
> +/// fn remove(_data: &Self::Data) {
> +/// }
> +/// }
> +///```
> +/// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the
> +/// `Adapter` documentation for an example.
> +pub trait Driver {
> + /// Data stored on device by driver.
> + ///
> + /// Corresponds to the data set or retrieved via the kernel's
> + /// `pci_{set,get}_drvdata()` functions.
> + ///
> + /// Require that `Data` implements `ForeignOwnable`. We guarantee to
> + /// never move the underlying wrapped data structure.
> + ///
> + /// TODO: Use associated_type_defaults once stabilized:
> + ///
> + /// `type Data: ForeignOwnable = ();`
> + type Data: ForeignOwnable;
Does this mean this all can be 'static' in memory and never dynamically
allocated? If so, good, if not, why not?
> +
> + /// The type holding information about each device id supported by the driver.
> + ///
> + /// TODO: Use associated_type_defaults once stabilized:
> + ///
> + /// type IdInfo: 'static = ();
> + type IdInfo: 'static;
What does static mean here?
> +
> + /// The table of device ids supported by the driver.
> + const ID_TABLE: IdTable<'static, DeviceId, Self::IdInfo>;
> +
> + /// PCI driver probe.
> + ///
> + /// Called when a new platform device is added or discovered.
This is not a platform device
> + /// Implementers should attempt to initialize the device here.
> + fn probe(dev: &mut Device, id: Option<&Self::IdInfo>) -> Result<Self::Data>;
> +
> + /// PCI driver remove.
> + ///
> + /// Called when a platform device is removed.
This is not a platform device.
> + /// Implementers should prepare the device for complete removal here.
> + fn remove(data: &Self::Data);
No suspend? No resume? No shutdown? only probe/remove? Ok, baby
steps are nice :)
> +}
> +
> +/// The PCI device representation.
> +///
> +/// A PCI device is based on an always reference counted `device:Device` instance. Cloning a PCI
> +/// device, hence, also increments the base device' reference count.
> +#[derive(Clone)]
> +pub struct Device(ARef<device::Device>);
> +
> +impl Device {
> + /// Create a PCI Device instance from an existing `device::Device`.
> + ///
> + /// # Safety
> + ///
> + /// `dev` must be an `ARef<device::Device>` whose underlying `bindings::device` is a member of
> + /// a `bindings::pci_dev`.
> + pub unsafe fn from_dev(dev: ARef<device::Device>) -> Self {
> + Self(dev)
> + }
> +
> + fn as_raw(&self) -> *mut bindings::pci_dev {
> + // SAFETY: Guaranteed by the type invaraints.
> + unsafe { container_of!(self.0.as_raw(), bindings::pci_dev, dev) as _ }
> + }
> +
> + /// Enable the Device's memory.
> + pub fn enable_device_mem(&self) -> Result {
> + // SAFETY: Safe by the type invariants.
> + let ret = unsafe { bindings::pci_enable_device_mem(self.as_raw()) };
> + if ret != 0 {
> + Err(Error::from_errno(ret))
> + } else {
> + Ok(())
> + }
> + }
> +
> + /// Set the Device's master.
> + pub fn set_master(&self) {
> + // SAFETY: Safe by the type invariants.
> + unsafe { bindings::pci_set_master(self.as_raw()) };
> + }
Why just these 2 functions? Just an example, or you don't need anything
else yet?
thanks,
greg k-h
next prev parent reply other threads:[~2024-06-20 15:11 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
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 [this message]
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=2024062011-property-hypnotist-e652@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).