]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gpio: ath79: use the generic GPIO chip lock for IRQ handling
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Wed, 10 Sep 2025 07:12:41 +0000 (09:12 +0200)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 12 Sep 2025 07:22:44 +0000 (09:22 +0200)
This driver uses its own raw spinlock in interrupt routines while the
generic GPIO chip callbacks use a separate one. This is, of course, racy
so use the fact that the lock in generic GPIO chip is also a raw
spinlock and convert the interrupt handling functions in this module to
using the provided generic GPIO chip locking API.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250910-gpio-mmio-gpio-conv-part4-v2-5-f3d1a4c57124@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpio-ath79.c

index 8879f23f1871ed323513082f4d2ebb2c40544cde..2ad9f6ac66362fba8cdab152a2b2c782dddf427c 100644 (file)
@@ -31,7 +31,6 @@
 struct ath79_gpio_ctrl {
        struct gpio_generic_chip chip;
        void __iomem *base;
-       raw_spinlock_t lock;
        unsigned long both_edges;
 };
 
@@ -72,23 +71,22 @@ static void ath79_gpio_irq_unmask(struct irq_data *data)
 {
        struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
        u32 mask = BIT(irqd_to_hwirq(data));
-       unsigned long flags;
 
        gpiochip_enable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
+
+       guard(gpio_generic_lock_irqsave)(&ctrl->chip);
+
        ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static void ath79_gpio_irq_mask(struct irq_data *data)
 {
        struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
        u32 mask = BIT(irqd_to_hwirq(data));
-       unsigned long flags;
 
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
-       ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
+       scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip)
+               ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
+
        gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
 }
 
@@ -96,24 +94,20 @@ static void ath79_gpio_irq_enable(struct irq_data *data)
 {
        struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
        u32 mask = BIT(irqd_to_hwirq(data));
-       unsigned long flags;
 
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
+       guard(gpio_generic_lock_irqsave)(&ctrl->chip);
        ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
        ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static void ath79_gpio_irq_disable(struct irq_data *data)
 {
        struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
        u32 mask = BIT(irqd_to_hwirq(data));
-       unsigned long flags;
 
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
+       guard(gpio_generic_lock_irqsave)(&ctrl->chip);
        ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
        ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static int ath79_gpio_irq_set_type(struct irq_data *data,
@@ -122,7 +116,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
        struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
        u32 mask = BIT(irqd_to_hwirq(data));
        u32 type = 0, polarity = 0;
-       unsigned long flags;
        bool disabled;
 
        switch (flow_type) {
@@ -144,7 +137,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
                return -EINVAL;
        }
 
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
+       guard(gpio_generic_lock_irqsave)(&ctrl->chip);
 
        if (flow_type == IRQ_TYPE_EDGE_BOTH) {
                ctrl->both_edges |= mask;
@@ -169,8 +162,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
                ath79_gpio_update_bits(
                        ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
 
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-
        return 0;
 }
 
@@ -192,26 +183,24 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
        struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
        struct ath79_gpio_ctrl *ctrl =
                container_of(gen_gc, struct ath79_gpio_ctrl, chip);
-       unsigned long flags, pending;
+       unsigned long pending;
        u32 both_edges, state;
        int irq;
 
        chained_irq_enter(irqchip, desc);
 
-       raw_spin_lock_irqsave(&ctrl->lock, flags);
-
-       pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
+       scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip) {
+               pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
 
-       /* Update the polarity of the both edges irqs */
-       both_edges = ctrl->both_edges & pending;
-       if (both_edges) {
-               state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN);
-               ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
-                               both_edges, ~state);
+               /* Update the polarity of the both edges irqs */
+               both_edges = ctrl->both_edges & pending;
+               if (both_edges) {
+                       state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN);
+                       ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
+                                              both_edges, ~state);
+               }
        }
 
-       raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-
        for_each_set_bit(irq, &pending, gc->ngpio)
                generic_handle_domain_irq(gc->irq.domain, irq);
 
@@ -256,8 +245,6 @@ static int ath79_gpio_probe(struct platform_device *pdev)
        if (IS_ERR(ctrl->base))
                return PTR_ERR(ctrl->base);
 
-       raw_spin_lock_init(&ctrl->lock);
-
        config = (struct gpio_generic_chip_config) {
                .dev = dev,
                .sz = 4,