Skip to content

Commit

Permalink
gpio: pl061: use raw spinlock
Browse files Browse the repository at this point in the history
Lockdep finds the issue below when we use a regular spinlock. The issue
is that the ack callback is called with a raw spinlock held, so we
cannot try to acquire a regular one.

[    6.209959] =============================
[    6.210193] [ BUG: Invalid wait context ]
[    6.210490] 5.17.0-rc8-126314-g126438203c44-dirty torvalds#482 Not tainted
[    6.210968] -----------------------------
[    6.211200] swapper/0/1 is trying to lock:
[    6.211457] ffff0000039e4c88 (PL061Data::inner){....}-{3:3}, at: rust_helper_spin_lock+0x10/0x1c
[    6.212324] other info that might help us debug this:
[    6.212714] context-{5:5}
[    6.213157] 3 locks held by swapper/0/1:
[    6.213559]  #0: ffff000003353188 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xe0/0x190
[    6.214080]  #1: ffff800009ed6bf0 (irq_domain_mutex){+.+.}-{4:4}, at: irq_domain_associate+0x58/0x1bc
[    6.214598]  #2: ffff0000050c04f8 (lock_class){....}-{2:2}, at: __irq_get_desc_lock+0x6c/0x94
[    6.215105] stack backtrace:
[    6.215507] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.17.0-rc8-126314-g126438203c44-dirty torvalds#482
[    6.216109] Hardware name: linux,dummy-virt (DT)
[    6.216688] Call trace:
[    6.217075]  dump_backtrace+0xec/0x10c
[    6.217370]  show_stack+0x18/0x24
[    6.217560]  dump_stack_lvl+0x7c/0xa0
[    6.217772]  dump_stack+0x18/0x44
[    6.217962]  __lock_acquire+0x9e0/0xbf8
[    6.218176]  lock_acquire+0xf4/0x1c0
[    6.218386]  _raw_spin_lock+0x6c/0x84
[    6.218577]  rust_helper_spin_lock+0x10/0x1c
[    6.218810]  _RINvNtCsbgmUaSdIQ4l_6kernel3irq16irq_ack_callbackINtNtNtB4_4gpio7irqchip14IrqChipAdapterNtCs7lwOkdKm4ly_15gpio_pl061_rust11PL061DeviceEEB1q_+0x50/0xac
[    6.219566]  irq_set_chip_and_handler_name+0x138/0x1a4
[    6.219848]  gpiochip_irq_map+0x5c/0x108
[    6.220083]  irq_domain_associate+0x7c/0x1bc
[    6.220343]  irq_create_mapping_affinity+0x120/0x190
[    6.220754]  gpiochip_to_irq+0x48/0xd4
[    6.221147]  gpiod_to_irq+0x54/0x8c
[    6.221469]  gpio_keys_probe+0x2ec/0x8b8
[    6.221703]  platform_probe+0xa8/0xd0
[    6.221917]  really_probe+0x12c/0x2f8
[    6.222107]  __driver_probe_device+0xb4/0xe0
[    6.222352]  driver_probe_device+0x40/0x134
[    6.222602]  __driver_attach+0xec/0x190
[    6.222810]  bus_for_each_dev+0x80/0xcc
[    6.223033]  driver_attach+0x24/0x30
[    6.223243]  bus_add_driver+0x100/0x1e0
[    6.223439]  driver_register+0x78/0x110
[    6.223619]  __platform_driver_register+0x24/0x30
[    6.223855]  gpio_keys_init+0x1c/0x28
[    6.224051]  do_one_initcall+0xb8/0x19c
[    6.224255]  do_initcall_level+0xa0/0xc0
[    6.224461]  do_initcalls+0x54/0x94
[    6.224927]  do_basic_setup+0x50/0x60
[    6.225145]  kernel_init_freeable+0x88/0xe0
[    6.225422]  kernel_init+0x20/0x1a0
[    6.225628]  ret_from_fork+0x10/0x20

Signed-off-by: Wedson Almeida Filho <[email protected]>
  • Loading branch information
wedsonaf committed Apr 8, 2022
1 parent 13bb4c8 commit cb54d39
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions drivers/gpio/gpio_pl061_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use kernel::{
irq::{self, ExtraResult, IrqData, LockedIrqData},
power,
prelude::*,
sync::{Ref, RefBorrow, SpinLock},
sync::{RawSpinLock, Ref, RefBorrow},
};

const GPIODIR: usize = 0x400;
Expand Down Expand Up @@ -41,7 +41,7 @@ struct PL061DataInner {

struct PL061Data {
dev: device::Device,
inner: SpinLock<PL061DataInner>,
inner: RawSpinLock<PL061DataInner>,
}

struct PL061Resources {
Expand Down Expand Up @@ -283,15 +283,15 @@ impl amba::Driver for PL061Device {
},
PL061Data {
dev: device::Device::from_dev(dev),
// SAFETY: We call `spinlock_init` below.
inner: unsafe { SpinLock::new(PL061DataInner::default()) },
// SAFETY: We call `rawspinlock_init` below.
inner: unsafe { RawSpinLock::new(PL061DataInner::default()) },
},
"PL061::Registrations"
)?;

// SAFETY: General part of the data is pinned when `data` is.
let gen_inner = unsafe { data.as_mut().map_unchecked_mut(|d| &mut (**d).inner) };
kernel::spinlock_init!(gen_inner, "PL061Data::inner");
kernel::rawspinlock_init!(gen_inner, "PL061Data::inner");

let data = Ref::<DeviceData>::from(data);

Expand Down

0 comments on commit cb54d39

Please sign in to comment.