Message ID | 1438660720-30033-4-git-send-email-vinod.koul@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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 :)
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);