The driver may sleep while holding a spinlock. The function call path (from bottom to top) in Linux 4.19 is: drivers/gpio/gpiolib-sysfs.c, 796: mutex_lock in gpiochip_sysfs_unregister drivers/gpio/gpiolib.c, 1455: gpiochip_sysfs_unregister in gpiochip_remove drivers/gpio/gpio-grgpio.c, 460: gpiochip_remove in grgpio_remove drivers/gpio/gpio-grgpio.c, 449: _raw_spin_lock_irqsave in grgpio_remove kernel/irq/irqdomain.c, 243: mutex_lock in irq_domain_remove drivers/gpio/gpio-grgpio.c, 463: irq_domain_remove in grgpio_remove drivers/gpio/gpio-grgpio.c, 449: _raw_spin_lock_irqsave in grgpio_remove mutex_lock() can sleep at runtime. To fix these bugs, gpiochip_remove() and irq_domain_remove() are called without holding the spinlock. These bugs are found by a static analysis tool STCheck written by myself. Signed-off-by: Jia-Ju Bai <baijiaju1990@xxxxxxxxx> --- drivers/gpio/gpio-grgpio.c | 5 ++++- sound/soc/sti/uniperif_player.c | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 08234e64993a..60a2871c5ba7 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -448,13 +448,16 @@ static int grgpio_remove(struct platform_device *ofdev) } } + spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); + gpiochip_remove(&priv->gc); if (priv->domain) irq_domain_remove(priv->domain); out: - spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); + if (ret) + spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags); return ret; } diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 48ea915b24ba..62244e207679 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -601,13 +601,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, mutex_unlock(&player->ctrl_lock); spin_lock_irqsave(&player->irq_lock, flags); + spin_unlock_irqrestore(&player->irq_lock, flags); + if (player->substream && player->substream->runtime) uni_player_set_channel_status(player, player->substream->runtime); else uni_player_set_channel_status(player, NULL); - spin_unlock_irqrestore(&player->irq_lock, flags); return 0; } -- 2.17.1