Skip to content

Commit 2140b58

Browse files
committed
rust: take lock class keys when registering gpio chips
We also define macros to automatically define the keys. This fixes the following warning when booting with lockdep enabled: [ 1.100169] DEBUG_LOCKS_WARN_ON(!key) [ 1.100752] WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:4831 lockdep_init_map_type+0x238/0x288 Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
1 parent c810c92 commit 2140b58

File tree

3 files changed

+84
-10
lines changed

3 files changed

+84
-10
lines changed

drivers/gpio/gpio_pl061_rust.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,15 @@ impl amba::Driver for PL061Device {
297297

298298
data.resources().ok_or(ENXIO)?.base.writeb(0, GPIOIE); // disable irqs
299299

300-
data.registrations()
301-
.ok_or(ENXIO)?
302-
.as_pinned_mut()
303-
.register::<Self>(PL061_GPIO_NR, None, dev, data.clone(), irq)?;
300+
kernel::gpio_irq_chip_register!(
301+
data.registrations().ok_or(ENXIO)?.as_pinned_mut(),
302+
Self,
303+
PL061_GPIO_NR,
304+
None,
305+
dev,
306+
data.clone(),
307+
irq
308+
)?;
304309

305310
dev_info!(data.dev, "PL061 GPIO chip registered\n");
306311

rust/kernel/gpio.rs

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
//! C header: [`include/linux/gpio/driver.h`](../../../../include/linux/gpio/driver.h)
66
77
use crate::{
8-
bindings, device, error::code::*, error::from_kernel_result, types::PointerWrapper, Error,
9-
Result,
8+
bindings, device, error::code::*, error::from_kernel_result, sync::LockClassKey,
9+
types::PointerWrapper, Error, Result,
1010
};
1111
use core::{
1212
cell::UnsafeCell,
@@ -120,6 +120,27 @@ macro_rules! declare_gpio_chip_operations {
120120
}
121121

122122
/// A registration of a gpio chip.
123+
///
124+
/// # Examples
125+
///
126+
/// The following example registers an empty gpio chip.
127+
///
128+
/// ```
129+
/// # use kernel::prelude::*;
130+
/// use kernel::{device::RawDevice, gpio::{self, Registration}};
131+
///
132+
/// struct MyGpioChip;
133+
/// impl gpio::Chip for MyGpioChip {
134+
/// type Data = ();
135+
/// kernel::declare_gpio_chip_operations!();
136+
/// }
137+
///
138+
/// fn example(parent: &dyn RawDevice) -> Result<Pin<Box<Registration<MyGpioChip>>>> {
139+
/// let mut r = Pin::from(Box::try_new(Registration::new())?);
140+
/// kernel::gpio_chip_register!(r.as_mut(), 32, None, parent, ())?;
141+
/// Ok(r)
142+
/// }
143+
/// ```
123144
pub struct Registration<T: Chip> {
124145
gc: UnsafeCell<bindings::gpio_chip>,
125146
parent: Option<device::Device>,
@@ -141,12 +162,16 @@ impl<T: Chip> Registration<T> {
141162
}
142163

143164
/// Registers a gpio chip with the rest of the kernel.
165+
///
166+
/// Users are encouraged to use the [`gpio_chip_register`] macro because it automatically
167+
/// defines the lock classes and calls the registration function.
144168
pub fn register(
145169
self: Pin<&mut Self>,
146170
gpio_count: u16,
147171
base: Option<i32>,
148172
parent: &dyn device::RawDevice,
149173
data: T::Data,
174+
lock_keys: [&'static LockClassKey; 2],
150175
) -> Result {
151176
if self.parent.is_some() {
152177
// Already registered.
@@ -197,8 +222,8 @@ impl<T: Chip> Registration<T> {
197222
bindings::gpiochip_add_data_with_key(
198223
this.gc.get(),
199224
data_pointer as _,
200-
core::ptr::null_mut(),
201-
core::ptr::null_mut(),
225+
lock_keys[0].get(),
226+
lock_keys[1].get(),
202227
)
203228
};
204229
if ret < 0 {
@@ -247,6 +272,25 @@ impl<T: Chip> Drop for Registration<T> {
247272
}
248273
}
249274

275+
/// Registers a gpio chip with the rest of the kernel.
276+
///
277+
/// It automatically defines the required lock classes.
278+
#[macro_export]
279+
macro_rules! gpio_chip_register {
280+
($reg:expr, $count:expr, $base:expr, $parent:expr, $data:expr $(,)?) => {{
281+
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
282+
static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
283+
$crate::gpio::Registration::register(
284+
$reg,
285+
$count,
286+
$base,
287+
$parent,
288+
$data,
289+
[&CLASS1, &CLASS2],
290+
)
291+
}};
292+
}
293+
250294
unsafe extern "C" fn get_direction_callback<T: Chip>(
251295
gc: *mut bindings::gpio_chip,
252296
offset: core::ffi::c_uint,
@@ -340,13 +384,17 @@ mod irqchip {
340384
}
341385

342386
/// Registers a gpio chip and its irq chip with the rest of the kernel.
387+
///
388+
/// Users are encouraged to use the [`gpio_irq_chip_register`] macro because it
389+
/// automatically defines the lock classes and calls the registration function.
343390
pub fn register<U: irq::Chip<Data = T::Data>>(
344391
mut self: Pin<&mut Self>,
345392
gpio_count: u16,
346393
base: Option<i32>,
347394
parent: &dyn device::RawDevice,
348395
data: T::Data,
349396
parent_irq: u32,
397+
lock_keys: [&'static LockClassKey; 2],
350398
) -> Result {
351399
if self.reg.parent.is_some() {
352400
// Already registered.
@@ -384,7 +432,7 @@ mod irqchip {
384432

385433
// SAFETY: `reg` is pinned when `self` is.
386434
let pinned = unsafe { self.map_unchecked_mut(|r| &mut r.reg) };
387-
pinned.register(gpio_count, base, parent, data)
435+
pinned.register(gpio_count, base, parent, data, lock_keys)
388436
}
389437
}
390438

@@ -475,4 +523,25 @@ mod irqchip {
475523
T::set_wake(data, irq_data, on)
476524
}
477525
}
526+
527+
/// Registers a gpio chip and its irq chip with the rest of the kernel.
528+
///
529+
/// It automatically defines the required lock classes.
530+
#[macro_export]
531+
macro_rules! gpio_irq_chip_register {
532+
($reg:expr, $irqchip:ty, $count:expr, $base:expr, $parent:expr, $data:expr,
533+
$parent_irq:expr $(,)?) => {{
534+
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
535+
static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
536+
$crate::gpio::RegistrationWithIrqChip::register::<$irqchip>(
537+
$reg,
538+
$count,
539+
$base,
540+
$parent,
541+
$data,
542+
$parent_irq,
543+
[&CLASS1, &CLASS2],
544+
)
545+
}};
546+
}
478547
}

rust/kernel/sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl LockClassKey {
6262
Self(UnsafeCell::new(MaybeUninit::uninit()))
6363
}
6464

65-
fn get(&self) -> *mut bindings::lock_class_key {
65+
pub(crate) fn get(&self) -> *mut bindings::lock_class_key {
6666
self.0.get().cast()
6767
}
6868
}

0 commit comments

Comments
 (0)