aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2014-04-28 08:30:51 -0400
committerMark Brown <broonie@linaro.org>2014-04-29 13:09:11 -0400
commit4da533932dedff930596bc536adaba1e508f9ffa (patch)
treeb3e54c8d576cf3c0a05652a0d184c286908389de
parent907fe36a2cd572fe58d98be01457b945c47b996e (diff)
ASoC: core: Fix component_list corruption when unloading modules
This fixes module unload regressions introduced by commits 98e639fb8a3e ("ASoC: Track which components have been registered with snd_soc_register_component()") and b37f1d123c69 ("ASoC: Let snd_soc_platform subclass snd_soc_component"). First commit causes component_list to be corrupted when removing codec and second when removing platform. Reason for both is that components associated with platform or codec are never removed from the list because for them registered_as_component field in struct snd_soc_component is always false. Now list becomes corrupted when snd_soc_unregister_platform() or snd_soc_unregister_codec() frees the platform or codec structure and where the associated struct snd_soc_component is embedded. Fix these by moving component unregistration and cleanup to a new local function __snd_soc_unregister_component() that takes component as its argument. Since component is known for platforms and codecs the __snd_soc_unregister_component() can be called directly and snd_soc_unregister_component() takes care to find and unregister only components that were registered using snd_soc_register_component(). Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/soc-core.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d5cd80b6d320..4a381b307b08 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4010,6 +4010,18 @@ int snd_soc_register_component(struct device *dev,
4010} 4010}
4011EXPORT_SYMBOL_GPL(snd_soc_register_component); 4011EXPORT_SYMBOL_GPL(snd_soc_register_component);
4012 4012
4013static void __snd_soc_unregister_component(struct snd_soc_component *cmpnt)
4014{
4015 snd_soc_unregister_dais(cmpnt);
4016
4017 mutex_lock(&client_mutex);
4018 list_del(&cmpnt->list);
4019 mutex_unlock(&client_mutex);
4020
4021 dev_dbg(cmpnt->dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
4022 kfree(cmpnt->name);
4023}
4024
4013/** 4025/**
4014 * snd_soc_unregister_component - Unregister a component from the ASoC core 4026 * snd_soc_unregister_component - Unregister a component from the ASoC core
4015 * 4027 *
@@ -4025,14 +4037,7 @@ void snd_soc_unregister_component(struct device *dev)
4025 return; 4037 return;
4026 4038
4027found: 4039found:
4028 snd_soc_unregister_dais(cmpnt); 4040 __snd_soc_unregister_component(cmpnt);
4029
4030 mutex_lock(&client_mutex);
4031 list_del(&cmpnt->list);
4032 mutex_unlock(&client_mutex);
4033
4034 dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
4035 kfree(cmpnt->name);
4036} 4041}
4037EXPORT_SYMBOL_GPL(snd_soc_unregister_component); 4042EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
4038 4043
@@ -4132,7 +4137,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
4132 */ 4137 */
4133void snd_soc_remove_platform(struct snd_soc_platform *platform) 4138void snd_soc_remove_platform(struct snd_soc_platform *platform)
4134{ 4139{
4135 snd_soc_unregister_component(platform->dev); 4140 __snd_soc_unregister_component(&platform->component);
4136 4141
4137 mutex_lock(&client_mutex); 4142 mutex_lock(&client_mutex);
4138 list_del(&platform->list); 4143 list_del(&platform->list);
@@ -4337,7 +4342,7 @@ void snd_soc_unregister_codec(struct device *dev)
4337 return; 4342 return;
4338 4343
4339found: 4344found:
4340 snd_soc_unregister_component(dev); 4345 __snd_soc_unregister_component(&codec->component);
4341 4346
4342 mutex_lock(&client_mutex); 4347 mutex_lock(&client_mutex);
4343 list_del(&codec->list); 4348 list_del(&codec->list);