diff options
author | Lee Jones <lee@kernel.org> | 2024-12-13 16:47:08 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-12-16 18:12:53 +0300 |
commit | 42523ceba5f6735df4d02c6982d1733a1465afbd (patch) | |
tree | ae74fb42d3fc169b524973d9b4fd8cb8fb6b049c /samples/rust/rust_misc_device.rs | |
parent | fdb1ac6c302689b286eca9bb7247111bffc7db17 (diff) | |
download | linux-42523ceba5f6735df4d02c6982d1733a1465afbd.tar.xz |
samples: rust_misc_device: Demonstrate additional get/set value functionality
Expand the complexity of the sample driver by providing the ability to
get and set an integer. The value is protected by a mutex.
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20241213134715.601415-4-lee@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'samples/rust/rust_misc_device.rs')
-rw-r--r-- | samples/rust/rust_misc_device.rs | 89 |
1 files changed, 75 insertions, 14 deletions
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs index 324c3696ae3f..ae1474a451f1 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -4,17 +4,24 @@ //! Rust misc device sample. +use core::pin::Pin; + use kernel::{ c_str, device::Device, fs::File, - ioctl::_IO, + ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, + new_mutex, prelude::*, + sync::Mutex, types::ARef, + uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, }; const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80); +const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x81); +const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x82); module! { type: RustMiscDeviceModule, @@ -44,44 +51,98 @@ impl kernel::InPlaceModule for RustMiscDeviceModule { } } +struct Inner { + value: i32, +} + +#[pin_data(PinnedDrop)] struct RustMiscDevice { + #[pin] + inner: Mutex<Inner>, dev: ARef<Device>, } #[vtable] impl MiscDevice for RustMiscDevice { - type Ptr = KBox<Self>; + type Ptr = Pin<KBox<Self>>; - fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<KBox<Self>> { + fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<Pin<KBox<Self>>> { let dev = ARef::from(misc.device()); dev_info!(dev, "Opening Rust Misc Device Sample\n"); - Ok(KBox::new(RustMiscDevice { dev }, GFP_KERNEL)?) + KBox::try_pin_init( + try_pin_init! { + RustMiscDevice { + inner <- new_mutex!( Inner{ value: 0_i32 } ), + dev: dev, + } + }, + GFP_KERNEL, + ) } - fn ioctl( - me: <Self::Ptr as kernel::types::ForeignOwnable>::Borrowed<'_>, - _file: &File, - cmd: u32, - _arg: usize, - ) -> Result<isize> { + fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result<isize> { dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n"); + let size = _IOC_SIZE(cmd); + match cmd { - RUST_MISC_DEV_HELLO => dev_info!(me.dev, "Hello from the Rust Misc Device\n"), + RUST_MISC_DEV_GET_VALUE => me.get_value(UserSlice::new(arg, size).writer())?, + RUST_MISC_DEV_SET_VALUE => me.set_value(UserSlice::new(arg, size).reader())?, + RUST_MISC_DEV_HELLO => me.hello()?, _ => { dev_err!(me.dev, "-> IOCTL not recognised: {}\n", cmd); return Err(ENOTTY); } - } + }; Ok(0) } } -impl Drop for RustMiscDevice { - fn drop(&mut self) { +#[pinned_drop] +impl PinnedDrop for RustMiscDevice { + fn drop(self: Pin<&mut Self>) { dev_info!(self.dev, "Exiting the Rust Misc Device Sample\n"); } } + +impl RustMiscDevice { + fn set_value(&self, mut reader: UserSliceReader) -> Result<isize> { + let new_value = reader.read::<i32>()?; + let mut guard = self.inner.lock(); + + dev_info!( + self.dev, + "-> Copying data from userspace (value: {})\n", + new_value + ); + + guard.value = new_value; + Ok(0) + } + + fn get_value(&self, mut writer: UserSliceWriter) -> Result<isize> { + let guard = self.inner.lock(); + let value = guard.value; + + // Free-up the lock and use our locally cached instance from here + drop(guard); + + dev_info!( + self.dev, + "-> Copying data to userspace (value: {})\n", + &value + ); + + writer.write::<i32>(&value)?; + Ok(0) + } + + fn hello(&self) -> Result<isize> { + dev_info!(self.dev, "-> Hello from the Rust Misc Device\n"); + + Ok(0) + } +} |