summaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-13 19:03:11 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-13 19:03:11 -0700
commit4793dae01f47754e288cdbb3a22581cac2317f2b (patch)
tree8a40b7277b52db2ef0605775ac4f627ff6cffabe /samples
parentd568788baab24875604c231f723dbb72387fb081 (diff)
parent6c8dfb0362732bf1e4829867a2a5239fedc592d0 (diff)
Merge tag 'driver-core-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core updates from Danilo Krummrich: "debugfs: - Fix NULL pointer dereference in debugfs_create_str() - Fix misplaced EXPORT_SYMBOL_GPL for debugfs_create_str() - Fix soundwire debugfs NULL pointer dereference from uninitialized firmware_file device property: - Make fwnode flags modifications thread safe; widen the field to unsigned long and use set_bit() / clear_bit() based accessors - Document how to check for the property presence devres: - Separate struct devres_node from its "subclasses" (struct devres, struct devres_group); give struct devres_node its own release and free callbacks for per-type dispatch - Introduce struct devres_action for devres actions, avoiding the ARCH_DMA_MINALIGN alignment overhead of struct devres - Export struct devres_node and its init/add/remove/dbginfo primitives for use by Rust Devres<T> - Fix missing node debug info in devm_krealloc() - Use guard(spinlock_irqsave) where applicable; consolidate unlock paths in devres_release_group() driver_override: - Convert PCI, WMI, vdpa, s390/cio, s390/ap, and fsl-mc to the generic driver_override infrastructure, replacing per-bus driver_override strings, sysfs attributes, and match logic; fixes a potential UAF from unsynchronized access to driver_override in bus match() callbacks - Simplify __device_set_driver_override() logic kernfs: - Send IN_DELETE_SELF and IN_IGNORED inotify events on kernfs file and directory removal - Add corresponding selftests for memcg platform: - Allow attaching software nodes when creating platform devices via a new 'swnode' field in struct platform_device_info - Add kerneldoc for struct platform_device_info software node: - Move software node initialization from postcore_initcall() to driver_init(), making it available early in the boot process - Move kernel_kobj initialization (ksysfs_init) earlier to support the above - Remove software_node_exit(); dead code in a built-in unit SoC: - Introduce of_machine_read_compatible() and of_machine_read_model() OF helpers and export soc_attr_read_machine() to replace direct accesses to of_root from SoC drivers; also enables CONFIG_COMPILE_TEST coverage for these drivers sysfs: - Constify attribute group array pointers to 'const struct attribute_group *const *' in sysfs functions, device_add_groups() / device_remove_groups(), and struct class Rust: - Devres: - Embed struct devres_node directly in Devres<T> instead of going through devm_add_action(), avoiding the extra allocation and the unnecessary ARCH_DMA_MINALIGN alignment - I/O: - Turn IoCapable from a marker trait into a functional trait carrying the raw I/O accessor implementation (io_read / io_write), providing working defaults for the per-type Io methods - Add RelaxedMmio wrapper type, making relaxed accessors usable in code generic over the Io trait - Remove overloaded per-type Io methods and per-backend macros from Mmio and PCI ConfigSpace - I/O (Register): - Add IoLoc trait and generic read/write/update methods to the Io trait, making I/O operations parameterizable by typed locations - Add register! macro for defining hardware register types with typed bitfield accessors backed by Bounded values; supports direct, relative, and array register addressing - Add write_reg() / try_write_reg() and LocatedRegister trait - Update PCI sample driver to demonstrate the register! macro Example: ``` register! { /// UART control register. CTRL(u32) @ 0x18 { /// Receiver enable. 19:19 rx_enable => bool; /// Parity configuration. 14:13 parity ?=> Parity; } /// FIFO watermark and counter register. WATER(u32) @ 0x2c { /// Number of datawords in the receive FIFO. 26:24 rx_count; /// RX interrupt threshold. 17:16 rx_water; } } impl WATER { fn rx_above_watermark(&self) -> bool { self.rx_count() > self.rx_water() } } fn init(bar: &pci::Bar<BAR0_SIZE>) { let water = WATER::zeroed() .with_const_rx_water::<1>(); // > 3 would not compile bar.write_reg(water); let ctrl = CTRL::zeroed() .with_parity(Parity::Even) .with_rx_enable(true); bar.write_reg(ctrl); } fn handle_rx(bar: &pci::Bar<BAR0_SIZE>) { if bar.read(WATER).rx_above_watermark() { // drain the FIFO } } fn set_parity(bar: &pci::Bar<BAR0_SIZE>, parity: Parity) { bar.update(CTRL, |r| r.with_parity(parity)); } ``` - IRQ: - Move 'static bounds from where clauses to trait declarations for IRQ handler traits - Misc: - Enable the generic_arg_infer Rust feature - Extend Bounded with shift operations, single-bit bool conversion, and const get() Misc: - Make deferred_probe_timeout default a Kconfig option - Drop auxiliary_dev_pm_ops; the PM core falls back to driver PM callbacks when no bus type PM ops are set - Add conditional guard support for device_lock() - Add ksysfs.c to the DRIVER CORE MAINTAINERS entry - Fix kernel-doc warnings in base.h - Fix stale reference to memory_block_add_nid() in documentation" * tag 'driver-core-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (67 commits) bus: fsl-mc: use generic driver_override infrastructure s390/ap: use generic driver_override infrastructure s390/cio: use generic driver_override infrastructure vdpa: use generic driver_override infrastructure platform/wmi: use generic driver_override infrastructure PCI: use generic driver_override infrastructure driver core: make software nodes available earlier software node: remove software_node_exit() kernel: ksysfs: initialize kernel_kobj earlier MAINTAINERS: add ksysfs.c to the DRIVER CORE entry drivers/base/memory: fix stale reference to memory_block_add_nid() device property: Document how to check for the property presence soundwire: debugfs: initialize firmware_file to empty string debugfs: fix placement of EXPORT_SYMBOL_GPL for debugfs_create_str() debugfs: check for NULL pointer in debugfs_create_str() driver core: Make deferred_probe_timeout default a Kconfig option driver core: simplify __device_set_driver_override() clearing logic driver core: auxiliary bus: Drop auxiliary_dev_pm_ops device property: Make modifications of fwnode "flags" thread safe rust: devres: embed struct devres_node directly ...
Diffstat (limited to 'samples')
-rw-r--r--samples/rust/rust_driver_pci.rs90
1 files changed, 68 insertions, 22 deletions
diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs
index d3d4a7931deb..47d3e84fab63 100644
--- a/samples/rust/rust_driver_pci.rs
+++ b/samples/rust/rust_driver_pci.rs
@@ -5,30 +5,63 @@
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
use kernel::{
- device::Bound,
- device::Core,
+ device::{
+ Bound,
+ Core, //
+ },
devres::Devres,
- io::Io,
+ io::{
+ register,
+ register::Array,
+ Io, //
+ },
+ num::Bounded,
pci,
prelude::*,
sync::aref::ARef, //
};
-struct Regs;
+mod regs {
+ use super::*;
-impl Regs {
- const TEST: usize = 0x0;
- const OFFSET: usize = 0x4;
- const DATA: usize = 0x8;
- const COUNT: usize = 0xC;
- const END: usize = 0x10;
+ register! {
+ pub(super) TEST(u8) @ 0x0 {
+ 7:0 index => TestIndex;
+ }
+
+ pub(super) OFFSET(u32) @ 0x4 {
+ 31:0 offset;
+ }
+
+ pub(super) DATA(u8) @ 0x8 {
+ 7:0 data;
+ }
+
+ pub(super) COUNT(u32) @ 0xC {
+ 31:0 count;
+ }
+ }
+
+ pub(super) const END: usize = 0x10;
}
-type Bar0 = pci::Bar<{ Regs::END }>;
+type Bar0 = pci::Bar<{ regs::END }>;
#[derive(Copy, Clone, Debug)]
struct TestIndex(u8);
+impl From<Bounded<u8, 8>> for TestIndex {
+ fn from(value: Bounded<u8, 8>) -> Self {
+ Self(value.into())
+ }
+}
+
+impl From<TestIndex> for Bounded<u8, 8> {
+ fn from(value: TestIndex) -> Self {
+ value.0.into()
+ }
+}
+
impl TestIndex {
const NO_EVENTFD: Self = Self(0);
}
@@ -54,40 +87,53 @@ kernel::pci_device_table!(
impl SampleDriver {
fn testdev(index: &TestIndex, bar: &Bar0) -> Result<u32> {
// Select the test.
- bar.write8(index.0, Regs::TEST);
+ bar.write_reg(regs::TEST::zeroed().with_index(*index));
- let offset = bar.read32(Regs::OFFSET) as usize;
- let data = bar.read8(Regs::DATA);
+ let offset = bar.read(regs::OFFSET).into_raw() as usize;
+ let data = bar.read(regs::DATA).into();
// Write `data` to `offset` to increase `count` by one.
//
// Note that we need `try_write8`, since `offset` can't be checked at compile-time.
bar.try_write8(data, offset)?;
- Ok(bar.read32(Regs::COUNT))
+ Ok(bar.read(regs::COUNT).into())
}
fn config_space(pdev: &pci::Device<Bound>) {
let config = pdev.config_space();
- // TODO: use the register!() macro for defining PCI configuration space registers once it
- // has been move out of nova-core.
+ // Some PCI configuration space registers.
+ register! {
+ VENDOR_ID(u16) @ 0x0 {
+ 15:0 vendor_id;
+ }
+
+ REVISION_ID(u8) @ 0x8 {
+ 7:0 revision_id;
+ }
+
+ BAR(u32)[6] @ 0x10 {
+ 31:0 value;
+ }
+ }
+
dev_info!(
pdev,
"pci-testdev config space read8 rev ID: {:x}\n",
- config.read8(0x8)
+ config.read(REVISION_ID).revision_id()
);
dev_info!(
pdev,
"pci-testdev config space read16 vendor ID: {:x}\n",
- config.read16(0)
+ config.read(VENDOR_ID).vendor_id()
);
dev_info!(
pdev,
"pci-testdev config space read32 BAR 0: {:x}\n",
- config.read32(0x10)
+ config.read(BAR::at(0)).value()
);
}
}
@@ -111,7 +157,7 @@ impl pci::Driver for SampleDriver {
pdev.set_master();
Ok(try_pin_init!(Self {
- bar <- pdev.iomap_region_sized::<{ Regs::END }>(0, c"rust_driver_pci"),
+ bar <- pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_driver_pci"),
index: *info,
_: {
let bar = bar.access(pdev.as_ref())?;
@@ -131,7 +177,7 @@ impl pci::Driver for SampleDriver {
fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
if let Ok(bar) = this.bar.access(pdev.as_ref()) {
// Reset pci-testdev by writing a new test index.
- bar.write8(this.index.0, Regs::TEST);
+ bar.write_reg(regs::TEST::zeroed().with_index(this.index));
}
}
}