diff mbox series

[v2,3/5] ASoC: rt5640: Fix sleep in atomic context

Message ID 1688015537-31682-4-git-send-email-spujar@nvidia.com (mailing list archive)
State Accepted
Commit 70a6404ff610aa4889d98977da131c37f9ff9d1f
Headers show
Series Few audio fixes on Tegra platforms | expand

Commit Message

Sameer Pujar June 29, 2023, 5:12 a.m. UTC
Following prints are observed while testing audio on Jetson AGX Orin which
has onboard RT5640 audio codec:

  BUG: sleeping function called from invalid context at kernel/workqueue.c:3027
  in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/0
  preempt_count: 10001, expected: 0
  RCU nest depth: 0, expected: 0
  ------------[ cut here ]------------
  WARNING: CPU: 0 PID: 0 at kernel/irq/handle.c:159 __handle_irq_event_percpu+0x1e0/0x270
  ---[ end trace ad1c64905aac14a6 ]-

The IRQ handler rt5640_irq() runs in interrupt context and can sleep
during cancel_delayed_work_sync().

Fix this by running IRQ handler, rt5640_irq(), in thread context.
Hence replace request_irq() calls with devm_request_threaded_irq().

Fixes: 051dade34695 ("ASoC: rt5640: Fix the wrong state of JD1 and JD2")
Cc: stable@vger.kernel.org
Cc: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/codecs/rt5640.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

Comments

David Laight June 29, 2023, 8:38 a.m. UTC | #1
From: Sameer Pujar
> Sent: 29 June 2023 06:12
> 
> Following prints are observed while testing audio on Jetson AGX Orin which
> has onboard RT5640 audio codec:
> 
>   BUG: sleeping function called from invalid context at kernel/workqueue.c:3027
>   in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/0
>   preempt_count: 10001, expected: 0
>   RCU nest depth: 0, expected: 0
>   ------------[ cut here ]------------
>   WARNING: CPU: 0 PID: 0 at kernel/irq/handle.c:159 __handle_irq_event_percpu+0x1e0/0x270
>   ---[ end trace ad1c64905aac14a6 ]-
> 
> The IRQ handler rt5640_irq() runs in interrupt context and can sleep
> during cancel_delayed_work_sync().
> 
> Fix this by running IRQ handler, rt5640_irq(), in thread context.
> Hence replace request_irq() calls with devm_request_threaded_irq().

My 'gut feel' is that this will just move the problem elsewhere.

If the ISR is responsible for adding audio buffers (etc) then it is
also not unlikely that the scheduling delays in running a threaded ISR
will cause audio glitches if the system is busy.

> 
> Fixes: 051dade34695 ("ASoC: rt5640: Fix the wrong state of JD1 and JD2")
> Cc: stable@vger.kernel.org
> Cc: Oder Chiou <oder_chiou@realtek.com>
> Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> ---
>  sound/soc/codecs/rt5640.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
> index 0ed4fa2..e24ed75 100644
> --- a/sound/soc/codecs/rt5640.c
> +++ b/sound/soc/codecs/rt5640.c
> @@ -2567,9 +2567,10 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
>  	if (jack_data && jack_data->use_platform_clock)
>  		rt5640->use_platform_clock = jack_data->use_platform_clock;
> 
> -	ret = request_irq(rt5640->irq, rt5640_irq,
> -			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> -			  "rt5640", rt5640);
> +	ret = devm_request_threaded_irq(component->dev, rt5640->irq,
> +					NULL, rt5640_irq,
> +					IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> +					"rt5640", rt5640);

You need a comment saying this must be a threaded IRQ because the ISR
calls cancel_delayed_work_sync().

	David

>  	if (ret) {
>  		dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
>  		rt5640_disable_jack_detect(component);
> @@ -2622,8 +2623,9 @@ static void rt5640_enable_hda_jack_detect(
> 
>  	rt5640->jack = jack;
> 
> -	ret = request_irq(rt5640->irq, rt5640_irq,
> -			  IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
> +	ret = devm_request_threaded_irq(component->dev, rt5640->irq,
> +					NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> +					"rt5640", rt5640);
>  	if (ret) {
>  		dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
>  		rt5640->irq = -ENXIO;
> --
> 2.7.4

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Mark Brown June 29, 2023, 10:11 a.m. UTC | #2
On Thu, Jun 29, 2023 at 08:38:09AM +0000, David Laight wrote:
> From: Sameer Pujar

> > Following prints are observed while testing audio on Jetson AGX Orin which
> > has onboard RT5640 audio codec:
> > 
> >   BUG: sleeping function called from invalid context at kernel/workqueue.c:3027
> >   in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/0

> My 'gut feel' is that this will just move the problem elsewhere.

> If the ISR is responsible for adding audio buffers (etc) then it is
> also not unlikely that the scheduling delays in running a threaded ISR
> will cause audio glitches if the system is busy.

What makes you think this is anything to do with audio glitches?  The
bug is literally what is described, it is not valid to sleep in atomic
contexts and if we ever actually try things are likely to go badly.
David Laight June 29, 2023, 10:21 a.m. UTC | #3
From: Mark Brown
> Sent: 29 June 2023 11:11
> 
> On Thu, Jun 29, 2023 at 08:38:09AM +0000, David Laight wrote:
> > From: Sameer Pujar
> 
> > > Following prints are observed while testing audio on Jetson AGX Orin which
> > > has onboard RT5640 audio codec:
> > >
> > >   BUG: sleeping function called from invalid context at kernel/workqueue.c:3027
> > >   in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/0
> 
> > My 'gut feel' is that this will just move the problem elsewhere.
> 
> > If the ISR is responsible for adding audio buffers (etc) then it is
> > also not unlikely that the scheduling delays in running a threaded ISR
> > will cause audio glitches if the system is busy.
> 
> What makes you think this is anything to do with audio glitches?  The
> bug is literally what is described, it is not valid to sleep in atomic
> contexts and if we ever actually try things are likely to go badly.

What I mean is that deferring the ISR to process context
is likely to generate audio glitches on a busy system.

I realise that sleeping in an ISR goes badly wrong.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Mark Brown June 29, 2023, 10:27 a.m. UTC | #4
On Thu, Jun 29, 2023 at 10:21:06AM +0000, David Laight wrote:
> From: Mark Brown

> > What makes you think this is anything to do with audio glitches?  The
> > bug is literally what is described, it is not valid to sleep in atomic
> > contexts and if we ever actually try things are likely to go badly.

> What I mean is that deferring the ISR to process context
> is likely to generate audio glitches on a busy system.

This is an I2C connected CODEC.  We're not doing anything with it in
atomic context, and nothing it does is going to be *that* latency
sensitive.
diff mbox series

Patch

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 0ed4fa2..e24ed75 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2567,9 +2567,10 @@  static void rt5640_enable_jack_detect(struct snd_soc_component *component,
 	if (jack_data && jack_data->use_platform_clock)
 		rt5640->use_platform_clock = jack_data->use_platform_clock;
 
-	ret = request_irq(rt5640->irq, rt5640_irq,
-			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-			  "rt5640", rt5640);
+	ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+					NULL, rt5640_irq,
+					IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					"rt5640", rt5640);
 	if (ret) {
 		dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
 		rt5640_disable_jack_detect(component);
@@ -2622,8 +2623,9 @@  static void rt5640_enable_hda_jack_detect(
 
 	rt5640->jack = jack;
 
-	ret = request_irq(rt5640->irq, rt5640_irq,
-			  IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
+	ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+					NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					"rt5640", rt5640);
 	if (ret) {
 		dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
 		rt5640->irq = -ENXIO;