Skip to content

Commit bfcaf4e

Browse files
author
Danilo Krummrich
committed
rust: io: macro_export io_define_read!() and io_define_write!()
Currently, the define_read!() and define_write!() I/O macros are crate public. The only user outside of the I/O module is PCI (for the configurations space I/O backend). Consequently, when CONFIG_PCI=n this causes a compile time warning [1]. In order to fix this, rename the macros to io_define_read!() and io_define_write!() and use #[macro_export] to export them. This is better than making the crate public visibility conditional, as eventually subsystems will have their own crate. Also, I/O backends are valid to be implemented by drivers as well. For instance, there are devices (such as GPUs) that run firmware which allows to program other devices only accessible through the primary device through indirect I/O. Since the macros are now public, also add the corresponding documentation. Fixes: 121d87b ("rust: io: separate generic I/O helpers from MMIO implementation") Reported-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> Closes: https://lore.kernel.org/driver-core/CANiq72khOYkt6t5zwMvSiyZvWWHMZuNCMERXu=7K=_5tT-8Pgg@mail.gmail.com/ [1] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://patch.msgid.link/20260216131534.65008-1-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent 2692c61 commit bfcaf4e

2 files changed

Lines changed: 101 additions & 54 deletions

File tree

rust/kernel/io.rs

Lines changed: 89 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ pub struct Mmio<const SIZE: usize = 0>(MmioRaw<SIZE>);
139139

140140
/// Internal helper macros used to invoke C MMIO read functions.
141141
///
142-
/// This macro is intended to be used by higher-level MMIO access macros (define_read) and provides
143-
/// a unified expansion for infallible vs. fallible read semantics. It emits a direct call into the
144-
/// corresponding C helper and performs the required cast to the Rust return type.
142+
/// This macro is intended to be used by higher-level MMIO access macros (io_define_read) and
143+
/// provides a unified expansion for infallible vs. fallible read semantics. It emits a direct call
144+
/// into the corresponding C helper and performs the required cast to the Rust return type.
145145
///
146146
/// # Parameters
147147
///
@@ -166,9 +166,9 @@ macro_rules! call_mmio_read {
166166

167167
/// Internal helper macros used to invoke C MMIO write functions.
168168
///
169-
/// This macro is intended to be used by higher-level MMIO access macros (define_write) and provides
170-
/// a unified expansion for infallible vs. fallible write semantics. It emits a direct call into the
171-
/// corresponding C helper and performs the required cast to the Rust return type.
169+
/// This macro is intended to be used by higher-level MMIO access macros (io_define_write) and
170+
/// provides a unified expansion for infallible vs. fallible write semantics. It emits a direct call
171+
/// into the corresponding C helper and performs the required cast to the Rust return type.
172172
///
173173
/// # Parameters
174174
///
@@ -193,7 +193,30 @@ macro_rules! call_mmio_write {
193193
}};
194194
}
195195

196-
macro_rules! define_read {
196+
/// Generates an accessor method for reading from an I/O backend.
197+
///
198+
/// This macro reduces boilerplate by automatically generating either compile-time bounds-checked
199+
/// (infallible) or runtime bounds-checked (fallible) read methods. It abstracts the address
200+
/// calculation and bounds checking, and delegates the actual I/O read operation to a specified
201+
/// helper macro, making it generic over different I/O backends.
202+
///
203+
/// # Parameters
204+
///
205+
/// * `infallible` / `fallible` - Determines the bounds-checking strategy. `infallible` relies on
206+
/// `IoKnownSize` for compile-time checks and returns the value directly. `fallible` performs
207+
/// runtime checks against `maxsize()` and returns a `Result<T>`.
208+
/// * `$(#[$attr:meta])*` - Optional attributes to apply to the generated method (e.g.,
209+
/// `#[cfg(CONFIG_64BIT)]` or inline directives).
210+
/// * `$vis:vis` - The visibility of the generated method (e.g., `pub`).
211+
/// * `$name:ident` / `$try_name:ident` - The name of the generated method (e.g., `read32`,
212+
/// `try_read8`).
213+
/// * `$call_macro:ident` - The backend-specific helper macro used to emit the actual I/O call
214+
/// (e.g., `call_mmio_read`).
215+
/// * `$c_fn:ident` - The backend-specific C function or identifier to be passed into the
216+
/// `$call_macro`.
217+
/// * `$type_name:ty` - The Rust type of the value being read (e.g., `u8`, `u32`).
218+
#[macro_export]
219+
macro_rules! io_define_read {
197220
(infallible, $(#[$attr:meta])* $vis:vis $name:ident, $call_macro:ident($c_fn:ident) ->
198221
$type_name:ty) => {
199222
/// Read IO data from a given offset known at compile time.
@@ -226,9 +249,33 @@ macro_rules! define_read {
226249
}
227250
};
228251
}
229-
pub(crate) use define_read;
252+
pub use io_define_read;
230253

231-
macro_rules! define_write {
254+
/// Generates an accessor method for writing to an I/O backend.
255+
///
256+
/// This macro reduces boilerplate by automatically generating either compile-time bounds-checked
257+
/// (infallible) or runtime bounds-checked (fallible) write methods. It abstracts the address
258+
/// calculation and bounds checking, and delegates the actual I/O write operation to a specified
259+
/// helper macro, making it generic over different I/O backends.
260+
///
261+
/// # Parameters
262+
///
263+
/// * `infallible` / `fallible` - Determines the bounds-checking strategy. `infallible` relies on
264+
/// `IoKnownSize` for compile-time checks and returns `()`. `fallible` performs runtime checks
265+
/// against `maxsize()` and returns a `Result`.
266+
/// * `$(#[$attr:meta])*` - Optional attributes to apply to the generated method (e.g.,
267+
/// `#[cfg(CONFIG_64BIT)]` or inline directives).
268+
/// * `$vis:vis` - The visibility of the generated method (e.g., `pub`).
269+
/// * `$name:ident` / `$try_name:ident` - The name of the generated method (e.g., `write32`,
270+
/// `try_write8`).
271+
/// * `$call_macro:ident` - The backend-specific helper macro used to emit the actual I/O call
272+
/// (e.g., `call_mmio_write`).
273+
/// * `$c_fn:ident` - The backend-specific C function or identifier to be passed into the
274+
/// `$call_macro`.
275+
/// * `$type_name:ty` - The Rust type of the value being written (e.g., `u8`, `u32`). Note the use
276+
/// of `<-` before the type to denote a write operation.
277+
#[macro_export]
278+
macro_rules! io_define_write {
232279
(infallible, $(#[$attr:meta])* $vis:vis $name:ident, $call_macro:ident($c_fn:ident) <-
233280
$type_name:ty) => {
234281
/// Write IO data from a given offset known at compile time.
@@ -259,7 +306,7 @@ macro_rules! define_write {
259306
}
260307
};
261308
}
262-
pub(crate) use define_write;
309+
pub use io_define_write;
263310

264311
/// Checks whether an access of type `U` at the given `offset`
265312
/// is valid within this region.
@@ -509,40 +556,40 @@ impl<const SIZE: usize> Io for Mmio<SIZE> {
509556
self.0.maxsize()
510557
}
511558

512-
define_read!(fallible, try_read8, call_mmio_read(readb) -> u8);
513-
define_read!(fallible, try_read16, call_mmio_read(readw) -> u16);
514-
define_read!(fallible, try_read32, call_mmio_read(readl) -> u32);
515-
define_read!(
559+
io_define_read!(fallible, try_read8, call_mmio_read(readb) -> u8);
560+
io_define_read!(fallible, try_read16, call_mmio_read(readw) -> u16);
561+
io_define_read!(fallible, try_read32, call_mmio_read(readl) -> u32);
562+
io_define_read!(
516563
fallible,
517564
#[cfg(CONFIG_64BIT)]
518565
try_read64,
519566
call_mmio_read(readq) -> u64
520567
);
521568

522-
define_write!(fallible, try_write8, call_mmio_write(writeb) <- u8);
523-
define_write!(fallible, try_write16, call_mmio_write(writew) <- u16);
524-
define_write!(fallible, try_write32, call_mmio_write(writel) <- u32);
525-
define_write!(
569+
io_define_write!(fallible, try_write8, call_mmio_write(writeb) <- u8);
570+
io_define_write!(fallible, try_write16, call_mmio_write(writew) <- u16);
571+
io_define_write!(fallible, try_write32, call_mmio_write(writel) <- u32);
572+
io_define_write!(
526573
fallible,
527574
#[cfg(CONFIG_64BIT)]
528575
try_write64,
529576
call_mmio_write(writeq) <- u64
530577
);
531578

532-
define_read!(infallible, read8, call_mmio_read(readb) -> u8);
533-
define_read!(infallible, read16, call_mmio_read(readw) -> u16);
534-
define_read!(infallible, read32, call_mmio_read(readl) -> u32);
535-
define_read!(
579+
io_define_read!(infallible, read8, call_mmio_read(readb) -> u8);
580+
io_define_read!(infallible, read16, call_mmio_read(readw) -> u16);
581+
io_define_read!(infallible, read32, call_mmio_read(readl) -> u32);
582+
io_define_read!(
536583
infallible,
537584
#[cfg(CONFIG_64BIT)]
538585
read64,
539586
call_mmio_read(readq) -> u64
540587
);
541588

542-
define_write!(infallible, write8, call_mmio_write(writeb) <- u8);
543-
define_write!(infallible, write16, call_mmio_write(writew) <- u16);
544-
define_write!(infallible, write32, call_mmio_write(writel) <- u32);
545-
define_write!(
589+
io_define_write!(infallible, write8, call_mmio_write(writeb) <- u8);
590+
io_define_write!(infallible, write16, call_mmio_write(writew) <- u16);
591+
io_define_write!(infallible, write32, call_mmio_write(writel) <- u32);
592+
io_define_write!(
546593
infallible,
547594
#[cfg(CONFIG_64BIT)]
548595
write64,
@@ -566,40 +613,40 @@ impl<const SIZE: usize> Mmio<SIZE> {
566613
unsafe { &*core::ptr::from_ref(raw).cast() }
567614
}
568615

569-
define_read!(infallible, pub read8_relaxed, call_mmio_read(readb_relaxed) -> u8);
570-
define_read!(infallible, pub read16_relaxed, call_mmio_read(readw_relaxed) -> u16);
571-
define_read!(infallible, pub read32_relaxed, call_mmio_read(readl_relaxed) -> u32);
572-
define_read!(
616+
io_define_read!(infallible, pub read8_relaxed, call_mmio_read(readb_relaxed) -> u8);
617+
io_define_read!(infallible, pub read16_relaxed, call_mmio_read(readw_relaxed) -> u16);
618+
io_define_read!(infallible, pub read32_relaxed, call_mmio_read(readl_relaxed) -> u32);
619+
io_define_read!(
573620
infallible,
574621
#[cfg(CONFIG_64BIT)]
575622
pub read64_relaxed,
576623
call_mmio_read(readq_relaxed) -> u64
577624
);
578625

579-
define_read!(fallible, pub try_read8_relaxed, call_mmio_read(readb_relaxed) -> u8);
580-
define_read!(fallible, pub try_read16_relaxed, call_mmio_read(readw_relaxed) -> u16);
581-
define_read!(fallible, pub try_read32_relaxed, call_mmio_read(readl_relaxed) -> u32);
582-
define_read!(
626+
io_define_read!(fallible, pub try_read8_relaxed, call_mmio_read(readb_relaxed) -> u8);
627+
io_define_read!(fallible, pub try_read16_relaxed, call_mmio_read(readw_relaxed) -> u16);
628+
io_define_read!(fallible, pub try_read32_relaxed, call_mmio_read(readl_relaxed) -> u32);
629+
io_define_read!(
583630
fallible,
584631
#[cfg(CONFIG_64BIT)]
585632
pub try_read64_relaxed,
586633
call_mmio_read(readq_relaxed) -> u64
587634
);
588635

589-
define_write!(infallible, pub write8_relaxed, call_mmio_write(writeb_relaxed) <- u8);
590-
define_write!(infallible, pub write16_relaxed, call_mmio_write(writew_relaxed) <- u16);
591-
define_write!(infallible, pub write32_relaxed, call_mmio_write(writel_relaxed) <- u32);
592-
define_write!(
636+
io_define_write!(infallible, pub write8_relaxed, call_mmio_write(writeb_relaxed) <- u8);
637+
io_define_write!(infallible, pub write16_relaxed, call_mmio_write(writew_relaxed) <- u16);
638+
io_define_write!(infallible, pub write32_relaxed, call_mmio_write(writel_relaxed) <- u32);
639+
io_define_write!(
593640
infallible,
594641
#[cfg(CONFIG_64BIT)]
595642
pub write64_relaxed,
596643
call_mmio_write(writeq_relaxed) <- u64
597644
);
598645

599-
define_write!(fallible, pub try_write8_relaxed, call_mmio_write(writeb_relaxed) <- u8);
600-
define_write!(fallible, pub try_write16_relaxed, call_mmio_write(writew_relaxed) <- u16);
601-
define_write!(fallible, pub try_write32_relaxed, call_mmio_write(writel_relaxed) <- u32);
602-
define_write!(
646+
io_define_write!(fallible, pub try_write8_relaxed, call_mmio_write(writeb_relaxed) <- u8);
647+
io_define_write!(fallible, pub try_write16_relaxed, call_mmio_write(writew_relaxed) <- u16);
648+
io_define_write!(fallible, pub try_write32_relaxed, call_mmio_write(writel_relaxed) <- u32);
649+
io_define_write!(
603650
fallible,
604651
#[cfg(CONFIG_64BIT)]
605652
pub try_write64_relaxed,

rust/kernel/pci/io.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use crate::{
88
device,
99
devres::Devres,
1010
io::{
11-
define_read,
12-
define_write,
11+
io_define_read,
12+
io_define_write,
1313
Io,
1414
IoCapable,
1515
IoKnownSize,
@@ -88,7 +88,7 @@ pub struct ConfigSpace<'a, S: ConfigSpaceKind = Extended> {
8888
/// Internal helper macros used to invoke C PCI configuration space read functions.
8989
///
9090
/// This macro is intended to be used by higher-level PCI configuration space access macros
91-
/// (define_read) and provides a unified expansion for infallible vs. fallible read semantics. It
91+
/// (io_define_read) and provides a unified expansion for infallible vs. fallible read semantics. It
9292
/// emits a direct call into the corresponding C helper and performs the required cast to the Rust
9393
/// return type.
9494
///
@@ -117,9 +117,9 @@ macro_rules! call_config_read {
117117
/// Internal helper macros used to invoke C PCI configuration space write functions.
118118
///
119119
/// This macro is intended to be used by higher-level PCI configuration space access macros
120-
/// (define_write) and provides a unified expansion for infallible vs. fallible read semantics. It
121-
/// emits a direct call into the corresponding C helper and performs the required cast to the Rust
122-
/// return type.
120+
/// (io_define_write) and provides a unified expansion for infallible vs. fallible read semantics.
121+
/// It emits a direct call into the corresponding C helper and performs the required cast to the
122+
/// Rust return type.
123123
///
124124
/// # Parameters
125125
///
@@ -163,13 +163,13 @@ impl<'a, S: ConfigSpaceKind> Io for ConfigSpace<'a, S> {
163163
// PCI configuration space does not support fallible operations.
164164
// The default implementations from the Io trait are not used.
165165

166-
define_read!(infallible, read8, call_config_read(pci_read_config_byte) -> u8);
167-
define_read!(infallible, read16, call_config_read(pci_read_config_word) -> u16);
168-
define_read!(infallible, read32, call_config_read(pci_read_config_dword) -> u32);
166+
io_define_read!(infallible, read8, call_config_read(pci_read_config_byte) -> u8);
167+
io_define_read!(infallible, read16, call_config_read(pci_read_config_word) -> u16);
168+
io_define_read!(infallible, read32, call_config_read(pci_read_config_dword) -> u32);
169169

170-
define_write!(infallible, write8, call_config_write(pci_write_config_byte) <- u8);
171-
define_write!(infallible, write16, call_config_write(pci_write_config_word) <- u16);
172-
define_write!(infallible, write32, call_config_write(pci_write_config_dword) <- u32);
170+
io_define_write!(infallible, write8, call_config_write(pci_write_config_byte) <- u8);
171+
io_define_write!(infallible, write16, call_config_write(pci_write_config_word) <- u16);
172+
io_define_write!(infallible, write32, call_config_write(pci_write_config_dword) <- u32);
173173
}
174174

175175
impl<'a, S: ConfigSpaceKind> IoKnownSize for ConfigSpace<'a, S> {

0 commit comments

Comments
 (0)