Commit 11391100 authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown

ASoC: dapm: Add locking to snd_soc_dapm_xxxx_pin functions

The snd_soc_dapm_xxxx_pin all require the dapm_mutex to be held when
they are called as they edit the dirty list, however very few of the
callers do so.

This patch adds unlocked versions of all the functions replacing the
existing implementations with one that holds the lock internally. We
also fix up the places where the lock was actually held on the caller
side.
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
Cc: stable@vger.kernel.org
parent c4204960
...@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) ...@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
struct snd_soc_dapm_context *dapm = arizona->dapm; struct snd_soc_dapm_context *dapm = arizona->dapm;
int ret; int ret;
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_force_enable_pin(dapm, widget); ret = snd_soc_dapm_force_enable_pin(dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, "Failed to enable %s: %d\n", dev_warn(arizona->dev, "Failed to enable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
if (!arizona->pdata.micd_force_micbias) { if (!arizona->pdata.micd_force_micbias) {
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_disable_pin(arizona->dapm, widget); ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, "Failed to disable %s: %d\n", dev_warn(arizona->dev, "Failed to disable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
} }
} }
...@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info) ...@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
ARIZONA_MICD_ENA, 0, ARIZONA_MICD_ENA, 0,
&change); &change);
mutex_lock(&dapm->card->dapm_mutex);
ret = snd_soc_dapm_disable_pin(dapm, widget); ret = snd_soc_dapm_disable_pin(dapm, widget);
if (ret != 0) if (ret != 0)
dev_warn(arizona->dev, dev_warn(arizona->dev,
"Failed to disable %s: %d\n", "Failed to disable %s: %d\n",
widget, ret); widget, ret);
mutex_unlock(&dapm->card->dapm_mutex);
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
if (info->micd_reva) { if (info->micd_reva) {
......
...@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *work)
struct arizona_haptics, struct arizona_haptics,
work); work);
struct arizona *arizona = haptics->arizona; struct arizona *arizona = haptics->arizona;
struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
int ret; int ret;
if (!haptics->arizona->dapm) { if (!haptics->arizona->dapm) {
...@@ -67,18 +66,13 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -67,18 +66,13 @@ static void arizona_haptics_work(struct work_struct *work)
return; return;
} }
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
mutex_unlock(dapm_mutex);
ret = snd_soc_dapm_sync(arizona->dapm); ret = snd_soc_dapm_sync(arizona->dapm);
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n", dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
...@@ -87,18 +81,13 @@ static void arizona_haptics_work(struct work_struct *work) ...@@ -87,18 +81,13 @@ static void arizona_haptics_work(struct work_struct *work)
} }
} else { } else {
/* This disable sequence will be a noop if already enabled */ /* This disable sequence will be a noop if already enabled */
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
ret); ret);
mutex_unlock(dapm_mutex);
return; return;
} }
mutex_unlock(dapm_mutex);
ret = snd_soc_dapm_sync(arizona->dapm); ret = snd_soc_dapm_sync(arizona->dapm);
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to sync DAPM: %d\n", dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
...@@ -152,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data, ...@@ -152,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
static void arizona_haptics_close(struct input_dev *input) static void arizona_haptics_close(struct input_dev *input)
{ {
struct arizona_haptics *haptics = input_get_drvdata(input); struct arizona_haptics *haptics = input_get_drvdata(input);
struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
cancel_work_sync(&haptics->work); cancel_work_sync(&haptics->work);
mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (haptics->arizona->dapm) if (haptics->arizona->dapm)
snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
mutex_unlock(dapm_mutex);
} }
static int arizona_haptics_probe(struct platform_device *pdev) static int arizona_haptics_probe(struct platform_device *pdev)
......
...@@ -449,14 +449,22 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, ...@@ -449,14 +449,22 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
/* dapm audio pin control and status */ /* dapm audio pin control and status */
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin);
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
const char *pin); const char *pin);
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
......
...@@ -3210,15 +3210,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, ...@@ -3210,15 +3210,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value; const char *pin = (const char *)kcontrol->private_value;
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (ucontrol->value.integer.value[0]) if (ucontrol->value.integer.value[0])
snd_soc_dapm_enable_pin(&card->dapm, pin); snd_soc_dapm_enable_pin(&card->dapm, pin);
else else
snd_soc_dapm_disable_pin(&card->dapm, pin); snd_soc_dapm_disable_pin(&card->dapm, pin);
mutex_unlock(&card->dapm_mutex);
snd_soc_dapm_sync(&card->dapm); snd_soc_dapm_sync(&card->dapm);
return 0; return 0;
} }
...@@ -3766,6 +3762,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, ...@@ -3766,6 +3762,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
mutex_unlock(&card->dapm_mutex); mutex_unlock(&card->dapm_mutex);
} }
/**
* snd_soc_dapm_enable_pin_unlocked - enable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Enables input/output pin and its parents or children widgets iff there is
* a valid audio route and active audio stream.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 1);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
/** /**
* snd_soc_dapm_enable_pin - enable pin. * snd_soc_dapm_enable_pin - enable pin.
* @dapm: DAPM context * @dapm: DAPM context
...@@ -3773,17 +3789,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, ...@@ -3773,17 +3789,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
* *
* Enables input/output pin and its parents or children widgets iff there is * Enables input/output pin and its parents or children widgets iff there is
* a valid audio route and active audio stream. * a valid audio route and active audio stream.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 1); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 1);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
/** /**
* snd_soc_dapm_force_enable_pin - force a pin to be enabled * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
* @dapm: DAPM context * @dapm: DAPM context
* @pin: pin name * @pin: pin name
* *
...@@ -3791,10 +3816,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); ...@@ -3791,10 +3816,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
* intended for use with microphone bias supplies used in microphone * intended for use with microphone bias supplies used in microphone
* jack detection. * jack detection.
* *
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin) const char *pin)
{ {
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
...@@ -3811,24 +3838,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, ...@@ -3811,24 +3838,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
/**
* snd_soc_dapm_force_enable_pin - force a pin to be enabled
* @dapm: DAPM context
* @pin: pin name
*
* Enables input/output pin regardless of any other state. This is
* intended for use with microphone bias supplies used in microphone
* jack detection.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
const char *pin)
{
int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
/**
* snd_soc_dapm_disable_pin_unlocked - disable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Disables input/output pin and its parents or children widgets.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
/** /**
* snd_soc_dapm_disable_pin - disable pin. * snd_soc_dapm_disable_pin - disable pin.
* @dapm: DAPM context * @dapm: DAPM context
* @pin: pin name * @pin: pin name
* *
* Disables input/output pin and its parents or children widgets. * Disables input/output pin and its parents or children widgets.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching. * do any widget power switching.
*/ */
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
const char *pin) const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 0); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 0);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
/**
* snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
* @dapm: DAPM context
* @pin: pin name
*
* Marks the specified pin as being not connected, disabling it along
* any parent or child widgets. At present this is identical to
* snd_soc_dapm_disable_pin() but in future it will be extended to do
* additional things such as disabling controls which only affect
* paths through the pin.
*
* Requires external locking.
*
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
* do any widget power switching.
*/
int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
const char *pin)
{
return snd_soc_dapm_set_pin(dapm, pin, 0);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
/** /**
* snd_soc_dapm_nc_pin - permanently disable pin. * snd_soc_dapm_nc_pin - permanently disable pin.
* @dapm: DAPM context * @dapm: DAPM context
...@@ -3845,7 +3950,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); ...@@ -3845,7 +3950,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
*/ */
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
{ {
return snd_soc_dapm_set_pin(dapm, pin, 0); int ret;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = snd_soc_dapm_set_pin(dapm, pin, 0);
mutex_unlock(&dapm->card->dapm_mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment