[alsa-devel] [PATCH 1/4] ASoC: Free the card's DAPM context
Free the card's DAPM context when the card is removed.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-core.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a823654..6a3cb53 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2047,6 +2047,8 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) if (card->remove) card->remove(card);
+ snd_soc_dapm_free(&card->dapm); + kfree(card->rtd); snd_card_free(card->snd_card); return 0;
Move the creation of the DAPM debugfs directory to snd_soc_dapm_debugfs_init instead of having the same duplicated code in both codec and card DAPM setup.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- include/sound/soc-dapm.h | 3 ++- sound/soc/soc-core.c | 16 ++-------------- sound/soc/soc-dapm.c | 13 ++++++++++--- 3 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index d5f1b9a..f8a7c9a 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -356,7 +356,8 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card);
/* dapm sys fs - used by the core */ int snd_soc_dapm_sys_add(struct device *dev); -void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, + struct dentry *parent);
/* dapm audio pin control and status */ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6a3cb53..983ec64 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -302,13 +302,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) printk(KERN_WARNING "ASoC: Failed to create codec register debugfs file\n");
- codec->dapm.debugfs_dapm = debugfs_create_dir("dapm", - codec->debugfs_codec_root); - if (!codec->dapm.debugfs_dapm) - printk(KERN_WARNING - "Failed to create DAPM debugfs directory\n"); - - snd_soc_dapm_debugfs_init(&codec->dapm); + snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); }
static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) @@ -1926,13 +1920,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) card->num_dapm_routes);
#ifdef CONFIG_DEBUG_FS - card->dapm.debugfs_dapm = debugfs_create_dir("dapm", - card->debugfs_card_root); - if (!card->dapm.debugfs_dapm) - printk(KERN_WARNING - "Failed to create card DAPM debugfs directory\n"); - - snd_soc_dapm_debugfs_init(&card->dapm); + snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); #endif
snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 378f08a..ffed456 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1254,13 +1254,19 @@ static const struct file_operations dapm_bias_fops = { .llseek = default_llseek, };
-void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) +void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, + struct dentry *parent) { struct snd_soc_dapm_widget *w; struct dentry *d;
- if (!dapm->debugfs_dapm) + dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); + + if (!dapm->debugfs_dapm) { + printk(KERN_WARNING + "Failed to create DAPM debugfs directory\n"); return; + }
d = debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm, @@ -1283,7 +1289,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) } } #else -void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) +void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, + struct dentry *parent) { } #endif
Currently debugfs entries for a DAPM widgets are only added in snd_soc_dapm_debugfs_init. If a widget is added later (for example in the dai_link's probe callback) it will not show up in debugfs. This patch moves the creation of the widget debugfs entry to snd_soc_dapm_new_widgets where it will be added after the widget has been properly instantiated.
As a side-effect this will also reduce the number of times the DAPM widget list is iterated during a card's instantiation.
Since it is possible that snd_soc_dapm_new_widgets is invoked form the codecs or cards probe callbacks, the creation of the debugfs dapm directory has to be moved before these are called.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-core.c | 13 +++++++------ sound/soc/soc-dapm.c | 35 +++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 983ec64..fbd011eb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1493,6 +1493,8 @@ static int soc_probe_codec(struct snd_soc_card *card, if (!try_module_get(codec->dev->driver->owner)) return -ENODEV;
+ soc_init_codec_debugfs(codec); + if (driver->probe) { ret = driver->probe(codec); if (ret < 0) { @@ -1513,8 +1515,6 @@ static int soc_probe_codec(struct snd_soc_card *card, snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, driver->num_dapm_routes);
- soc_init_codec_debugfs(codec); - /* mark codec as probed and add to card codec list */ codec->probed = 1; list_add(&codec->card_list, &card->codec_dev_list); @@ -1523,6 +1523,7 @@ static int soc_probe_codec(struct snd_soc_card *card, return 0;
err_probe: + soc_cleanup_codec_debugfs(codec); module_put(codec->dev->driver->owner);
return ret; @@ -1873,6 +1874,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) card->dapm.card = card; list_add(&card->dapm.list, &card->dapm_list);
+#ifdef CONFIG_DEBUG_FS + snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); +#endif + #ifdef CONFIG_PM_SLEEP /* deferred resume work */ INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); @@ -1919,10 +1924,6 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes);
-#ifdef CONFIG_DEBUG_FS - snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); -#endif - snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), "%s", card->name); snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ffed456..8454cc2 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1257,7 +1257,6 @@ static const struct file_operations dapm_bias_fops = { void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent) { - struct snd_soc_dapm_widget *w; struct dentry *d;
dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); @@ -1274,25 +1273,35 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, if (!d) dev_warn(dapm->dev, "ASoC: Failed to create bias level debugfs file\n"); +}
- list_for_each_entry(w, &dapm->card->widgets, list) { - if (!w->name || w->dapm != dapm) - continue; +static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct dentry *d;
- d = debugfs_create_file(w->name, 0444, - dapm->debugfs_dapm, w, - &dapm_widget_power_fops); - if (!d) - dev_warn(w->dapm->dev, - "ASoC: Failed to create %s debugfs file\n", - w->name); - } + if (!dapm->debugfs_dapm || !w->name) + return; + + d = debugfs_create_file(w->name, 0444, + dapm->debugfs_dapm, w, + &dapm_widget_power_fops); + if (!d) + dev_warn(w->dapm->dev, + "ASoC: Failed to create %s debugfs file\n", + w->name); } + #else void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent) { } + +static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) +{ +} + #endif
/* test and update the power status of a mux widget */ @@ -1765,6 +1774,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) }
w->new = 1; + + dapm_debugfs_add_widget(w); }
dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
Remove the DAPM debugfs entries before freeing the context's widgets, otherwise a use after free situation might occur.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- sound/soc/soc-dapm.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8454cc2..169e176 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1292,6 +1292,11 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) w->name); }
+static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) +{ + debugfs_remove_recursive(dapm->debugfs_dapm); +} + #else void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent) @@ -1302,6 +1307,10 @@ static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) { }
+static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) +{ +} + #endif
/* test and update the power status of a mux widget */ @@ -2445,6 +2454,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) { snd_soc_dapm_sys_remove(dapm->dev); + dapm_debugfs_cleanup(dapm); dapm_free_widgets(dapm); list_del(&dapm->list); }
On Sat, 2011-04-30 at 19:45 +0200, Lars-Peter Clausen wrote:
Free the card's DAPM context when the card is removed.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de
All
Acked-by: Liam Girdwood lrg@ti.com
participants (3)
-
Lars-Peter Clausen
-
Liam Girdwood
-
Mark Brown