* [PATCH v2 1/2] gpio: tegra: Add lockdep class @ 2020-11-04 17:04 Dmitry Osipenko 2020-11-04 17:04 ` [PATCH v2 2/2] gpio: tegra: Use raw_spinlock Dmitry Osipenko 0 siblings, 1 reply; 3+ messages in thread From: Dmitry Osipenko @ 2020-11-04 17:04 UTC (permalink / raw) To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Bartosz Golaszewski, Linus Walleij, Andy Shevchenko, Peter Geis Cc: linux-tegra, linux-gpio, linux-kernel Add lockdep class in order to fix debug warnings that are coming from a legit nested use of irq_set_irq_wake() by the Tegra GPIO driver. WARNING: possible recursive locking detected ... (irq_set_irq_wake) from (tegra_gpio_irq_set_wake) (tegra_gpio_irq_set_wake) from (irq_set_irq_wake) (irq_set_irq_wake) from (brcmf_sdiod_intr_register [brcmfmac]) ... Tested-by: Peter Geis <pgwipeout@gmail.com> Reported-by: Peter Geis <pgwipeout@gmail.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- Changelog: v2: - No changes. drivers/gpio/gpio-tegra.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 86568154cdb3..98fc78739ebf 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -560,6 +560,9 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) }; +static struct lock_class_key gpio_lock_class; +static struct lock_class_key gpio_request_class; + static int tegra_gpio_probe(struct platform_device *pdev) { struct tegra_gpio_info *tgi; @@ -661,6 +664,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) bank = &tgi->bank_info[GPIO_BANK(gpio)]; irq_set_chip_data(irq, bank); + irq_set_lockdep_class(irq, &gpio_lock_class, &gpio_request_class); irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq); } -- 2.27.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] gpio: tegra: Use raw_spinlock 2020-11-04 17:04 [PATCH v2 1/2] gpio: tegra: Add lockdep class Dmitry Osipenko @ 2020-11-04 17:04 ` Dmitry Osipenko 2020-11-06 14:31 ` Bartosz Golaszewski 0 siblings, 1 reply; 3+ messages in thread From: Dmitry Osipenko @ 2020-11-04 17:04 UTC (permalink / raw) To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Bartosz Golaszewski, Linus Walleij, Andy Shevchenko, Peter Geis Cc: linux-tegra, linux-gpio, linux-kernel Use raw_spinlock in order to fix spurious messages about invalid context when spinlock debugging is enabled. This happens because there is a legit nested raw_spinlock->spinlock locking usage within IRQ-related code. IRQ core uses raw spinlock and then Tegra GPIO driver uses a nested spinlock. The debug code can't recognize and handle this case, hence we need to use raw spinlock in the GPIO driver. [ BUG: Invalid wait context ] ... (dump_stack) from (__lock_acquire) (__lock_acquire) from (lock_acquire) (lock_acquire) from (_raw_spin_lock_irqsave) (_raw_spin_lock_irqsave) from (tegra_gpio_irq_set_type) (tegra_gpio_irq_set_type) from (__irq_set_trigger) (__irq_set_trigger) from (__setup_irq) (__setup_irq) from (request_threaded_irq) (request_threaded_irq) from (devm_request_threaded_irq) (devm_request_threaded_irq) from (elants_i2c_probe) (elants_i2c_probe) from (i2c_device_probe) ... Tested-by: Peter Geis <pgwipeout@gmail.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- Changelog: v2: - Only lvl_lock is converted to raw_spinlock. The dbc_lock doesn't relate to IRQ and doesn't need the conversion. - Improved commit message by clarifying that IRQ core uses raw spinlock. - Added clarifying comment to the code for the lvl_lock. drivers/gpio/gpio-tegra.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 98fc78739ebf..e19ebff6018c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -61,8 +61,16 @@ struct tegra_gpio_info; struct tegra_gpio_bank { unsigned int bank; unsigned int irq; - spinlock_t lvl_lock[4]; - spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */ + + /* + * IRQ-core code uses raw locking, and thus, nested locking also + * should be raw in order not to trip spinlock debug warnings. + */ + raw_spinlock_t lvl_lock[4]; + + /* Lock for updating debounce count register */ + spinlock_t dbc_lock[4]; + #ifdef CONFIG_PM_SLEEP u32 cnf[4]; u32 out[4]; @@ -334,14 +342,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - spin_lock_irqsave(&bank->lvl_lock[port], flags); + raw_spin_lock_irqsave(&bank->lvl_lock[port], flags); val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); val |= lvl_type << GPIO_BIT(gpio); tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio)); - spin_unlock_irqrestore(&bank->lvl_lock[port], flags); + raw_spin_unlock_irqrestore(&bank->lvl_lock[port], flags); tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0); tegra_gpio_enable(tgi, gpio); @@ -675,7 +683,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) tegra_gpio_irq_handler, bank); for (j = 0; j < 4; j++) { - spin_lock_init(&bank->lvl_lock[j]); + raw_spin_lock_init(&bank->lvl_lock[j]); spin_lock_init(&bank->dbc_lock[j]); } } -- 2.27.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 2/2] gpio: tegra: Use raw_spinlock 2020-11-04 17:04 ` [PATCH v2 2/2] gpio: tegra: Use raw_spinlock Dmitry Osipenko @ 2020-11-06 14:31 ` Bartosz Golaszewski 0 siblings, 0 replies; 3+ messages in thread From: Bartosz Golaszewski @ 2020-11-06 14:31 UTC (permalink / raw) To: Dmitry Osipenko Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Linus Walleij, Andy Shevchenko, Peter Geis, linux-tegra, linux-gpio, LKML On Wed, Nov 4, 2020 at 6:04 PM Dmitry Osipenko <digetx@gmail.com> wrote: > > Use raw_spinlock in order to fix spurious messages about invalid context > when spinlock debugging is enabled. This happens because there is a legit > nested raw_spinlock->spinlock locking usage within IRQ-related code. IRQ > core uses raw spinlock and then Tegra GPIO driver uses a nested spinlock. > The debug code can't recognize and handle this case, hence we need to use > raw spinlock in the GPIO driver. > > [ BUG: Invalid wait context ] > ... > (dump_stack) from (__lock_acquire) > (__lock_acquire) from (lock_acquire) > (lock_acquire) from (_raw_spin_lock_irqsave) > (_raw_spin_lock_irqsave) from (tegra_gpio_irq_set_type) > (tegra_gpio_irq_set_type) from (__irq_set_trigger) > (__irq_set_trigger) from (__setup_irq) > (__setup_irq) from (request_threaded_irq) > (request_threaded_irq) from (devm_request_threaded_irq) > (devm_request_threaded_irq) from (elants_i2c_probe) > (elants_i2c_probe) from (i2c_device_probe) > ... > > Tested-by: Peter Geis <pgwipeout@gmail.com> > Signed-off-by: Dmitry Osipenko <digetx@gmail.com> > --- > > Changelog: > > v2: - Only lvl_lock is converted to raw_spinlock. The dbc_lock doesn't > relate to IRQ and doesn't need the conversion. > > - Improved commit message by clarifying that IRQ core uses raw > spinlock. > > - Added clarifying comment to the code for the lvl_lock. > > drivers/gpio/gpio-tegra.c | 18 +++++++++++++----- > 1 file changed, 13 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c > index 98fc78739ebf..e19ebff6018c 100644 > --- a/drivers/gpio/gpio-tegra.c > +++ b/drivers/gpio/gpio-tegra.c > @@ -61,8 +61,16 @@ struct tegra_gpio_info; > struct tegra_gpio_bank { > unsigned int bank; > unsigned int irq; > - spinlock_t lvl_lock[4]; > - spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */ > + > + /* > + * IRQ-core code uses raw locking, and thus, nested locking also > + * should be raw in order not to trip spinlock debug warnings. > + */ > + raw_spinlock_t lvl_lock[4]; > + > + /* Lock for updating debounce count register */ > + spinlock_t dbc_lock[4]; > + > #ifdef CONFIG_PM_SLEEP > u32 cnf[4]; > u32 out[4]; > @@ -334,14 +342,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) > return -EINVAL; > } > > - spin_lock_irqsave(&bank->lvl_lock[port], flags); > + raw_spin_lock_irqsave(&bank->lvl_lock[port], flags); > > val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); > val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); > val |= lvl_type << GPIO_BIT(gpio); > tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio)); > > - spin_unlock_irqrestore(&bank->lvl_lock[port], flags); > + raw_spin_unlock_irqrestore(&bank->lvl_lock[port], flags); > > tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0); > tegra_gpio_enable(tgi, gpio); > @@ -675,7 +683,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) > tegra_gpio_irq_handler, bank); > > for (j = 0; j < 4; j++) { > - spin_lock_init(&bank->lvl_lock[j]); > + raw_spin_lock_init(&bank->lvl_lock[j]); > spin_lock_init(&bank->dbc_lock[j]); > } > } > -- > 2.27.0 > Patch applied, thanks! Bartosz ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-11-06 14:32 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-11-04 17:04 [PATCH v2 1/2] gpio: tegra: Add lockdep class Dmitry Osipenko 2020-11-04 17:04 ` [PATCH v2 2/2] gpio: tegra: Use raw_spinlock Dmitry Osipenko 2020-11-06 14:31 ` Bartosz Golaszewski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).