Skip to content

Commit a1639e1

Browse files
committed
rust: add device::Data
Based on 9d7d482 (Fixed a few warnings.) Signed-off-by: Danilo Krummrich <[email protected]>
1 parent a74f8e8 commit a1639e1

File tree

1 file changed

+119
-1
lines changed

1 file changed

+119
-1
lines changed

rust/kernel/device.rs

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,22 @@
44
//!
55
//! C header: [`include/linux/device.h`](../../../../include/linux/device.h)
66
7-
use crate::{bindings, str::CStr};
7+
use macros::pin_data;
8+
9+
use crate::{
10+
bindings,
11+
error::Result,
12+
init::InPlaceInit,
13+
init::PinInit,
14+
pin_init,
15+
revocable::{Revocable, RevocableGuard},
16+
str::CStr,
17+
sync::{LockClassKey, RevocableMutex, UniqueArc},
18+
};
19+
use core::{
20+
ops::{Deref, DerefMut},
21+
pin::Pin,
22+
};
823

924
/// A raw device.
1025
///
@@ -95,3 +110,106 @@ impl Clone for Device {
95110
Self::from_dev(self)
96111
}
97112
}
113+
114+
/// Device data.
115+
///
116+
/// When a device is removed (for whatever reason, for example, because the device was unplugged or
117+
/// because the user decided to unbind the driver), the driver is given a chance to clean its state
118+
/// up, and all io resources should ideally not be used anymore.
119+
///
120+
/// However, the device data is reference-counted because other subsystems hold pointers to it. So
121+
/// some device state must be freed and not used anymore, while others must remain accessible.
122+
///
123+
/// This struct separates the device data into three categories:
124+
/// 1. Registrations: are destroyed when the device is removed, but before the io resources
125+
/// become inaccessible.
126+
/// 2. Io resources: are available until the device is removed.
127+
/// 3. General data: remain available as long as the ref count is nonzero.
128+
///
129+
/// This struct implements the `DeviceRemoval` trait so that it can clean resources up even if not
130+
/// explicitly called by the device drivers.
131+
#[pin_data]
132+
pub struct Data<T, U, V> {
133+
#[pin]
134+
registrations: RevocableMutex<T>,
135+
#[pin]
136+
resources: Revocable<U>,
137+
#[pin]
138+
general: V,
139+
}
140+
141+
/// Safely creates an new reference-counted instance of [`Data`].
142+
#[doc(hidden)]
143+
#[macro_export]
144+
macro_rules! new_device_data {
145+
($reg:expr, $res:expr, $gen:expr, $name:literal) => {{
146+
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
147+
let regs = $reg;
148+
let res = $res;
149+
let gen = $gen;
150+
let name = $crate::c_str!($name);
151+
$crate::device::Data::try_new(regs, res, gen, name, &CLASS1)
152+
}};
153+
}
154+
155+
impl<T, U, V> Data<T, U, V> {
156+
/// Creates a new instance of `Data`.
157+
///
158+
/// It is recommended that the [`new_device_data`] macro be used as it automatically creates
159+
/// the lock classes.
160+
pub fn try_new(
161+
registrations: T,
162+
resources: impl PinInit<U>,
163+
general: impl PinInit<V>,
164+
name: &'static CStr,
165+
key1: &'static LockClassKey,
166+
) -> Result<Pin<UniqueArc<Self>>> {
167+
let ret = UniqueArc::pin_init(pin_init!(Self {
168+
registrations <- RevocableMutex::new(
169+
registrations,
170+
name,
171+
key1,
172+
),
173+
resources <- Revocable::new(resources),
174+
general <- general,
175+
}))?;
176+
177+
Ok(ret)
178+
}
179+
180+
/// Returns the resources if they're still available.
181+
pub fn resources(&self) -> Option<RevocableGuard<'_, U>> {
182+
self.resources.try_access()
183+
}
184+
185+
/// Returns the locked registrations if they're still available.
186+
#[cfg(disabled)]
187+
pub fn registrations(&self) -> Option<RevocableMutexGuard<'_, T>> {
188+
self.registrations.try_write()
189+
}
190+
}
191+
192+
impl<T, U, V> crate::driver::DeviceRemoval for Data<T, U, V> {
193+
fn device_remove(&self) {
194+
// We revoke the registrations first so that resources are still available to them during
195+
// unregistration.
196+
self.registrations.revoke();
197+
198+
// Release resources now. General data remains available.
199+
self.resources.revoke();
200+
}
201+
}
202+
203+
impl<T, U, V> Deref for Data<T, U, V> {
204+
type Target = V;
205+
206+
fn deref(&self) -> &V {
207+
&self.general
208+
}
209+
}
210+
211+
impl<T, U, V> DerefMut for Data<T, U, V> {
212+
fn deref_mut(&mut self) -> &mut V {
213+
&mut self.general
214+
}
215+
}

0 commit comments

Comments
 (0)