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

pinctrl: mediatek: use spin lock in mtk_rmw

Commit 42a46434e9b1 ("pinctrl: add lock in mtk_rmw function.") uses
mutex lock in mtk_rmw. However the function is possible called from
atomic context.

For example call trace:
mutex_lock+0x28/0x64
mtk_rmw+0x38/0x80
[snip]
max98357a_daiops_trigger+0x8c/0x9c
soc_pcm_trigger+0x5c/0x10c

The max98357a_daiops_trigger() could run in either atomic or non-atomic
context. As a result, dmesg shows some similar messages: "BUG: sleeping
function called from invalid context at kernel/locking/mutex.c:254".

Uses spin lock in mtk_rmw instead.

Fixes: 42a46434e9b1 ("pinctrl: add lock in mtk_rmw function.")
Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
Link: https://lore.kernel.org/r/20210419093449.3125704-1-tzungbi@google.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Tzung-Bi Shih and committed by
Linus Walleij
56ab29ec ea9d2ed4

+6 -5
+1 -1
drivers/pinctrl/mediatek/pinctrl-moore.c
··· 619 619 620 620 hw->nbase = hw->soc->nbase_names; 621 621 622 - mutex_init(&hw->lock); 622 + spin_lock_init(&hw->lock); 623 623 624 624 /* Copy from internal struct mtk_pin_desc to register to the core */ 625 625 pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
+3 -2
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
··· 57 57 void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set) 58 58 { 59 59 u32 val; 60 + unsigned long flags; 60 61 61 - mutex_lock(&pctl->lock); 62 + spin_lock_irqsave(&pctl->lock, flags); 62 63 63 64 val = mtk_r32(pctl, i, reg); 64 65 val &= ~mask; 65 66 val |= set; 66 67 mtk_w32(pctl, i, reg, val); 67 68 68 - mutex_unlock(&pctl->lock); 69 + spin_unlock_irqrestore(&pctl->lock, flags); 69 70 } 70 71 71 72 static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
+1 -1
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
··· 253 253 struct mtk_pinctrl_group *groups; 254 254 const char **grp_names; 255 255 /* lock pin's register resource to avoid multiple threads issue*/ 256 - struct mutex lock; 256 + spinlock_t lock; 257 257 }; 258 258 259 259 void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set);
+1 -1
drivers/pinctrl/mediatek/pinctrl-paris.c
··· 970 970 971 971 hw->nbase = hw->soc->nbase_names; 972 972 973 - mutex_init(&hw->lock); 973 + spin_lock_init(&hw->lock); 974 974 975 975 err = mtk_pctrl_build_state(pdev); 976 976 if (err) {