mirror of
https://github.com/torvalds/linux.git
synced 2025-11-01 09:09:47 +02:00
Change Device::vendor_id() to return a Vendor type, and change DeviceId::from_id() to accept a Vendor type. Use the new pci::Vendor in the various Rust for Linux callers who were previously using bindings::PCI_VENDOR_ID_*. Doing so also allows removing "use kernel::bindings" entirely from most of the affected files here. Also, mark vendor_id() as inline. Cc: Danilo Krummrich <dakr@kernel.org> Cc: Elle Rhumsaa <elle@weathered-steel.dev> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: John Hubbard <jhubbard@nvidia.com> Link: https://lore.kernel.org/r/20250829223632.144030-6-jhubbard@nvidia.com [ Replace "as a validated vendor" with "as [`Vendor`]". - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
107 lines
2.7 KiB
Rust
107 lines
2.7 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
//! Rust DMA api test (based on QEMU's `pci-testdev`).
|
|
//!
|
|
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
|
|
|
|
use kernel::{
|
|
device::Core,
|
|
dma::{CoherentAllocation, Device, DmaMask},
|
|
pci,
|
|
prelude::*,
|
|
types::ARef,
|
|
};
|
|
|
|
struct DmaSampleDriver {
|
|
pdev: ARef<pci::Device>,
|
|
ca: CoherentAllocation<MyStruct>,
|
|
}
|
|
|
|
const TEST_VALUES: [(u32, u32); 5] = [
|
|
(0xa, 0xb),
|
|
(0xc, 0xd),
|
|
(0xe, 0xf),
|
|
(0xab, 0xba),
|
|
(0xcd, 0xef),
|
|
];
|
|
|
|
struct MyStruct {
|
|
h: u32,
|
|
b: u32,
|
|
}
|
|
|
|
impl MyStruct {
|
|
fn new(h: u32, b: u32) -> Self {
|
|
Self { h, b }
|
|
}
|
|
}
|
|
// SAFETY: All bit patterns are acceptable values for `MyStruct`.
|
|
unsafe impl kernel::transmute::AsBytes for MyStruct {}
|
|
// SAFETY: Instances of `MyStruct` have no uninitialized portions.
|
|
unsafe impl kernel::transmute::FromBytes for MyStruct {}
|
|
|
|
kernel::pci_device_table!(
|
|
PCI_TABLE,
|
|
MODULE_PCI_TABLE,
|
|
<DmaSampleDriver as pci::Driver>::IdInfo,
|
|
[(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
|
|
);
|
|
|
|
impl pci::Driver for DmaSampleDriver {
|
|
type IdInfo = ();
|
|
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
|
|
|
|
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
|
|
dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
|
|
|
|
let mask = DmaMask::new::<64>();
|
|
|
|
// SAFETY: There are no concurrent calls to DMA allocation and mapping primitives.
|
|
unsafe { pdev.dma_set_mask_and_coherent(mask)? };
|
|
|
|
let ca: CoherentAllocation<MyStruct> =
|
|
CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
|
|
|
|
for (i, value) in TEST_VALUES.into_iter().enumerate() {
|
|
kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?;
|
|
}
|
|
|
|
let drvdata = KBox::new(
|
|
Self {
|
|
pdev: pdev.into(),
|
|
ca,
|
|
},
|
|
GFP_KERNEL,
|
|
)?;
|
|
|
|
Ok(drvdata.into())
|
|
}
|
|
}
|
|
|
|
impl Drop for DmaSampleDriver {
|
|
fn drop(&mut self) {
|
|
dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n");
|
|
|
|
for (i, value) in TEST_VALUES.into_iter().enumerate() {
|
|
let val0 = kernel::dma_read!(self.ca[i].h);
|
|
let val1 = kernel::dma_read!(self.ca[i].b);
|
|
assert!(val0.is_ok());
|
|
assert!(val1.is_ok());
|
|
|
|
if let Ok(val0) = val0 {
|
|
assert_eq!(val0, value.0);
|
|
}
|
|
if let Ok(val1) = val1 {
|
|
assert_eq!(val1, value.1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
kernel::module_pci_driver! {
|
|
type: DmaSampleDriver,
|
|
name: "rust_dma",
|
|
authors: ["Abdiel Janulgue"],
|
|
description: "Rust DMA test",
|
|
license: "GPL v2",
|
|
}
|