diff mbox series

ASoC: dapm: Use less aggressive caching to ensure correctness

Message ID 20181105111912.14464-1-tzungbi@google.com (mailing list archive)
State New, archived
Headers show
Series ASoC: dapm: Use less aggressive caching to ensure correctness | expand

Commit Message

Tzung-Bi Shih Nov. 5, 2018, 11:19 a.m. UTC
Commit 92a99ea439c4 ("ASoC: dapm: Use more aggressive caching") only
invalidates necessary caches to improve the cache hit rate.  However,
in snd_soc_dapm_add_path(), the cache is too aggressive which results
in wrong state of the audio map.

E.g. imaging the following examples during snd_soc_instantiate_card():

time 1: at the beginning

  in:-1    in:-1     in:-1
 out:-1   out:-1    out:-1
      A -----> B       Spk

time 2: after someone called snd_soc_dapm_new_widgets()
(e.g. create_fill_widget_route_map() in sound/soc/codecs/hdac_hdmi.c)

  in:0    in:0     in:0
 out:0   out:0    out:1
     A ----> B      Spk

time 3: route added to Spk

  in:0    in:0      in:0
 out:0   out:0     out:1
     A ----> B ----> Spk

time N: route added from SIGGEN

  in:1    in:0    in:0      in:0
 out:0   out:0   out:0     out:1
SIGGEN ----> A ----> B ----> Spk

In the end, the path will not power on but it should be.  At time 2, the
caches have been polluted.  At time 3, it will not get the correct state
if snd_soc_dapm_add_path() does not invalidate "out" of B and A.

time 3 (expected result):

  in:0    in:0      in:0
 out:1   out:1     out:1
     A ----> B ----> Spk

Signed-off-by: Tzung-Bi Shih <tzungbi@google.com>
---
 sound/soc/soc-dapm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Mark Brown Nov. 6, 2018, 5:18 p.m. UTC | #1
On Mon, Nov 05, 2018 at 07:19:12PM +0800, Tzung-Bi Shih wrote:

> +++ b/sound/soc/soc-dapm.c
> @@ -2722,7 +2722,7 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
>  		dapm_mark_dirty(widgets[dir], "Route added");
>  	}
>  
> -	if (dapm->card->instantiated && path->connect)
> +	if (path->connect)
>  		dapm_path_invalidate(path);
>  
>  	return 0;

The whole point with the instantiated check here is that when we
instantiate the card we're supposed to go through and redo all the DAPM
configuration for the card in one fell swoop rather than having to
constantly redo things while we're building up the graph.  If that
invalidation isn't happening then we should fix that.
Tzung-Bi Shih Nov. 7, 2018, 4:03 a.m. UTC | #2
The original assumption at the bottom of snd_soc_instantiate_card()
would be: all widget->endpoints are -1, and all widgets are in the
list card->dapm_dirty.  So that before returning from
snd_soc_instantiate_card(), the snd_soc_dapm_sync() can calculate
widget->endpoints and check power states for the whole graph of the
card.

However, if some widgets' endpoints have been polluted and get removed
from the dirty list in the middle of snd_soc_instantiate_card(), they
would have no chance to be recalculated at the bottom of
snd_soc_instantiate_card().

Two ideas so far:
The first one is protecting the endpoints cache and the dirty list
during card instantiating by checking card->instantiated in
is_connected_output_ep(), is_connected_input_ep(), and
dapm_power_widgets().  Note that is_connected_output_ep() and
is_connected_input_ep() will be invoked if someone read from debugfs.
We could return -1 to indicate the endpoints cache is disallowed to
access in the case.

The second one is forcing to recalculate the graph at the bottom of
snd_soc_instantiate_card() by additionally calling
dapm_mark_endpoints_dirty().  It would waste some computing power by
comparing with the first idea but it would be also simpler than the
first one.

Which one makes the most sense for you?  Or any other ideas?

On Wed, Nov 7, 2018 at 1:18 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Mon, Nov 05, 2018 at 07:19:12PM +0800, Tzung-Bi Shih wrote:
>
> > +++ b/sound/soc/soc-dapm.c
> > @@ -2722,7 +2722,7 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
> >               dapm_mark_dirty(widgets[dir], "Route added");
> >       }
> >
> > -     if (dapm->card->instantiated && path->connect)
> > +     if (path->connect)
> >               dapm_path_invalidate(path);
> >
> >       return 0;
>
> The whole point with the instantiated check here is that when we
> instantiate the card we're supposed to go through and redo all the DAPM
> configuration for the card in one fell swoop rather than having to
> constantly redo things while we're building up the graph.  If that
> invalidation isn't happening then we should fix that.
Mark Brown Nov. 14, 2018, 12:26 a.m. UTC | #3
On Wed, Nov 07, 2018 at 12:03:06PM +0800, Tzung-Bi Shih wrote:

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.

> The second one is forcing to recalculate the graph at the bottom of
> snd_soc_instantiate_card() by additionally calling
> dapm_mark_endpoints_dirty().  It would waste some computing power by
> comparing with the first idea but it would be also simpler than the
> first one.

As we just discussed in person this is probably the best option - it's
what we used to have (or were supposed to have, but I'm fairly sure I
remember writing the code), I'm guessing it's gone AWOL during all the
refactorings for componentization.
diff mbox series

Patch

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index a5178845065b..2914f3adb333 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2722,7 +2722,7 @@  static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
 		dapm_mark_dirty(widgets[dir], "Route added");
 	}
 
-	if (dapm->card->instantiated && path->connect)
+	if (path->connect)
 		dapm_path_invalidate(path);
 
 	return 0;