Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: pl061: make use of raw_spinlock variants

The pl061 gpio driver currently implements an irq_chip for handling
interrupts; due to how irq_chip handling is done, it's necessary for the
irq_chip methods to be invoked from hardirq context, even on a a
real-time kernel. Because the spinlock_t type becomes a "sleeping"
spinlock w/ RT kernels, it is not suitable to be used with irq_chips.

A quick audit of the operations under the lock reveal that they do only
minimal, bounded work, and are therefore safe to do under a raw spinlock.

Signed-off-by: Julia Cartwright <julia@ni.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Julia Cartwright and committed by
Linus Walleij
99b9b45d f9c56536

+14 -14
+14 -14
drivers/gpio/gpio-pl061.c
··· 50 50 #endif 51 51 52 52 struct pl061 { 53 - spinlock_t lock; 53 + raw_spinlock_t lock; 54 54 55 55 void __iomem *base; 56 56 struct gpio_chip gc; ··· 74 74 unsigned long flags; 75 75 unsigned char gpiodir; 76 76 77 - spin_lock_irqsave(&pl061->lock, flags); 77 + raw_spin_lock_irqsave(&pl061->lock, flags); 78 78 gpiodir = readb(pl061->base + GPIODIR); 79 79 gpiodir &= ~(BIT(offset)); 80 80 writeb(gpiodir, pl061->base + GPIODIR); 81 - spin_unlock_irqrestore(&pl061->lock, flags); 81 + raw_spin_unlock_irqrestore(&pl061->lock, flags); 82 82 83 83 return 0; 84 84 } ··· 90 90 unsigned long flags; 91 91 unsigned char gpiodir; 92 92 93 - spin_lock_irqsave(&pl061->lock, flags); 93 + raw_spin_lock_irqsave(&pl061->lock, flags); 94 94 writeb(!!value << offset, pl061->base + (BIT(offset + 2))); 95 95 gpiodir = readb(pl061->base + GPIODIR); 96 96 gpiodir |= BIT(offset); ··· 101 101 * a gpio pin before configuring it in OUT mode. 102 102 */ 103 103 writeb(!!value << offset, pl061->base + (BIT(offset + 2))); 104 - spin_unlock_irqrestore(&pl061->lock, flags); 104 + raw_spin_unlock_irqrestore(&pl061->lock, flags); 105 105 106 106 return 0; 107 107 } ··· 143 143 } 144 144 145 145 146 - spin_lock_irqsave(&pl061->lock, flags); 146 + raw_spin_lock_irqsave(&pl061->lock, flags); 147 147 148 148 gpioiev = readb(pl061->base + GPIOIEV); 149 149 gpiois = readb(pl061->base + GPIOIS); ··· 203 203 writeb(gpioibe, pl061->base + GPIOIBE); 204 204 writeb(gpioiev, pl061->base + GPIOIEV); 205 205 206 - spin_unlock_irqrestore(&pl061->lock, flags); 206 + raw_spin_unlock_irqrestore(&pl061->lock, flags); 207 207 208 208 return 0; 209 209 } ··· 235 235 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); 236 236 u8 gpioie; 237 237 238 - spin_lock(&pl061->lock); 238 + raw_spin_lock(&pl061->lock); 239 239 gpioie = readb(pl061->base + GPIOIE) & ~mask; 240 240 writeb(gpioie, pl061->base + GPIOIE); 241 - spin_unlock(&pl061->lock); 241 + raw_spin_unlock(&pl061->lock); 242 242 } 243 243 244 244 static void pl061_irq_unmask(struct irq_data *d) ··· 248 248 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); 249 249 u8 gpioie; 250 250 251 - spin_lock(&pl061->lock); 251 + raw_spin_lock(&pl061->lock); 252 252 gpioie = readb(pl061->base + GPIOIE) | mask; 253 253 writeb(gpioie, pl061->base + GPIOIE); 254 - spin_unlock(&pl061->lock); 254 + raw_spin_unlock(&pl061->lock); 255 255 } 256 256 257 257 /** ··· 268 268 struct pl061 *pl061 = gpiochip_get_data(gc); 269 269 u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); 270 270 271 - spin_lock(&pl061->lock); 271 + raw_spin_lock(&pl061->lock); 272 272 writeb(mask, pl061->base + GPIOIC); 273 - spin_unlock(&pl061->lock); 273 + raw_spin_unlock(&pl061->lock); 274 274 } 275 275 276 276 static int pl061_irq_set_wake(struct irq_data *d, unsigned int state) ··· 304 304 if (IS_ERR(pl061->base)) 305 305 return PTR_ERR(pl061->base); 306 306 307 - spin_lock_init(&pl061->lock); 307 + raw_spin_lock_init(&pl061->lock); 308 308 if (of_property_read_bool(dev->of_node, "gpio-ranges")) { 309 309 pl061->gc.request = gpiochip_generic_request; 310 310 pl061->gc.free = gpiochip_generic_free;