Skip to content

Commit ef320da

Browse files
authored
Merge pull request torvalds#640 from wedsonaf/miscdev-opts
rust: add optional parameters to the registration of misc devices
2 parents 736e9af + 4a89f74 commit ef320da

File tree

5 files changed

+103
-18
lines changed

5 files changed

+103
-18
lines changed

drivers/android/rust_binder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct BinderModule {
105105
impl KernelModule for BinderModule {
106106
fn init(name: &'static CStr, _module: &'static kernel::ThisModule) -> Result<Self> {
107107
let ctx = Context::new()?;
108-
let reg = Registration::new_pinned(name, None, ctx)?;
108+
let reg = Registration::new_pinned(name, ctx)?;
109109
Ok(Self { _reg: reg })
110110
}
111111
}

drivers/char/hw_random/bcm2835_rng_rust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl platform::Driver for RngDriver {
5757
data.registrations()
5858
.ok_or(Error::ENXIO)?
5959
.as_pinned_mut()
60-
.register(c_str!("rust_hwrng"), None, ())?;
60+
.register(c_str!("rust_hwrng"), ())?;
6161
Ok(data.into())
6262
}
6363
}

rust/kernel/miscdev.rs

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,89 @@
99
use crate::bindings;
1010
use crate::error::{Error, Result};
1111
use crate::file_operations::{FileOpenAdapter, FileOperations, FileOperationsVtable};
12-
use crate::{str::CStr, KernelModule, ThisModule};
12+
use crate::{device, str::CStr, KernelModule, ThisModule};
1313
use alloc::boxed::Box;
1414
use core::marker::PhantomPinned;
1515
use core::{mem::MaybeUninit, pin::Pin};
1616

17+
/// Options which can be used to configure how a misc device is registered.
18+
///
19+
/// # Examples
20+
///
21+
/// ```
22+
/// # use kernel::{c_str, device::RawDevice, file_operations::FileOperations, miscdev, prelude::*};
23+
/// pub fn example(
24+
/// reg: Pin<&mut miscdev::Registration<impl FileOperations<OpenData = ()>>>,
25+
/// parent: &dyn RawDevice,
26+
/// ) -> Result {
27+
/// miscdev::Options::new()
28+
/// .mode(0o600)
29+
/// .minor(10)
30+
/// .parent(parent)
31+
/// .register(reg, c_str!("sample"), ())
32+
/// }
33+
/// ```
34+
#[derive(Default)]
35+
pub struct Options<'a> {
36+
minor: Option<i32>,
37+
mode: Option<u16>,
38+
parent: Option<&'a dyn device::RawDevice>,
39+
}
40+
41+
impl<'a> Options<'a> {
42+
/// Creates new [`Options`] instance with the required fields.
43+
pub const fn new() -> Self {
44+
Self {
45+
minor: None,
46+
mode: None,
47+
parent: None,
48+
}
49+
}
50+
51+
/// Sets the minor device number.
52+
pub const fn minor(&mut self, v: i32) -> &mut Self {
53+
self.minor = Some(v);
54+
self
55+
}
56+
57+
/// Sets the device mode.
58+
///
59+
/// This is usually an octal number and describes who can perform read/write/execute operations
60+
/// on the device.
61+
pub const fn mode(&mut self, m: u16) -> &mut Self {
62+
self.mode = Some(m);
63+
self
64+
}
65+
66+
/// Sets the device parent.
67+
pub const fn parent(&mut self, p: &'a dyn device::RawDevice) -> &mut Self {
68+
self.parent = Some(p);
69+
self
70+
}
71+
72+
/// Registers a misc device using the configured options.
73+
pub fn register<T: FileOperations>(
74+
&self,
75+
reg: Pin<&mut Registration<T>>,
76+
name: &'static CStr,
77+
open_data: T::OpenData,
78+
) -> Result {
79+
reg.register_with_options(name, open_data, self)
80+
}
81+
82+
/// Allocates a new registration of a misc device and completes the registration with the
83+
/// configured options.
84+
pub fn register_new<T: FileOperations>(
85+
&self,
86+
name: &'static CStr,
87+
open_data: T::OpenData,
88+
) -> Result<Pin<Box<Registration<T>>>> {
89+
let mut r = Pin::from(Box::try_new(Registration::new())?);
90+
self.register(r.as_mut(), name, open_data)?;
91+
Ok(r)
92+
}
93+
}
94+
1795
/// A registration of a miscellaneous device.
1896
///
1997
/// # Invariants
@@ -46,25 +124,28 @@ impl<T: FileOperations> Registration<T> {
46124
/// Registers a miscellaneous device.
47125
///
48126
/// Returns a pinned heap-allocated representation of the registration.
49-
pub fn new_pinned(
50-
name: &'static CStr,
51-
minor: Option<i32>,
52-
open_data: T::OpenData,
53-
) -> Result<Pin<Box<Self>>> {
54-
let mut r = Pin::from(Box::try_new(Self::new())?);
55-
r.as_mut().register(name, minor, open_data)?;
56-
Ok(r)
127+
pub fn new_pinned(name: &'static CStr, open_data: T::OpenData) -> Result<Pin<Box<Self>>> {
128+
Options::new().register_new(name, open_data)
57129
}
58130

59131
/// Registers a miscellaneous device with the rest of the kernel.
60132
///
61133
/// It must be pinned because the memory block that represents the registration is
62-
/// self-referential. If a minor is not given, the kernel allocates a new one if possible.
63-
pub fn register(
134+
/// self-referential.
135+
pub fn register(self: Pin<&mut Self>, name: &'static CStr, open_data: T::OpenData) -> Result {
136+
Options::new().register(self, name, open_data)
137+
}
138+
139+
/// Registers a miscellaneous device with the rest of the kernel. Additional optional settings
140+
/// are provided via the `opts` parameter.
141+
///
142+
/// It must be pinned because the memory block that represents the registration is
143+
/// self-referential.
144+
pub fn register_with_options(
64145
self: Pin<&mut Self>,
65146
name: &'static CStr,
66-
minor: Option<i32>,
67147
open_data: T::OpenData,
148+
opts: &Options<'_>,
68149
) -> Result {
69150
// SAFETY: We must ensure that we never move out of `this`.
70151
let this = unsafe { self.get_unchecked_mut() };
@@ -76,7 +157,11 @@ impl<T: FileOperations> Registration<T> {
76157
// SAFETY: The adapter is compatible with `misc_register`.
77158
this.mdev.fops = unsafe { FileOperationsVtable::<Self, T>::build() };
78159
this.mdev.name = name.as_char_ptr();
79-
this.mdev.minor = minor.unwrap_or(bindings::MISC_DYNAMIC_MINOR as i32);
160+
this.mdev.minor = opts.minor.unwrap_or(bindings::MISC_DYNAMIC_MINOR as i32);
161+
this.mdev.mode = opts.mode.unwrap_or(0);
162+
this.mdev.parent = opts
163+
.parent
164+
.map_or(core::ptr::null_mut(), |p| p.raw_device());
80165

81166
// We write to `open_data` here because as soon as `misc_register` succeeds, the file can be
82167
// opened, so we need `open_data` configured ahead of time.
@@ -150,7 +235,7 @@ pub struct Module<T: FileOperations<OpenData = ()>> {
150235
impl<T: FileOperations<OpenData = ()>> KernelModule for Module<T> {
151236
fn init(name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
152237
Ok(Self {
153-
_dev: Registration::new_pinned(name, None, ())?,
238+
_dev: Registration::new_pinned(name, ())?,
154239
})
155240
}
156241
}

samples/rust/rust_miscdev.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl KernelModule for RustMiscdev {
132132
let state = SharedState::try_new()?;
133133

134134
Ok(RustMiscdev {
135-
_dev: miscdev::Registration::new_pinned(name, None, state)?,
135+
_dev: miscdev::Registration::new_pinned(name, state)?,
136136
})
137137
}
138138
}

samples/rust/rust_semaphore.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl KernelModule for RustSemaphore {
133133
mutex_init!(pinned, "Semaphore::inner");
134134

135135
Ok(Self {
136-
_dev: Registration::new_pinned(name, None, sema.into())?,
136+
_dev: Registration::new_pinned(name, sema.into())?,
137137
})
138138
}
139139
}

0 commit comments

Comments
 (0)