[3/3] ALSA: HDA: wait for RIRB, CORB DMA to finish
diff mbox

Message ID 1438660720-30033-4-git-send-email-vinod.koul@intel.com
State New
Headers show

Commit Message

Vinod Koul Aug. 4, 2015, 3:58 a.m. UTC
HDA spec says that RORB and CORB DMA stop will take some
time to complete.  So we should wait till the DMAs are
stopped.

Although the current controllers don't have multilinks so
doesn't impact much, but SKL onwards we have multiple links
so waiting for DMAs to stop makes better sense.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 sound/hda/hdac_controller.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

Comments

Takashi Iwai Aug. 4, 2015, 5:13 a.m. UTC | #1
On Tue, 04 Aug 2015 05:58:40 +0200,
Vinod Koul wrote:
> 
> HDA spec says that RORB and CORB DMA stop will take some
> time to complete.  So we should wait till the DMAs are
> stopped.
> 
> Although the current controllers don't have multilinks so
> doesn't impact much, but SKL onwards we have multiple links
> so waiting for DMAs to stop makes better sense.
> 
> Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> ---
>  sound/hda/hdac_controller.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
> index b5a17cb510a0..3b5d07174d79 100644
> --- a/sound/hda/hdac_controller.c
> +++ b/sound/hda/hdac_controller.c
> @@ -86,10 +86,24 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
>   */
>  void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
>  {
> +	unsigned long timeout;
> +
>  	spin_lock_irq(&bus->reg_lock);
>  	/* disable ringbuffer DMAs */
>  	snd_hdac_chip_writeb(bus, RIRBCTL, 0);
>  	snd_hdac_chip_writeb(bus, CORBCTL, 0);
> +
> +	/* poll DMAs to check if they stopped or not */
> +
> +	timeout = jiffies + msecs_to_jiffies(100);
> +	while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN) &&
> +	       time_before(jiffies, timeout))
> +		usleep_range(500, 1000);

You must not use *sleep() inside atomic context.


Takashi
Vinod Koul Aug. 4, 2015, 9:10 a.m. UTC | #2
On Tue, Aug 04, 2015 at 07:13:12AM +0200, Takashi Iwai wrote:
> > @@ -86,10 +86,24 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
> >   */
> >  void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
> >  {
> > +	unsigned long timeout;
> > +
> >  	spin_lock_irq(&bus->reg_lock);
> >  	/* disable ringbuffer DMAs */
> >  	snd_hdac_chip_writeb(bus, RIRBCTL, 0);
> >  	snd_hdac_chip_writeb(bus, CORBCTL, 0);
> > +
> > +	/* poll DMAs to check if they stopped or not */
> > +
> > +	timeout = jiffies + msecs_to_jiffies(100);
> > +	while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN) &&
> > +	       time_before(jiffies, timeout))
> > +		usleep_range(500, 1000);
> 
> You must not use *sleep() inside atomic context.
Right, not sure why it didnt crib when we tested, will send updated one soon

Thanks for the super quick review :)

Patch
diff mbox

diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c
index b5a17cb510a0..3b5d07174d79 100644
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -86,10 +86,24 @@  EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
  */
 void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
 {
+	unsigned long timeout;
+
 	spin_lock_irq(&bus->reg_lock);
 	/* disable ringbuffer DMAs */
 	snd_hdac_chip_writeb(bus, RIRBCTL, 0);
 	snd_hdac_chip_writeb(bus, CORBCTL, 0);
+
+	/* poll DMAs to check if they stopped or not */
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN) &&
+	       time_before(jiffies, timeout))
+		usleep_range(500, 1000);
+	timeout = jiffies + msecs_to_jiffies(100);
+	while ((snd_hdac_chip_readb(bus, CORBCTL) & AZX_CORBCTL_RUN) &&
+	       time_before(jiffies, timeout))
+		usleep_range(500, 1000);
+
 	/* disable unsolicited responses */
 	snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0);
 	spin_unlock_irq(&bus->reg_lock);