[alsa-devel] [PATCH V2] ASoC: fix hdmi codec driver contest in S3

Takashi Iwai tiwai at suse.de
Tue Mar 26 12:22:55 CET 2019


On Tue, 26 Mar 2019 12:19:15 +0100,
Yang, Libin wrote:
> 
> Hi Takashi,
> 
> >> Hi Takashi,
> >>
> >> >> >
> >> >> >On Tue, 26 Mar 2019 06:42:15 +0100, Yang, Libin wrote:
> >> >> >(snip)
> >> >> >> Hi Takashi,
> >> >> >> Below is my draft patch, which doesn't work with
> >> >> >> pm_runtime_get_sync(). Is there anything wrong in my code?
> >> >> >(snip)
> >> >> >> And the dmesg is:
> >> >> >> [   36.087224] HDMI HDA Codec ehdaudio0D2: in hdmi_codec_resume
> >> >1890
> >> >> >ylb
> >> >> >> [   36.087230] HDMI HDA Codec ehdaudio0D2: in
> >> >> >hdac_hdmi_runtime_resume 2122 ylb 1
> >> >> >> [   36.087335] HDMI HDA Codec ehdaudio0D2: in
> >> >> >hdac_hdmi_cvt_output_widget_event 812 ylb
> >> >> >> [   40.097586] HDMI HDA Codec ehdaudio0D2: in
> >> >> >hdac_hdmi_runtime_resume 2135 ylb 2
> >> >> >> [   40.097766] HDMI HDA Codec ehdaudio0D2: in
> >> >> >hdac_hdmi_pin_output_widget_event 767 ylb
> >> >> >> [   45.108632] HDMI HDA Codec ehdaudio0D2: in
> >> >> >hdac_hdmi_pin_mux_widget_event 857 ylb
> >> >> >>
> >> >> >> >From the dmesg, hdac_hdmi_cvt_output_widget_event()
> >> >> >> is called between "ylb 1" and "ylb 2" in runtime_resume().
> >> >> >> This means xxx_event() registers setting runs before display
> >> >> >> power is turned on.
> >> >> >
> >> >> >OK, now I understood what went wrong.  It's a similar issue as
> >> >> >we've hit for the legacy HD-audio and figured out recently.
> >> >> >
> >> >> >If my understanding is correct, the problem is the call of
> >> >> >pm_runtime_force_resume() in PM resume callback combined with an
> >> >> >async work.  pm_runtime_force_resume() sets the runtime state
> >> >> >immediately to RPM_ACTIVE even before finishing the task.  The
> >> >> >code seems assuming blindly that there is no other conflicting
> >> >> >task while
> >> >> >S3/S4 resume, but this is a problem.  That's why the next
> >> >> >pm_runtime_get_sync() wasn't blocked but just went through; since
> >> >> >the RPM flag was already set to RPM_ACTIVE in
> >> >> >pm_runtime_force_resume(), it thought as if it were already
> >> >> >active, while the real runtime resume code
> >> >was still processing the callback.
> >> >>
> >> >> Yes, exactly right. And I have checked dev->power.runtime_status,
> >> >> it's RPM_ACTIVE when xxx_event() calls pm_runtime_get_sync().
> >> >>
> >> >> >
> >> >> >In the case of legacy HD-audio, we "fixed" the problem by avoiding
> >> >> >the trigger of async work at resume, but let it be triggered from
> >> >> >runtime resume.  In ASoC case, however, it's no option.
> >> >> >
> >> >> >Maybe a possible solution in the sound driver side would be to
> >> >> >move from system suspend/resume to ASoC component
> >suspend/resume.
> >> >> >The runtime suspend/resume can be kept as is, and call
> >> >> >pm_runtime_force_suspend and resume from the component
> >> >suspend/resume
> >> >> >callbacks.  Since the component callbacks are certainly processed
> >> >> >before DAPM events, this should assure the order.
> >> >>
> >> >> I have worked out another patch. This patch decouples the
> >> >> xxx_event() and runtime suspend/resume. This means in whichever
> >> >> case, xxx_event() can make sure display power is in the correct status.
> >What do you think?
> >> >> On the same time, I will try the component suspend/resume. My
> >> >> understanding is that snd_hdac_display_power() should be called
> >> >> either in runtime_suspend/ resume or in component suspend/resume.
> >> >
> >> >This might work around the particular case, yes.  However it still
> >> >makes me uneasy as the root cause isn't full covered -- the other
> >> >part of runtime resume might be still pending while executing the DAPM
> >event.
> >> >
> >> >Now, considering the idea with device_link_add() again: I guess it's
> >> >snd_soc_resume() who kicks off the DAPM even work?  If so, and if
> >> >snd_soc_resume() gets called from the machine driver, we can assure
> >> >the PM order via device_link_add() so that the codec driver is
> >> >resumed before the machine driver.  Then at the time the deferred
> >> >resume work is executed, the codec is ready, so the display power is on.
> >>
> >> Yes, snd_soc_resume() kicks off the DAPM event work. The device PM
> >> sequence is good. The root cause is when hdmi runtime_resume calls
> >> snd_hdac_display_power(), it may sleep. The flow is:
> >>
> >> 1. HDMI runtime_resume runs
> >> 2. HDMI runtime_resume calls snd_hdac_display_power(), but display
> >> driver is also operating display power and the mutex_lock is hold. So
> >> HDMI runtime_resume sleeps.
> >> 3. the deferred work is scheduled and xxx_event() is called.
> >>
> >> This is wrong. All these happen because of the mutex_lock is hold by
> >> display driver, which causes HDMI runtime_resume sleep.
> >
> >Well, the mutex lock itself is OK, and it's designed to behave so.
> >
> >As mentioned, the root cause is pm_runtime_force_resume() that sets
> >RPM_ACTIVE while a concurrent task is running.
> >
> >OTOH, this can be seen indeed as a PM dependency between devices, and if
> >we set the order explicitly, the problem can be avoided, too.  Then the
> >runtime resume of codec finishes before snd_soc_resume() is called from the
> >machine driver resume.
> 
> Do you have any idea to set the order explicitly? What I can think of is that
> we set HDMI device to be the machine device parent?

device_link_add() should serve for defining the explicit PM
dependency.


Takashi


More information about the Alsa-devel mailing list