Skip to content

Commit ec966c7

Browse files
authored
Merge pull request #322 from nbdd0121/macros
Implement a `#[vtable]` macro
2 parents b3e8654 + d2b8246 commit ec966c7

File tree

15 files changed

+187
-237
lines changed

15 files changed

+187
-237
lines changed

Diff for: drivers/android/process.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -805,12 +805,11 @@ impl IoctlHandler for Process {
805805
}
806806
}
807807

808+
#[vtable]
808809
impl file::Operations for Process {
809810
type Data = Ref<Self>;
810811
type OpenData = Ref<Context>;
811812

812-
kernel::declare_file_operations!(ioctl, compat_ioctl, mmap, poll);
813-
814813
fn open(ctx: &Ref<Context>, file: &File) -> Result<Self::Data> {
815814
Self::new(ctx.clone(), file.cred().into())
816815
}

Diff for: drivers/char/hw_random/bcm2835_rng_rust.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ module_platform_driver! {
1717

1818
struct RngDevice;
1919

20+
#[vtable]
2021
impl file::Operations for RngDevice {
21-
kernel::declare_file_operations!(read);
22-
2322
fn open(_open_data: &(), _file: &File) -> Result {
2423
Ok(())
2524
}

Diff for: drivers/gpio/gpio_pl061_rust.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,10 @@ type DeviceData = device::Data<PL061Registrations, PL061Resources, PL061Data>;
5555

5656
struct PL061Device;
5757

58+
#[vtable]
5859
impl gpio::Chip for PL061Device {
5960
type Data = Ref<DeviceData>;
6061

61-
kernel::declare_gpio_chip_operations!(
62-
get_direction,
63-
direction_input,
64-
direction_output,
65-
get,
66-
set
67-
);
68-
6962
fn get_direction(data: RefBorrow<'_, DeviceData>, offset: u32) -> Result<gpio::LineDirection> {
7063
let pl061 = data.resources().ok_or(ENXIO)?;
7164
Ok(if pl061.base.readb(GPIODIR) & bit(offset) != 0 {
@@ -129,11 +122,10 @@ impl gpio::ChipWithIrqChip for PL061Device {
129122
}
130123
}
131124

125+
#[vtable]
132126
impl irq::Chip for PL061Device {
133127
type Data = Ref<DeviceData>;
134128

135-
kernel::declare_irq_chip_operations!(set_type, set_wake);
136-
137129
fn set_type(
138130
data: RefBorrow<'_, DeviceData>,
139131
irq_data: &mut LockedIrqData,

Diff for: rust/kernel/file.rs

+12-76
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
};
2020
use core::convert::{TryFrom, TryInto};
2121
use core::{cell::UnsafeCell, marker, mem, ptr};
22+
use macros::vtable;
2223

2324
/// Wraps the kernel's `struct file`.
2425
///
@@ -468,24 +469,24 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
468469
const VTABLE: bindings::file_operations = bindings::file_operations {
469470
open: Some(Self::open_callback),
470471
release: Some(Self::release_callback),
471-
read: if T::TO_USE.read {
472+
read: if T::HAS_READ {
472473
Some(Self::read_callback)
473474
} else {
474475
None
475476
},
476-
write: if T::TO_USE.write {
477+
write: if T::HAS_WRITE {
477478
Some(Self::write_callback)
478479
} else {
479480
None
480481
},
481-
llseek: if T::TO_USE.seek {
482+
llseek: if T::HAS_SEEK {
482483
Some(Self::llseek_callback)
483484
} else {
484485
None
485486
},
486487

487488
check_flags: None,
488-
compat_ioctl: if T::TO_USE.compat_ioctl {
489+
compat_ioctl: if T::HAS_COMPAT_IOCTL {
489490
Some(Self::compat_ioctl_callback)
490491
} else {
491492
None
@@ -496,7 +497,7 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
496497
fasync: None,
497498
flock: None,
498499
flush: None,
499-
fsync: if T::TO_USE.fsync {
500+
fsync: if T::HAS_FSYNC {
500501
Some(Self::fsync_callback)
501502
} else {
502503
None
@@ -506,19 +507,19 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
506507
iterate_shared: None,
507508
iopoll: None,
508509
lock: None,
509-
mmap: if T::TO_USE.mmap {
510+
mmap: if T::HAS_MMAP {
510511
Some(Self::mmap_callback)
511512
} else {
512513
None
513514
},
514515
mmap_supported_flags: 0,
515516
owner: ptr::null_mut(),
516-
poll: if T::TO_USE.poll {
517+
poll: if T::HAS_POLL {
517518
Some(Self::poll_callback)
518519
} else {
519520
None
520521
},
521-
read_iter: if T::TO_USE.read_iter {
522+
read_iter: if T::HAS_READ {
522523
Some(Self::read_iter_callback)
523524
} else {
524525
None
@@ -529,13 +530,13 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
529530
show_fdinfo: None,
530531
splice_read: None,
531532
splice_write: None,
532-
unlocked_ioctl: if T::TO_USE.ioctl {
533+
unlocked_ioctl: if T::HAS_IOCTL {
533534
Some(Self::unlocked_ioctl_callback)
534535
} else {
535536
None
536537
},
537538
uring_cmd: None,
538-
write_iter: if T::TO_USE.write_iter {
539+
write_iter: if T::HAS_WRITE {
539540
Some(Self::write_iter_callback)
540541
} else {
541542
None
@@ -552,69 +553,6 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
552553
}
553554
}
554555

555-
/// Represents which fields of [`struct file_operations`] should be populated with pointers.
556-
pub struct ToUse {
557-
/// The `read` field of [`struct file_operations`].
558-
pub read: bool,
559-
560-
/// The `read_iter` field of [`struct file_operations`].
561-
pub read_iter: bool,
562-
563-
/// The `write` field of [`struct file_operations`].
564-
pub write: bool,
565-
566-
/// The `write_iter` field of [`struct file_operations`].
567-
pub write_iter: bool,
568-
569-
/// The `llseek` field of [`struct file_operations`].
570-
pub seek: bool,
571-
572-
/// The `unlocked_ioctl` field of [`struct file_operations`].
573-
pub ioctl: bool,
574-
575-
/// The `compat_ioctl` field of [`struct file_operations`].
576-
pub compat_ioctl: bool,
577-
578-
/// The `fsync` field of [`struct file_operations`].
579-
pub fsync: bool,
580-
581-
/// The `mmap` field of [`struct file_operations`].
582-
pub mmap: bool,
583-
584-
/// The `poll` field of [`struct file_operations`].
585-
pub poll: bool,
586-
}
587-
588-
/// A constant version where all values are to set to `false`, that is, all supported fields will
589-
/// be set to null pointers.
590-
pub const USE_NONE: ToUse = ToUse {
591-
read: false,
592-
read_iter: false,
593-
write: false,
594-
write_iter: false,
595-
seek: false,
596-
ioctl: false,
597-
compat_ioctl: false,
598-
fsync: false,
599-
mmap: false,
600-
poll: false,
601-
};
602-
603-
/// Defines the [`Operations::TO_USE`] field based on a list of fields to be populated.
604-
#[macro_export]
605-
macro_rules! declare_file_operations {
606-
() => {
607-
const TO_USE: $crate::file::ToUse = $crate::file::USE_NONE;
608-
};
609-
($($i:ident),+) => {
610-
const TO_USE: kernel::file::ToUse =
611-
$crate::file::ToUse {
612-
$($i: true),+ ,
613-
..$crate::file::USE_NONE
614-
};
615-
};
616-
}
617-
618556
/// Allows the handling of ioctls defined with the `_IO`, `_IOR`, `_IOW`, and `_IOWR` macros.
619557
///
620558
/// For each macro, there is a handler function that takes the appropriate types as arguments.
@@ -742,10 +680,8 @@ pub trait OpenAdapter<T: Sync> {
742680
/// File descriptors may be used from multiple threads/processes concurrently, so your type must be
743681
/// [`Sync`]. It must also be [`Send`] because [`Operations::release`] will be called from the
744682
/// thread that decrements that associated file's refcount to zero.
683+
#[vtable]
745684
pub trait Operations {
746-
/// The methods to use to populate [`struct file_operations`].
747-
const TO_USE: ToUse;
748-
749685
/// The type of the context data returned by [`Operations::open`] and made available to
750686
/// other methods.
751687
type Data: PointerWrapper + Send + Sync = ();

Diff for: rust/kernel/gpio.rs

+12-57
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use core::{
1313
marker::{PhantomData, PhantomPinned},
1414
pin::Pin,
1515
};
16+
use macros::vtable;
1617

1718
#[cfg(CONFIG_GPIOLIB_IRQCHIP)]
1819
pub use irqchip::{ChipWithIrqChip, RegistrationWithIrqChip};
@@ -27,16 +28,13 @@ pub enum LineDirection {
2728
}
2829

2930
/// A gpio chip.
31+
#[vtable]
3032
pub trait Chip {
3133
/// Context data associated with the gpio chip.
3234
///
3335
/// It determines the type of the context data passed to each of the methods of the trait.
3436
type Data: PointerWrapper + Sync + Send;
3537

36-
/// The methods to use to populate [`struct gpio_chip`]. This is typically populated with
37-
/// [`declare_gpio_chip_operations`].
38-
const TO_USE: ToUse;
39-
4038
/// Returns the direction of the given gpio line.
4139
fn get_direction(
4240
_data: <Self::Data as PointerWrapper>::Borrowed<'_>,
@@ -73,52 +71,6 @@ pub trait Chip {
7371
fn set(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, _offset: u32, _value: bool) {}
7472
}
7573

76-
/// Represents which fields of [`struct gpio_chip`] should be populated with pointers.
77-
///
78-
/// This is typically populated with the [`declare_gpio_chip_operations`] macro.
79-
pub struct ToUse {
80-
/// The `get_direction` field of [`struct gpio_chip`].
81-
pub get_direction: bool,
82-
83-
/// The `direction_input` field of [`struct gpio_chip`].
84-
pub direction_input: bool,
85-
86-
/// The `direction_output` field of [`struct gpio_chip`].
87-
pub direction_output: bool,
88-
89-
/// The `get` field of [`struct gpio_chip`].
90-
pub get: bool,
91-
92-
/// The `set` field of [`struct gpio_chip`].
93-
pub set: bool,
94-
}
95-
96-
/// A constant version where all values are set to `false`, that is, all supported fields will be
97-
/// set to null pointers.
98-
pub const USE_NONE: ToUse = ToUse {
99-
get_direction: false,
100-
direction_input: false,
101-
direction_output: false,
102-
get: false,
103-
set: false,
104-
};
105-
106-
/// Defines the [`Chip::TO_USE`] field based on a list of fields to be populated.
107-
#[macro_export]
108-
macro_rules! declare_gpio_chip_operations {
109-
() => {
110-
const TO_USE: $crate::gpio::ToUse = $crate::gpio::USE_NONE;
111-
};
112-
($($i:ident),+) => {
113-
#[allow(clippy::needless_update)]
114-
const TO_USE: $crate::gpio::ToUse =
115-
$crate::gpio::ToUse {
116-
$($i: true),+ ,
117-
..$crate::gpio::USE_NONE
118-
};
119-
};
120-
}
121-
12274
/// A registration of a gpio chip.
12375
///
12476
/// # Examples
@@ -130,9 +82,9 @@ macro_rules! declare_gpio_chip_operations {
13082
/// use kernel::{device::RawDevice, gpio::{self, Registration}};
13183
///
13284
/// struct MyGpioChip;
85+
/// #[vtable]
13386
/// impl gpio::Chip for MyGpioChip {
13487
/// type Data = ();
135-
/// kernel::declare_gpio_chip_operations!();
13688
/// }
13789
///
13890
/// fn example(parent: &dyn RawDevice) -> Result<Pin<Box<Registration<MyGpioChip>>>> {
@@ -186,19 +138,19 @@ impl<T: Chip> Registration<T> {
186138
// Set up the callbacks.
187139
gc.request = Some(bindings::gpiochip_generic_request);
188140
gc.free = Some(bindings::gpiochip_generic_free);
189-
if T::TO_USE.get_direction {
141+
if T::HAS_GET_DIRECTION {
190142
gc.get_direction = Some(get_direction_callback::<T>);
191143
}
192-
if T::TO_USE.direction_input {
144+
if T::HAS_DIRECTION_INPUT {
193145
gc.direction_input = Some(direction_input_callback::<T>);
194146
}
195-
if T::TO_USE.direction_output {
147+
if T::HAS_DIRECTION_OUTPUT {
196148
gc.direction_output = Some(direction_output_callback::<T>);
197149
}
198-
if T::TO_USE.get {
150+
if T::HAS_GET {
199151
gc.get = Some(get_callback::<T>);
200152
}
201-
if T::TO_USE.set {
153+
if T::HAS_SET {
202154
gc.set = Some(set_callback::<T>);
203155
}
204156

@@ -475,9 +427,12 @@ mod irqchip {
475427
/// data is passed as context.
476428
struct IrqChipAdapter<T: irq::Chip>(PhantomData<T>);
477429

430+
#[vtable]
478431
impl<T: irq::Chip> irq::Chip for IrqChipAdapter<T> {
479432
type Data = *mut bindings::gpio_chip;
480-
const TO_USE: irq::ToUse = T::TO_USE;
433+
434+
const HAS_SET_TYPE: bool = T::HAS_SET_TYPE;
435+
const HAS_SET_WAKE: bool = T::HAS_SET_WAKE;
481436

482437
fn ack(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
483438
// SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the

0 commit comments

Comments
 (0)