aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-20 16:43:24 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-21 09:53:44 -0400
commitde02d0786d4075091f5b1860474cd21d85ff5862 (patch)
tree5767c43edb3ee26429b7ce1dd2e42a9f96a28965
parent6d4baf084f4d8dc43cf5d5a3c182018604afa80c (diff)
ASoC: Trace and collect statistics for DAPM graph walking
One of the longest standing areas for improvement in ASoC has been the DAPM algorithm - it repeats the same checks many times whenever it is run and makes no effort to limit the areas of the graph it checks meaning we do an awful lot of walks over the full graph. This has never mattered too much as the size of the graph has generally been small in relation to the size of the devices supported and the speed of CPUs but it is annoying. In preparation for work on improving this insert a trace point after the graph walk has been done. This gives us specific timing information for the walk, and in order to give quantifiable (non-benchmark) numbers also count every time we check a link or check the power for a widget and report those numbers. Substantial changes in the algorithm may require tweaks to the stats but they should be useful for simpler things. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--include/sound/soc-dapm.h5
-rw-r--r--include/sound/soc.h1
-rw-r--r--include/trace/events/asoc.h22
-rw-r--r--sound/soc/soc-dapm.c17
4 files changed, 45 insertions, 0 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 350b1b395cac..0e2d01713cb6 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -537,4 +537,9 @@ struct snd_soc_dapm_widget_list {
537 struct snd_soc_dapm_widget *widgets[0]; 537 struct snd_soc_dapm_widget *widgets[0];
538}; 538};
539 539
540struct snd_soc_dapm_stats {
541 int power_checks;
542 int path_checks;
543};
544
540#endif 545#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 24e17be38c19..006f4f633c52 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -828,6 +828,7 @@ struct snd_soc_card {
828 828
829 /* Generic DAPM context for the card */ 829 /* Generic DAPM context for the card */
830 struct snd_soc_dapm_context dapm; 830 struct snd_soc_dapm_context dapm;
831 struct snd_soc_dapm_stats dapm_stats;
831 832
832#ifdef CONFIG_DEBUG_FS 833#ifdef CONFIG_DEBUG_FS
833 struct dentry *debugfs_card_root; 834 struct dentry *debugfs_card_root;
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index 603f5a0f0365..2e1adf62e0a8 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -216,6 +216,28 @@ DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
216 216
217); 217);
218 218
219TRACE_EVENT(snd_soc_dapm_walk_done,
220
221 TP_PROTO(struct snd_soc_card *card),
222
223 TP_ARGS(card),
224
225 TP_STRUCT__entry(
226 __string( name, card->name )
227 __field( int, power_checks )
228 __field( int, path_checks )
229 ),
230
231 TP_fast_assign(
232 __assign_str(name, card->name);
233 __entry->power_checks = card->dapm_stats.power_checks;
234 __entry->path_checks = card->dapm_stats.path_checks;
235 ),
236
237 TP_printk("%s: %d power checks, %d path checks", __get_str(name),
238 (int)__entry->power_checks, (int)__entry->path_checks)
239);
240
219TRACE_EVENT(snd_soc_jack_irq, 241TRACE_EVENT(snd_soc_jack_irq,
220 242
221 TP_PROTO(const char *name), 243 TP_PROTO(const char *name),
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4a440b52dd7a..6a1e13ea996d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -48,6 +48,8 @@
48 48
49#include <trace/events/asoc.h> 49#include <trace/events/asoc.h>
50 50
51#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
52
51/* dapm power sequences - make this per codec in the future */ 53/* dapm power sequences - make this per codec in the future */
52static int dapm_up_seq[] = { 54static int dapm_up_seq[] = {
53 [snd_soc_dapm_pre] = 0, 55 [snd_soc_dapm_pre] = 0,
@@ -649,6 +651,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
649 struct snd_soc_dapm_path *path; 651 struct snd_soc_dapm_path *path;
650 int con = 0; 652 int con = 0;
651 653
654 DAPM_UPDATE_STAT(widget, path_checks);
655
652 if (widget->id == snd_soc_dapm_supply) 656 if (widget->id == snd_soc_dapm_supply)
653 return 0; 657 return 0;
654 658
@@ -697,6 +701,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
697 struct snd_soc_dapm_path *path; 701 struct snd_soc_dapm_path *path;
698 int con = 0; 702 int con = 0;
699 703
704 DAPM_UPDATE_STAT(widget, path_checks);
705
700 if (widget->id == snd_soc_dapm_supply) 706 if (widget->id == snd_soc_dapm_supply)
701 return 0; 707 return 0;
702 708
@@ -767,6 +773,8 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
767{ 773{
768 int in, out; 774 int in, out;
769 775
776 DAPM_UPDATE_STAT(w, power_checks);
777
770 in = is_connected_input_ep(w); 778 in = is_connected_input_ep(w);
771 dapm_clear_walk(w->dapm); 779 dapm_clear_walk(w->dapm);
772 out = is_connected_output_ep(w); 780 out = is_connected_output_ep(w);
@@ -779,6 +787,8 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
779{ 787{
780 int in; 788 int in;
781 789
790 DAPM_UPDATE_STAT(w, power_checks);
791
782 if (w->active) { 792 if (w->active) {
783 in = is_connected_input_ep(w); 793 in = is_connected_input_ep(w);
784 dapm_clear_walk(w->dapm); 794 dapm_clear_walk(w->dapm);
@@ -793,6 +803,8 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
793{ 803{
794 int out; 804 int out;
795 805
806 DAPM_UPDATE_STAT(w, power_checks);
807
796 if (w->active) { 808 if (w->active) {
797 out = is_connected_output_ep(w); 809 out = is_connected_output_ep(w);
798 dapm_clear_walk(w->dapm); 810 dapm_clear_walk(w->dapm);
@@ -808,6 +820,8 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
808 struct snd_soc_dapm_path *path; 820 struct snd_soc_dapm_path *path;
809 int power = 0; 821 int power = 0;
810 822
823 DAPM_UPDATE_STAT(w, power_checks);
824
811 /* Check if one of our outputs is connected */ 825 /* Check if one of our outputs is connected */
812 list_for_each_entry(path, &w->sinks, list_source) { 826 list_for_each_entry(path, &w->sinks, list_source) {
813 if (path->weak) 827 if (path->weak)
@@ -1208,6 +1222,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1208 } 1222 }
1209 } 1223 }
1210 1224
1225 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
1226
1211 /* Check which widgets we need to power and store them in 1227 /* Check which widgets we need to power and store them in
1212 * lists indicating if they should be powered up or down. 1228 * lists indicating if they should be powered up or down.
1213 */ 1229 */
@@ -1299,6 +1315,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1299 list_for_each_entry(d, &card->dapm_list, list) 1315 list_for_each_entry(d, &card->dapm_list, list)
1300 d->target_bias_level = bias; 1316 d->target_bias_level = bias;
1301 1317
1318 trace_snd_soc_dapm_walk_done(card);
1302 1319
1303 /* Run all the bias changes in parallel */ 1320 /* Run all the bias changes in parallel */
1304 list_for_each_entry(d, &dapm->card->dapm_list, list) 1321 list_for_each_entry(d, &dapm->card->dapm_list, list)