Skip to content

Commit 58f3015

Browse files
mripardbroonie
authored andcommitted
ASoC: core: Remove only the registered component in devm functions
The ASoC devm_ functions that register a component (devm_snd_soc_register_component and devm_snd_dmaengine_pcm_register) will clean their component by running snd_soc_unregister_component. snd_soc_unregister_component will then remove all the components for the device that was used to register the component in the first place. However, some drivers register several components (such as a DAI and a dmaengine PCM) on the same device, and if the dmaengine PCM is registered first, then the DAI will be cleaned up first and snd_dmaengine_pcm_unregister will be called next. snd_dmaengine_pcm_unregister will then lookup the dmaengine PCM component on the device, and if there's one unregister that component and release its dmaengine channels. That doesn't happen in practice though since the first call to snd_soc_unregister_component removed all the components, so we never get the chance to release the dmaengine channels. In order to fix this, instead of removing all the components for a given device, we can simply remove the component that was registered in the first place. We should have the same number of component registration than we have components, so it should work just fine. Signed-off-by: Maxime Ripard <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent c0dadd2 commit 58f3015

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

include/sound/soc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev,
444444
const struct snd_soc_component_driver *component_driver,
445445
struct snd_soc_dai_driver *dai_drv, int num_dai);
446446
void snd_soc_unregister_component(struct device *dev);
447+
void snd_soc_unregister_component_by_driver(struct device *dev,
448+
const struct snd_soc_component_driver *component_driver);
447449
struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
448450
const char *driver_name);
449451
struct snd_soc_component *snd_soc_lookup_component(struct device *dev,

sound/soc/soc-core.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2572,6 +2572,33 @@ int snd_soc_register_component(struct device *dev,
25722572
}
25732573
EXPORT_SYMBOL_GPL(snd_soc_register_component);
25742574

2575+
/**
2576+
* snd_soc_unregister_component_by_driver - Unregister component using a given driver
2577+
* from the ASoC core
2578+
*
2579+
* @dev: The device to unregister
2580+
* @component_driver: The component driver to unregister
2581+
*/
2582+
void snd_soc_unregister_component_by_driver(struct device *dev,
2583+
const struct snd_soc_component_driver *component_driver)
2584+
{
2585+
struct snd_soc_component *component;
2586+
2587+
if (!component_driver)
2588+
return;
2589+
2590+
mutex_lock(&client_mutex);
2591+
component = snd_soc_lookup_component_nolocked(dev, component_driver->name);
2592+
if (!component)
2593+
goto out;
2594+
2595+
snd_soc_del_component_unlocked(component);
2596+
2597+
out:
2598+
mutex_unlock(&client_mutex);
2599+
}
2600+
EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver);
2601+
25752602
/**
25762603
* snd_soc_unregister_component - Unregister all related component
25772604
* from the ASoC core

sound/soc/soc-devres.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
4848

4949
static void devm_component_release(struct device *dev, void *res)
5050
{
51-
snd_soc_unregister_component(*(struct device **)res);
51+
const struct snd_soc_component_driver **cmpnt_drv = res;
52+
53+
snd_soc_unregister_component_by_driver(dev, *cmpnt_drv);
5254
}
5355

5456
/**
@@ -65,7 +67,7 @@ int devm_snd_soc_register_component(struct device *dev,
6567
const struct snd_soc_component_driver *cmpnt_drv,
6668
struct snd_soc_dai_driver *dai_drv, int num_dai)
6769
{
68-
struct device **ptr;
70+
const struct snd_soc_component_driver **ptr;
6971
int ret;
7072

7173
ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
@@ -74,7 +76,7 @@ int devm_snd_soc_register_component(struct device *dev,
7476

7577
ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
7678
if (ret == 0) {
77-
*ptr = dev;
79+
*ptr = cmpnt_drv;
7880
devres_add(dev, ptr);
7981
} else {
8082
devres_free(ptr);

sound/soc/soc-generic-dmaengine-pcm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
478478

479479
pcm = soc_component_to_pcm(component);
480480

481-
snd_soc_unregister_component(dev);
481+
snd_soc_unregister_component_by_driver(dev, component->driver);
482482
dmaengine_pcm_release_chan(pcm);
483483
kfree(pcm);
484484
}

0 commit comments

Comments
 (0)