From: Chengfeng Ye Date: Tue, 26 Sep 2023 10:29:14 +0000 (+0000) Subject: gpio: timberdale: Fix potential deadlock on &tgpio->lock X-Git-Tag: v4.14.328~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=56ff7abffc0a38ead07869a24d6802be25fea53c;p=thirdparty%2Fkernel%2Fstable.git gpio: timberdale: Fix potential deadlock on &tgpio->lock [ Upstream commit 9e8bc2dda5a7a8e2babc9975f4b11c9a6196e490 ] As timbgpio_irq_enable()/timbgpio_irq_disable() callback could be executed under irq context, it could introduce double locks on &tgpio->lock if it preempts other execution units requiring the same locks. timbgpio_gpio_set() --> timbgpio_update_bit() --> spin_lock(&tgpio->lock) --> timbgpio_irq_disable() --> spin_lock_irqsave(&tgpio->lock) This flaw was found by an experimental static analysis tool I am developing for irq-related deadlock. To prevent the potential deadlock, the patch uses spin_lock_irqsave() on &tgpio->lock inside timbgpio_gpio_set() to prevent the possible deadlock scenario. Signed-off-by: Chengfeng Ye Reviewed-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski Signed-off-by: Sasha Levin --- diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 181f86ce00cd4..639c8daaeb310 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -55,9 +55,10 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, unsigned offset, bool enabled) { struct timbgpio *tgpio = gpiochip_get_data(gpio); + unsigned long flags; u32 reg; - spin_lock(&tgpio->lock); + spin_lock_irqsave(&tgpio->lock, flags); reg = ioread32(tgpio->membase + offset); if (enabled) @@ -66,7 +67,7 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, reg &= ~(1 << index); iowrite32(reg, tgpio->membase + offset); - spin_unlock(&tgpio->lock); + spin_unlock_irqrestore(&tgpio->lock, flags); return 0; }