]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqchip/meson-gpio: Convert meson_gpio_irq_controller::lock to 'raw_spinlock_t'
authorArseniy Krasnov <avkrasnov@salutedevices.com>
Mon, 29 Jul 2024 13:18:50 +0000 (16:18 +0300)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 29 Jul 2024 13:43:50 +0000 (15:43 +0200)
This lock is acquired under irq_desc::lock with interrupts disabled.

When PREEMPT_RT is enabled, 'spinlock_t' becomes preemptible, which results
in invalid lock acquire context;

  [ BUG: Invalid wait context ]
  swapper/0/1 is trying to lock:
  ffff0000008fed30 (&ctl->lock){....}-{3:3}, at: meson_gpio_irq_update_bits0
  other info that might help us debug this:
  context-{5:5}
  3 locks held by swapper/0/1:
   #0: ffff0000003cd0f8 (&dev->mutex){....}-{4:4}, at: __driver_attach+0x90c
   #1: ffff000004714650 (&desc->request_mutex){+.+.}-{4:4}, at: __setup_irq0
   #2: ffff0000047144c8 (&irq_desc_lock_class){-.-.}-{2:2}, at: __setup_irq0
  stack backtrace:
  CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.9.9-sdkernel #1
  Call trace:
   _raw_spin_lock_irqsave+0x60/0x88
   meson_gpio_irq_update_bits+0x34/0x70
   meson8_gpio_irq_set_type+0x78/0xc4
   meson_gpio_irq_set_type+0x30/0x60
   __irq_set_trigger+0x60/0x180
   __setup_irq+0x30c/0x6e0
   request_threaded_irq+0xec/0x1a4

Fixes: 215f4cc0fb20 ("irqchip/meson: Add support for gpio interrupt controller")
Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/20240729131850.3015508-1-avkrasnov@salutedevices.com
drivers/irqchip/irq-meson-gpio.c

index 27e30ce41db3a7d3a1f650cf91076439951b6b41..cd789fa5151909342271f46183aecceb6b007f84 100644 (file)
@@ -178,7 +178,7 @@ struct meson_gpio_irq_controller {
        void __iomem *base;
        u32 channel_irqs[MAX_NUM_CHANNEL];
        DECLARE_BITMAP(channel_map, MAX_NUM_CHANNEL);
-       spinlock_t lock;
+       raw_spinlock_t lock;
 };
 
 static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
@@ -187,14 +187,14 @@ static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
        unsigned long flags;
        u32 tmp;
 
-       spin_lock_irqsave(&ctl->lock, flags);
+       raw_spin_lock_irqsave(&ctl->lock, flags);
 
        tmp = readl_relaxed(ctl->base + reg);
        tmp &= ~mask;
        tmp |= val;
        writel_relaxed(tmp, ctl->base + reg);
 
-       spin_unlock_irqrestore(&ctl->lock, flags);
+       raw_spin_unlock_irqrestore(&ctl->lock, flags);
 }
 
 static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl)
@@ -244,12 +244,12 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
        unsigned long flags;
        unsigned int idx;
 
-       spin_lock_irqsave(&ctl->lock, flags);
+       raw_spin_lock_irqsave(&ctl->lock, flags);
 
        /* Find a free channel */
        idx = find_first_zero_bit(ctl->channel_map, ctl->params->nr_channels);
        if (idx >= ctl->params->nr_channels) {
-               spin_unlock_irqrestore(&ctl->lock, flags);
+               raw_spin_unlock_irqrestore(&ctl->lock, flags);
                pr_err("No channel available\n");
                return -ENOSPC;
        }
@@ -257,7 +257,7 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
        /* Mark the channel as used */
        set_bit(idx, ctl->channel_map);
 
-       spin_unlock_irqrestore(&ctl->lock, flags);
+       raw_spin_unlock_irqrestore(&ctl->lock, flags);
 
        /*
         * Setup the mux of the channel to route the signal of the pad
@@ -567,7 +567,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
        if (!ctl)
                return -ENOMEM;
 
-       spin_lock_init(&ctl->lock);
+       raw_spin_lock_init(&ctl->lock);
 
        ctl->base = of_iomap(node, 0);
        if (!ctl->base) {