diff --git a/drivers/char/hw_random/bcm2835_rng_rust.rs b/drivers/char/hw_random/bcm2835_rng_rust.rs index 40dddbdcd4471c..4c586c8bac838e 100644 --- a/drivers/char/hw_random/bcm2835_rng_rust.rs +++ b/drivers/char/hw_random/bcm2835_rng_rust.rs @@ -8,6 +8,7 @@ use alloc::boxed::Box; use core::pin::Pin; use kernel::of::OfMatchTable; +use kernel::platdev::PlatformDriver; use kernel::prelude::*; use kernel::{c_str, platdev}; @@ -19,6 +20,20 @@ module! { license: b"GPL v2", } +struct RngDriver; + +impl PlatformDriver for RngDriver { + fn probe(device_id: i32) -> Result { + pr_info!("probing discovered hwrng with id {}\n", device_id); + Ok(()) + } + + fn remove(device_id: i32) -> Result { + pr_info!("removing hwrng with id {}\n", device_id); + Ok(()) + } +} + struct RngModule { _pdev: Pin>, } @@ -27,7 +42,7 @@ impl KernelModule for RngModule { fn init() -> Result { let of_match_tbl = OfMatchTable::new(&c_str!("brcm,bcm2835-rng"))?; - let pdev = platdev::Registration::new_pinned( + let pdev = platdev::Registration::new_pinned::( c_str!("bcm2835-rng-rust"), Some(of_match_tbl), &THIS_MODULE, diff --git a/rust/kernel/platdev.rs b/rust/kernel/platdev.rs index c4e6061eb40440..1b79445c04df3c 100644 --- a/rust/kernel/platdev.rs +++ b/rust/kernel/platdev.rs @@ -9,8 +9,8 @@ use crate::{ bindings, c_types, error::{Error, Result}, + from_kernel_result, of::OfMatchTable, - pr_info, str::CStr, types::PointerWrapper, }; @@ -30,18 +30,30 @@ pub struct Registration { // (it is fine for multiple threads to have a shared reference to it). unsafe impl Sync for Registration {} -extern "C" fn probe_callback(_pdev: *mut bindings::platform_device) -> c_types::c_int { - pr_info!("Rust platform_device probed\n"); - 0 +extern "C" fn probe_callback( + pdev: *mut bindings::platform_device, +) -> c_types::c_int { + from_kernel_result! { + // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer. + let device_id = unsafe { (*pdev).id }; + P::probe(device_id)?; + Ok(0) + } } -extern "C" fn remove_callback(_pdev: *mut bindings::platform_device) -> c_types::c_int { - pr_info!("Rust platform_device removed\n"); - 0 +extern "C" fn remove_callback( + pdev: *mut bindings::platform_device, +) -> c_types::c_int { + from_kernel_result! { + // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer. + let device_id = unsafe { (*pdev).id }; + P::remove(device_id)?; + Ok(0) + } } impl Registration { - fn register( + fn register( self: Pin<&mut Self>, name: &'static CStr, of_match_table: Option, @@ -59,8 +71,8 @@ impl Registration { this.of_table = Some(ptr); this.pdrv.driver.of_match_table = ptr.cast(); } - this.pdrv.probe = Some(probe_callback); - this.pdrv.remove = Some(remove_callback); + this.pdrv.probe = Some(probe_callback::

); + this.pdrv.remove = Some(remove_callback::

); // SAFETY: // - `this.pdrv` lives at least until the call to `platform_driver_unregister()` returns. // - `name` pointer has static lifetime. @@ -81,13 +93,13 @@ impl Registration { /// Registers a platform device. /// /// Returns a pinned heap-allocated representation of the registration. - pub fn new_pinned( + pub fn new_pinned( name: &'static CStr, of_match_tbl: Option, module: &'static crate::ThisModule, ) -> Result>> { let mut r = Pin::from(Box::try_new(Self::default())?); - r.as_mut().register(name, of_match_tbl, module)?; + r.as_mut().register::

(name, of_match_tbl, module)?; Ok(r) } } @@ -107,3 +119,20 @@ impl Drop for Registration { } } } + +/// Trait for implementers of platform drivers. +/// +/// Implement this trait whenever you create a platform driver. +pub trait PlatformDriver { + /// Platform driver probe. + /// + /// Called when a new platform device is added or discovered. + /// Implementers should attempt to initialize the device here. + fn probe(device_id: i32) -> Result; + + /// Platform driver remove. + /// + /// Called when a platform device is removed. + /// Implementers should prepare the device for complete removal here. + fn remove(device_id: i32) -> Result; +}