Skip to content

Commit 984245b

Browse files
vladimirolteanlinusw
authored andcommitted
pinctrl: armada-37xx: make irq_lock a raw spinlock to avoid invalid wait context
The irqchip->irq_set_type method is called by __irq_set_trigger() under the desc->lock raw spinlock. The armada-37xx implementation, armada_37xx_irq_set_type(), takes a plain spinlock, the kind that becomes sleepable on RT. Therefore, this is an invalid locking scheme for which we get a kernel splat stating just that ("[ BUG: Invalid wait context ]"), because the context in which the plain spinlock may sleep is atomic due to the raw spinlock. We need to go raw spinlocks all the way. Replace the driver's irq_lock with a raw spinlock, to disable preemption even on RT. Cc: <stable@vger.kernel.org> # 5.15+ Fixes: 2f22760 ("pinctrl: armada-37xx: Add irqchip support") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20220716233745.1704677-2-vladimir.oltean@nxp.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 41ef3c1 commit 984245b

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

drivers/pinctrl/mvebu/pinctrl-armada-37xx.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ struct armada_37xx_pinctrl {
102102
struct device *dev;
103103
struct gpio_chip gpio_chip;
104104
struct irq_chip irq_chip;
105-
spinlock_t irq_lock;
105+
raw_spinlock_t irq_lock;
106106
struct pinctrl_desc pctl;
107107
struct pinctrl_dev *pctl_dev;
108108
struct armada_37xx_pin_group *groups;
@@ -523,9 +523,9 @@ static void armada_37xx_irq_ack(struct irq_data *d)
523523
unsigned long flags;
524524

525525
armada_37xx_irq_update_reg(&reg, d);
526-
spin_lock_irqsave(&info->irq_lock, flags);
526+
raw_spin_lock_irqsave(&info->irq_lock, flags);
527527
writel(d->mask, info->base + reg);
528-
spin_unlock_irqrestore(&info->irq_lock, flags);
528+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
529529
}
530530

531531
static void armada_37xx_irq_mask(struct irq_data *d)
@@ -536,10 +536,10 @@ static void armada_37xx_irq_mask(struct irq_data *d)
536536
unsigned long flags;
537537

538538
armada_37xx_irq_update_reg(&reg, d);
539-
spin_lock_irqsave(&info->irq_lock, flags);
539+
raw_spin_lock_irqsave(&info->irq_lock, flags);
540540
val = readl(info->base + reg);
541541
writel(val & ~d->mask, info->base + reg);
542-
spin_unlock_irqrestore(&info->irq_lock, flags);
542+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
543543
}
544544

545545
static void armada_37xx_irq_unmask(struct irq_data *d)
@@ -550,10 +550,10 @@ static void armada_37xx_irq_unmask(struct irq_data *d)
550550
unsigned long flags;
551551

552552
armada_37xx_irq_update_reg(&reg, d);
553-
spin_lock_irqsave(&info->irq_lock, flags);
553+
raw_spin_lock_irqsave(&info->irq_lock, flags);
554554
val = readl(info->base + reg);
555555
writel(val | d->mask, info->base + reg);
556-
spin_unlock_irqrestore(&info->irq_lock, flags);
556+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
557557
}
558558

559559
static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -564,14 +564,14 @@ static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on)
564564
unsigned long flags;
565565

566566
armada_37xx_irq_update_reg(&reg, d);
567-
spin_lock_irqsave(&info->irq_lock, flags);
567+
raw_spin_lock_irqsave(&info->irq_lock, flags);
568568
val = readl(info->base + reg);
569569
if (on)
570570
val |= (BIT(d->hwirq % GPIO_PER_REG));
571571
else
572572
val &= ~(BIT(d->hwirq % GPIO_PER_REG));
573573
writel(val, info->base + reg);
574-
spin_unlock_irqrestore(&info->irq_lock, flags);
574+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
575575

576576
return 0;
577577
}
@@ -583,7 +583,7 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
583583
u32 val, reg = IRQ_POL;
584584
unsigned long flags;
585585

586-
spin_lock_irqsave(&info->irq_lock, flags);
586+
raw_spin_lock_irqsave(&info->irq_lock, flags);
587587
armada_37xx_irq_update_reg(&reg, d);
588588
val = readl(info->base + reg);
589589
switch (type) {
@@ -607,11 +607,11 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
607607
break;
608608
}
609609
default:
610-
spin_unlock_irqrestore(&info->irq_lock, flags);
610+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
611611
return -EINVAL;
612612
}
613613
writel(val, info->base + reg);
614-
spin_unlock_irqrestore(&info->irq_lock, flags);
614+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
615615

616616
return 0;
617617
}
@@ -626,7 +626,7 @@ static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,
626626

627627
regmap_read(info->regmap, INPUT_VAL + 4*reg_idx, &l);
628628

629-
spin_lock_irqsave(&info->irq_lock, flags);
629+
raw_spin_lock_irqsave(&info->irq_lock, flags);
630630
p = readl(info->base + IRQ_POL + 4 * reg_idx);
631631
if ((p ^ l) & (1 << bit_num)) {
632632
/*
@@ -647,7 +647,7 @@ static int armada_37xx_edge_both_irq_swap_pol(struct armada_37xx_pinctrl *info,
647647
ret = -1;
648648
}
649649

650-
spin_unlock_irqrestore(&info->irq_lock, flags);
650+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
651651
return ret;
652652
}
653653

@@ -664,11 +664,11 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
664664
u32 status;
665665
unsigned long flags;
666666

667-
spin_lock_irqsave(&info->irq_lock, flags);
667+
raw_spin_lock_irqsave(&info->irq_lock, flags);
668668
status = readl_relaxed(info->base + IRQ_STATUS + 4 * i);
669669
/* Manage only the interrupt that was enabled */
670670
status &= readl_relaxed(info->base + IRQ_EN + 4 * i);
671-
spin_unlock_irqrestore(&info->irq_lock, flags);
671+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
672672
while (status) {
673673
u32 hwirq = ffs(status) - 1;
674674
u32 virq = irq_find_mapping(d, hwirq +
@@ -695,12 +695,12 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
695695

696696
update_status:
697697
/* Update status in case a new IRQ appears */
698-
spin_lock_irqsave(&info->irq_lock, flags);
698+
raw_spin_lock_irqsave(&info->irq_lock, flags);
699699
status = readl_relaxed(info->base +
700700
IRQ_STATUS + 4 * i);
701701
/* Manage only the interrupt that was enabled */
702702
status &= readl_relaxed(info->base + IRQ_EN + 4 * i);
703-
spin_unlock_irqrestore(&info->irq_lock, flags);
703+
raw_spin_unlock_irqrestore(&info->irq_lock, flags);
704704
}
705705
}
706706
chained_irq_exit(chip, desc);
@@ -731,7 +731,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
731731
struct device *dev = &pdev->dev;
732732
unsigned int i, nr_irq_parent;
733733

734-
spin_lock_init(&info->irq_lock);
734+
raw_spin_lock_init(&info->irq_lock);
735735

736736
nr_irq_parent = of_irq_count(np);
737737
if (!nr_irq_parent) {

0 commit comments

Comments
 (0)