diff mbox series

[v2,2/4] ALSA: hda: Rework snd_hdac_stream_reset() to use macros

Message ID 20220818141517.109280-3-amadeuszx.slawinski@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series hda: Minor cleanups | expand

Commit Message

Amadeusz Sławiński Aug. 18, 2022, 2:15 p.m. UTC
We can use existing macros to poll and update register values instead of
open coding the functionality.

Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
---
 sound/hda/hdac_stream.c | 26 ++++++--------------------
 1 file changed, 6 insertions(+), 20 deletions(-)

Comments

Jon Hunter Oct. 5, 2022, 12:10 p.m. UTC | #1
On 18/08/2022 15:15, Amadeusz Sławiński wrote:
> We can use existing macros to poll and update register values instead of
> open coding the functionality.
> 
> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
> Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
> ---
>   sound/hda/hdac_stream.c | 26 ++++++--------------------
>   1 file changed, 6 insertions(+), 20 deletions(-)
> 
> diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
> index f3582012d22f..bdf6d4db6769 100644
> --- a/sound/hda/hdac_stream.c
> +++ b/sound/hda/hdac_stream.c
> @@ -165,7 +165,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
>   void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
>   {
>   	unsigned char val;
> -	int timeout;
>   	int dma_run_state;
>   
>   	snd_hdac_stream_clear(azx_dev);
> @@ -173,30 +172,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
>   	dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
>   
>   	snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
> -	udelay(3);
> -	timeout = 300;
> -	do {
> -		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
> -			SD_CTL_STREAM_RESET;
> -		if (val)
> -			break;
> -	} while (--timeout);
> +
> +	/* wait for hardware to report that the stream entered reset */
> +	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
>   
>   	if (azx_dev->bus->dma_stop_delay && dma_run_state)
>   		udelay(azx_dev->bus->dma_stop_delay);
>   
> -	val &= ~SD_CTL_STREAM_RESET;
> -	snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
> -	udelay(3);
> +	snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
>   
> -	timeout = 300;
> -	/* waiting for hardware to report that the stream is out of reset */
> -	do {
> -		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
> -			SD_CTL_STREAM_RESET;
> -		if (!val)
> -			break;
> -	} while (--timeout);
> +	/* wait for hardware to report that the stream is out of reset */
> +	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
>   
>   	/* reset first position - may not be synced with hw at this time */
>   	if (azx_dev->posbuf)


HDA playback is failing on -next for various Tegra boards. Bisect is 
point to this commit and reverting it fixes the problem. I was a bit 
puzzled why this change is causing a problem, but looking closer there 
is a difference between the previous code that was calling 
snd_hdac_stream_readb() and the new code that is calling 
snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb() calls 
snd_hdac_aligned_mmio() is see if the device has an aligned MMIO which 
Tegra does and then would call snd_hdac_aligned_read(). However, now the 
code always call readb() and this is breaking Tegra.

So it is either necessary to update snd_hdac_stream_readb_poll() to 
handle this or revert this change.

Cheers
Jon
Takashi Iwai Oct. 5, 2022, 12:29 p.m. UTC | #2
On Wed, 05 Oct 2022 14:10:04 +0200,
Jon Hunter wrote:
> 
> 
> On 18/08/2022 15:15, Amadeusz Sławiński wrote:
> > We can use existing macros to poll and update register values instead of
> > open coding the functionality.
> > 
> > Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
> > Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
> > ---
> >   sound/hda/hdac_stream.c | 26 ++++++--------------------
> >   1 file changed, 6 insertions(+), 20 deletions(-)
> > 
> > diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
> > index f3582012d22f..bdf6d4db6769 100644
> > --- a/sound/hda/hdac_stream.c
> > +++ b/sound/hda/hdac_stream.c
> > @@ -165,7 +165,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
> >   void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
> >   {
> >   	unsigned char val;
> > -	int timeout;
> >   	int dma_run_state;
> >     	snd_hdac_stream_clear(azx_dev);
> > @@ -173,30 +172,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
> >   	dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
> >     	snd_hdac_stream_updateb(azx_dev, SD_CTL, 0,
> > SD_CTL_STREAM_RESET);
> > -	udelay(3);
> > -	timeout = 300;
> > -	do {
> > -		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
> > -			SD_CTL_STREAM_RESET;
> > -		if (val)
> > -			break;
> > -	} while (--timeout);
> > +
> > +	/* wait for hardware to report that the stream entered reset */
> > +	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
> >     	if (azx_dev->bus->dma_stop_delay && dma_run_state)
> >   		udelay(azx_dev->bus->dma_stop_delay);
> >   -	val &= ~SD_CTL_STREAM_RESET;
> > -	snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
> > -	udelay(3);
> > +	snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
> >   -	timeout = 300;
> > -	/* waiting for hardware to report that the stream is out of reset */
> > -	do {
> > -		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
> > -			SD_CTL_STREAM_RESET;
> > -		if (!val)
> > -			break;
> > -	} while (--timeout);
> > +	/* wait for hardware to report that the stream is out of reset */
> > +	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
> >     	/* reset first position - may not be synced with hw at this
> > time */
> >   	if (azx_dev->posbuf)
> 
> 
> HDA playback is failing on -next for various Tegra boards. Bisect is
> point to this commit and reverting it fixes the problem. I was a bit
> puzzled why this change is causing a problem, but looking closer there
> is a difference between the previous code that was calling
> snd_hdac_stream_readb() and the new code that is calling
> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
> which Tegra does and then would call snd_hdac_aligned_read(). However,
> now the code always call readb() and this is breaking Tegra.
> 
> So it is either necessary to update snd_hdac_stream_readb_poll() to
> handle this or revert this change.

Does the patch below work?


thanks,

Takashi

-- 8< --
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
 #define snd_hdac_stream_readb(dev, reg) \
 	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
-	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
-			   delay_us, timeout_us)
+	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
+			  false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
 	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
 			   delay_us, timeout_us)
Jon Hunter Oct. 5, 2022, 1:52 p.m. UTC | #3
On 05/10/2022 13:29, Takashi Iwai wrote:

...

>> HDA playback is failing on -next for various Tegra boards. Bisect is
>> point to this commit and reverting it fixes the problem. I was a bit
>> puzzled why this change is causing a problem, but looking closer there
>> is a difference between the previous code that was calling
>> snd_hdac_stream_readb() and the new code that is calling
>> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
>> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
>> which Tegra does and then would call snd_hdac_aligned_read(). However,
>> now the code always call readb() and this is breaking Tegra.
>>
>> So it is either necessary to update snd_hdac_stream_readb_poll() to
>> handle this or revert this change.
> 
> Does the patch below work?
> 
> 
> thanks,
> 
> Takashi
> 
> -- 8< --
> --- a/include/sound/hdaudio.h
> +++ b/include/sound/hdaudio.h
> @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
>   #define snd_hdac_stream_readb(dev, reg) \
>   	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>   #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
> -	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
> -			   delay_us, timeout_us)
> +	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
> +			  false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>   #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
>   	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>   			   delay_us, timeout_us)


Amazingly it does not work. I would have thought that would, but it does 
not. I am a bit puzzled by that?

Jon
Takashi Iwai Oct. 5, 2022, 2:07 p.m. UTC | #4
On Wed, 05 Oct 2022 15:52:01 +0200,
Jon Hunter wrote:
> 
> 
> On 05/10/2022 13:29, Takashi Iwai wrote:
> 
> ...
> 
> >> HDA playback is failing on -next for various Tegra boards. Bisect is
> >> point to this commit and reverting it fixes the problem. I was a bit
> >> puzzled why this change is causing a problem, but looking closer there
> >> is a difference between the previous code that was calling
> >> snd_hdac_stream_readb() and the new code that is calling
> >> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
> >> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
> >> which Tegra does and then would call snd_hdac_aligned_read(). However,
> >> now the code always call readb() and this is breaking Tegra.
> >> 
> >> So it is either necessary to update snd_hdac_stream_readb_poll() to
> >> handle this or revert this change.
> > 
> > Does the patch below work?
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > -- 8< --
> > --- a/include/sound/hdaudio.h
> > +++ b/include/sound/hdaudio.h
> > @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
> >   #define snd_hdac_stream_readb(dev, reg) \
> >   	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
> >   #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
> > -	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
> > -			   delay_us, timeout_us)
> > +	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
> > +			  false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
> >   #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
> >   	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
> >   			   delay_us, timeout_us)
> 
> 
> Amazingly it does not work. I would have thought that would, but it
> does not. I am a bit puzzled by that?

Interesting, it must be a subtle difference.
What about passing true?  It seems that the original code has the
udelay(3) before the loop.


Takashi

-- 8< --
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
 #define snd_hdac_stream_readb(dev, reg) \
 	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
-	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
-			   delay_us, timeout_us)
+	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
+			  true, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
 	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
 			   delay_us, timeout_us)
Jon Hunter Oct. 5, 2022, 2:26 p.m. UTC | #5
On 05/10/2022 15:07, Takashi Iwai wrote:
> On Wed, 05 Oct 2022 15:52:01 +0200,
> Jon Hunter wrote:
>>
>>
>> On 05/10/2022 13:29, Takashi Iwai wrote:
>>
>> ...
>>
>>>> HDA playback is failing on -next for various Tegra boards. Bisect is
>>>> point to this commit and reverting it fixes the problem. I was a bit
>>>> puzzled why this change is causing a problem, but looking closer there
>>>> is a difference between the previous code that was calling
>>>> snd_hdac_stream_readb() and the new code that is calling
>>>> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
>>>> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
>>>> which Tegra does and then would call snd_hdac_aligned_read(). However,
>>>> now the code always call readb() and this is breaking Tegra.
>>>>
>>>> So it is either necessary to update snd_hdac_stream_readb_poll() to
>>>> handle this or revert this change.
>>>
>>> Does the patch below work?
>>>
>>>
>>> thanks,
>>>
>>> Takashi
>>>
>>> -- 8< --
>>> --- a/include/sound/hdaudio.h
>>> +++ b/include/sound/hdaudio.h
>>> @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
>>>    #define snd_hdac_stream_readb(dev, reg) \
>>>    	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>>    #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
>>> -	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>>> -			   delay_us, timeout_us)
>>> +	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
>>> +			  false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>>    #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
>>>    	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>>>    			   delay_us, timeout_us)
>>
>>
>> Amazingly it does not work. I would have thought that would, but it
>> does not. I am a bit puzzled by that?
> 
> Interesting, it must be a subtle difference.
> What about passing true?  It seems that the original code has the
> udelay(3) before the loop.


I wondered the same and tried that, but still not working.

Jon
Amadeusz Sławiński Oct. 5, 2022, 2:47 p.m. UTC | #6
On 10/5/2022 4:26 PM, Jon Hunter wrote:
> 
> 
> On 05/10/2022 15:07, Takashi Iwai wrote:
>> On Wed, 05 Oct 2022 15:52:01 +0200,
>> Jon Hunter wrote:
>>>
>>>
>>> On 05/10/2022 13:29, Takashi Iwai wrote:
>>>
>>> ...
>>>
>>>>> HDA playback is failing on -next for various Tegra boards. Bisect is
>>>>> point to this commit and reverting it fixes the problem. I was a bit
>>>>> puzzled why this change is causing a problem, but looking closer there
>>>>> is a difference between the previous code that was calling
>>>>> snd_hdac_stream_readb() and the new code that is calling
>>>>> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
>>>>> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
>>>>> which Tegra does and then would call snd_hdac_aligned_read(). However,
>>>>> now the code always call readb() and this is breaking Tegra.
>>>>>
>>>>> So it is either necessary to update snd_hdac_stream_readb_poll() to
>>>>> handle this or revert this change.
>>>>
>>>> Does the patch below work?
>>>>
>>>>
>>>> thanks,
>>>>
>>>> Takashi
>>>>
>>>> -- 8< --
>>>> --- a/include/sound/hdaudio.h
>>>> +++ b/include/sound/hdaudio.h
>>>> @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct 
>>>> hdac_bus *bus,
>>>>    #define snd_hdac_stream_readb(dev, reg) \
>>>>        snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>>>    #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, 
>>>> timeout_us) \
>>>> -    readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>>>> -               delay_us, timeout_us)
>>>> +    read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, 
>>>> timeout_us,\
>>>> +              false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>>>    #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, 
>>>> timeout_us) \
>>>>        readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, 
>>>> cond, \
>>>>                   delay_us, timeout_us)
>>>
>>>
>>> Amazingly it does not work. I would have thought that would, but it
>>> does not. I am a bit puzzled by that?
>>
>> Interesting, it must be a subtle difference.
>> What about passing true?  It seems that the original code has the
>> udelay(3) before the loop.
> 
> 
> I wondered the same and tried that, but still not working.
> 
> Jon
> 

Well in worse case we can revert the patch in question, but I would like 
to get it working...

Maybe also try to raise timeout to 1000, as what original code called 
timeout, was actually number of retries? So 300 * udelay(3) which is 
more or less 900us, so we can round it up for test?

I mean, something like:

--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -176,7 +176,7 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
         snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);

         /* wait for hardware to report that the stream entered reset */
-       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & 
SD_CTL_STREAM_RESET), 3, 300);
+       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & 
SD_CTL_STREAM_RESET), 3, 1000);

         if (azx_dev->bus->dma_stop_delay && dma_run_state)
                 udelay(azx_dev->bus->dma_stop_delay);
@@ -184,7 +184,7 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
         snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);

         /* wait for hardware to report that the stream is out of reset */
-       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & 
SD_CTL_STREAM_RESET), 3, 300);
+       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & 
SD_CTL_STREAM_RESET), 3, 1000);

         /* reset first position - may not be synced with hw at this time */
         if (azx_dev->posbuf)


in addition to Takashi suggestion?
Jon Hunter Oct. 5, 2022, 8:16 p.m. UTC | #7
On 05/10/2022 15:47, Amadeusz Sławiński wrote:

...

> Well in worse case we can revert the patch in question, but I would like 
> to get it working...
> 
> Maybe also try to raise timeout to 1000, as what original code called 
> timeout, was actually number of retries? So 300 * udelay(3) which is 
> more or less 900us, so we can round it up for test?
> 
> I mean, something like:
> 
> --- a/sound/hda/hdac_stream.c
> +++ b/sound/hda/hdac_stream.c
> @@ -176,7 +176,7 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
>          snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
> 
>          /* wait for hardware to report that the stream entered reset */
> -       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & 
> SD_CTL_STREAM_RESET), 3, 300);
> +       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & 
> SD_CTL_STREAM_RESET), 3, 1000);
> 
>          if (azx_dev->bus->dma_stop_delay && dma_run_state)
>                  udelay(azx_dev->bus->dma_stop_delay);
> @@ -184,7 +184,7 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
>          snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
> 
>          /* wait for hardware to report that the stream is out of reset */
> -       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & 
> SD_CTL_STREAM_RESET), 3, 300);
> +       snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & 
> SD_CTL_STREAM_RESET), 3, 1000);
> 
>          /* reset first position - may not be synced with hw at this 
> time */
>          if (azx_dev->posbuf)
> 
> 
> in addition to Takashi suggestion?


Thanks. Tried that on top of Takaski's patch but still not working :-(

Jon
Jon Hunter Oct. 6, 2022, 8:45 a.m. UTC | #8
On 05/10/2022 13:29, Takashi Iwai wrote:

...

>> HDA playback is failing on -next for various Tegra boards. Bisect is
>> point to this commit and reverting it fixes the problem. I was a bit
>> puzzled why this change is causing a problem, but looking closer there
>> is a difference between the previous code that was calling
>> snd_hdac_stream_readb() and the new code that is calling
>> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
>> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
>> which Tegra does and then would call snd_hdac_aligned_read(). However,
>> now the code always call readb() and this is breaking Tegra.
>>
>> So it is either necessary to update snd_hdac_stream_readb_poll() to
>> handle this or revert this change.
> 
> Does the patch below work?
> 
> 
> thanks,
> 
> Takashi
> 
> -- 8< --
> --- a/include/sound/hdaudio.h
> +++ b/include/sound/hdaudio.h
> @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
>   #define snd_hdac_stream_readb(dev, reg) \
>   	snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>   #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
> -	readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
> -			   delay_us, timeout_us)
> +	read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, timeout_us,\
> +			  false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>   #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
>   	readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>   			   delay_us, timeout_us)


So looking at this a bit more I see ...

[  199.422773] bad: scheduling from the idle thread!
[  199.427610] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G      D  C         6.0.0-rc7-next-20220930-00007-gd6ae4ed0a78f-dirty #23
[  199.438880] Hardware name: NVIDIA Jetson Nano Developer Kit (DT)
[  199.444899] Call trace:
[  199.447357]  dump_backtrace.part.7+0xe8/0xf8
[  199.451680]  show_stack+0x14/0x38
[  199.455024]  dump_stack_lvl+0x64/0x7c
[  199.458715]  dump_stack+0x14/0x2c
[  199.462067]  dequeue_task_idle+0x2c/0x58
[  199.466038]  dequeue_task+0x38/0x98
[  199.469565]  __schedule+0x4a4/0x6d8
[  199.473104]  schedule+0x58/0xc0
[  199.476292]  schedule_hrtimeout_range_clock+0x98/0x108
[  199.481472]  schedule_hrtimeout_range+0x10/0x18
[  199.486039]  usleep_range_state+0x7c/0xb0
[  199.490084]  snd_hdac_stream_reset+0xe8/0x328 [snd_hda_core]
[  199.495913]  snd_hdac_stream_sync+0xe4/0x190 [snd_hda_core]
[  199.501627]  azx_pcm_trigger+0x1d8/0x250 [snd_hda_codec]
[  199.507109]  snd_pcm_do_stop+0x54/0x70
[  199.510904]  snd_pcm_action_single+0x44/0xa0
[  199.515215]  snd_pcm_drain_done+0x20/0x28
[  199.519267]  snd_pcm_update_state+0x114/0x128
[  199.523670]  snd_pcm_update_hw_ptr0+0x22c/0x3a0
[  199.528246]  snd_pcm_period_elapsed_under_stream_lock+0x44/0x88
[  199.534216]  snd_pcm_period_elapsed+0x24/0x48
[  199.538617]  stream_update+0x3c/0x50 [snd_hda_codec]
[  199.543737]  snd_hdac_bus_handle_stream_irq+0xe8/0x150 [snd_hda_core]
[  199.550320]  azx_interrupt+0xb4/0x1b0 [snd_hda_codec]
[  199.555524]  __handle_irq_event_percpu+0x74/0x140
[  199.560281]  handle_irq_event_percpu+0x14/0x48
[  199.564772]  handle_irq_event+0x44/0x88
[  199.568653]  handle_fasteoi_irq+0xa8/0x130
[  199.572788]  generic_handle_domain_irq+0x28/0x40
[  199.577452]  gic_handle_irq+0x9c/0xb8
[  199.581168]  call_on_irq_stack+0x2c/0x40
[  199.585129]  do_interrupt_handler+0x7c/0x80
[  199.589355]  el1_interrupt+0x34/0x68
[  199.592969]  el1h_64_irq_handler+0x14/0x20
[  199.597107]  el1h_64_irq+0x64/0x68
[  199.600540]  cpuidle_enter_state+0x130/0x2f8
[  199.604853]  cpuidle_enter+0x38/0x50
[  199.608463]  call_cpuidle+0x18/0x38
[  199.611991]  do_idle+0x1f8/0x248
[  199.615259]  cpu_startup_entry+0x20/0x28
[  199.619224]  kernel_init+0x0/0x128
[  199.622669]  arch_post_acpi_subsys_init+0x0/0x8
[  199.627240]  start_kernel+0x630/0x668
[  199.630933]  __primary_switched+0xb4/0xbc


If I change your patch to be read_poll_timeout_atomic, then it works \o/

Can we make that update?

Jon
Amadeusz Sławiński Oct. 7, 2022, 8:49 a.m. UTC | #9
On 10/6/2022 10:45 AM, Jon Hunter wrote:
> 
> On 05/10/2022 13:29, Takashi Iwai wrote:
> 
> ...
> 
>>> HDA playback is failing on -next for various Tegra boards. Bisect is
>>> point to this commit and reverting it fixes the problem. I was a bit
>>> puzzled why this change is causing a problem, but looking closer there
>>> is a difference between the previous code that was calling
>>> snd_hdac_stream_readb() and the new code that is calling
>>> snd_hdac_stream_readb_poll(). The function snd_hdac_stream_readb()
>>> calls snd_hdac_aligned_mmio() is see if the device has an aligned MMIO
>>> which Tegra does and then would call snd_hdac_aligned_read(). However,
>>> now the code always call readb() and this is breaking Tegra.
>>>
>>> So it is either necessary to update snd_hdac_stream_readb_poll() to
>>> handle this or revert this change.
>>
>> Does the patch below work?
>>
>>
>> thanks,
>>
>> Takashi
>>
>> -- 8< --
>> --- a/include/sound/hdaudio.h
>> +++ b/include/sound/hdaudio.h
>> @@ -592,8 +592,8 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus 
>> *bus,
>>   #define snd_hdac_stream_readb(dev, reg) \
>>       snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>   #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, 
>> timeout_us) \
>> -    readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>> -               delay_us, timeout_us)
>> +    read_poll_timeout(snd_hdac_reg_readb, val, cond, delay_us, 
>> timeout_us,\
>> +              false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
>>   #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, 
>> timeout_us) \
>>       readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
>>                  delay_us, timeout_us)
> 
> 
> So looking at this a bit more I see ...
> 
> [  199.422773] bad: scheduling from the idle thread!
> [  199.427610] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G      D  
> C         6.0.0-rc7-next-20220930-00007-gd6ae4ed0a78f-dirty #23
> [  199.438880] Hardware name: NVIDIA Jetson Nano Developer Kit (DT)
> [  199.444899] Call trace:
> [  199.447357]  dump_backtrace.part.7+0xe8/0xf8
> [  199.451680]  show_stack+0x14/0x38
> [  199.455024]  dump_stack_lvl+0x64/0x7c
> [  199.458715]  dump_stack+0x14/0x2c
> [  199.462067]  dequeue_task_idle+0x2c/0x58
> [  199.466038]  dequeue_task+0x38/0x98
> [  199.469565]  __schedule+0x4a4/0x6d8
> [  199.473104]  schedule+0x58/0xc0
> [  199.476292]  schedule_hrtimeout_range_clock+0x98/0x108
> [  199.481472]  schedule_hrtimeout_range+0x10/0x18
> [  199.486039]  usleep_range_state+0x7c/0xb0
> [  199.490084]  snd_hdac_stream_reset+0xe8/0x328 [snd_hda_core]
> [  199.495913]  snd_hdac_stream_sync+0xe4/0x190 [snd_hda_core]
> [  199.501627]  azx_pcm_trigger+0x1d8/0x250 [snd_hda_codec]
> [  199.507109]  snd_pcm_do_stop+0x54/0x70
> [  199.510904]  snd_pcm_action_single+0x44/0xa0
> [  199.515215]  snd_pcm_drain_done+0x20/0x28
> [  199.519267]  snd_pcm_update_state+0x114/0x128
> [  199.523670]  snd_pcm_update_hw_ptr0+0x22c/0x3a0
> [  199.528246]  snd_pcm_period_elapsed_under_stream_lock+0x44/0x88
> [  199.534216]  snd_pcm_period_elapsed+0x24/0x48
> [  199.538617]  stream_update+0x3c/0x50 [snd_hda_codec]
> [  199.543737]  snd_hdac_bus_handle_stream_irq+0xe8/0x150 [snd_hda_core]
> [  199.550320]  azx_interrupt+0xb4/0x1b0 [snd_hda_codec]
> [  199.555524]  __handle_irq_event_percpu+0x74/0x140
> [  199.560281]  handle_irq_event_percpu+0x14/0x48
> [  199.564772]  handle_irq_event+0x44/0x88
> [  199.568653]  handle_fasteoi_irq+0xa8/0x130
> [  199.572788]  generic_handle_domain_irq+0x28/0x40
> [  199.577452]  gic_handle_irq+0x9c/0xb8
> [  199.581168]  call_on_irq_stack+0x2c/0x40
> [  199.585129]  do_interrupt_handler+0x7c/0x80
> [  199.589355]  el1_interrupt+0x34/0x68
> [  199.592969]  el1h_64_irq_handler+0x14/0x20
> [  199.597107]  el1h_64_irq+0x64/0x68
> [  199.600540]  cpuidle_enter_state+0x130/0x2f8
> [  199.604853]  cpuidle_enter+0x38/0x50
> [  199.608463]  call_cpuidle+0x18/0x38
> [  199.611991]  do_idle+0x1f8/0x248
> [  199.615259]  cpu_startup_entry+0x20/0x28
> [  199.619224]  kernel_init+0x0/0x128
> [  199.622669]  arch_post_acpi_subsys_init+0x0/0x8
> [  199.627240]  start_kernel+0x630/0x668
> [  199.630933]  __primary_switched+0xb4/0xbc
> 
> 
> If I change your patch to be read_poll_timeout_atomic, then it works \o/
> 
> Can we make that update?
> 
> Jon
> 

Yes, it makes sense, as it uses udelay instead of usleep, same as 
original code.

I've send patch which updates the macros. It passed validation on our side.

Thanks for report!

Amadeusz
diff mbox series

Patch

diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index f3582012d22f..bdf6d4db6769 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -165,7 +165,6 @@  EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
 void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
 {
 	unsigned char val;
-	int timeout;
 	int dma_run_state;
 
 	snd_hdac_stream_clear(azx_dev);
@@ -173,30 +172,17 @@  void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
 	dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
 
 	snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
-	udelay(3);
-	timeout = 300;
-	do {
-		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
-			SD_CTL_STREAM_RESET;
-		if (val)
-			break;
-	} while (--timeout);
+
+	/* wait for hardware to report that the stream entered reset */
+	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
 
 	if (azx_dev->bus->dma_stop_delay && dma_run_state)
 		udelay(azx_dev->bus->dma_stop_delay);
 
-	val &= ~SD_CTL_STREAM_RESET;
-	snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
-	udelay(3);
+	snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
 
-	timeout = 300;
-	/* waiting for hardware to report that the stream is out of reset */
-	do {
-		val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
-			SD_CTL_STREAM_RESET;
-		if (!val)
-			break;
-	} while (--timeout);
+	/* wait for hardware to report that the stream is out of reset */
+	snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
 
 	/* reset first position - may not be synced with hw at this time */
 	if (azx_dev->posbuf)