Skip to content

Commit 4045daf

Browse files
ujfalusibroonie
authored andcommitted
ASoC: rt5682: Fix deadlock on resume
On resume from suspend the following chain of events can happen: A rt5682_resume() -> mod_delayed_work() for jack_detect_work B DAPM sequence starts ( DAPM is locked now) A1. rt5682_jack_detect_handler() scheduled - Takes both jdet_mutex and calibrate_mutex - Calls in to rt5682_headset_detect() which tries to take DAPM lock, it starts to wait for it as B path took it already. B1. DAPM sequence reaches the "HP Amp", rt5682_hp_event() tries to take the jdet_mutex, but it is locked in A1, so it waits. Deadlock. To solve the deadlock, drop the jdet_mutex, use the jack_detect_work to do the jack removal handling, move the dapm lock up one level to protect the most of the rt5682_jack_detect_handler(), but not the jack reporting as it might trigger a DAPM sequence. The rt5682_headset_detect() can be changed to static as well. Fixes: 8deb34a ("ASoC: rt5682: fix the wrong jack type detected") Signed-off-by: Peter Ujfalusi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 06feec6 commit 4045daf

File tree

3 files changed

+12
-29
lines changed

3 files changed

+12
-29
lines changed

sound/soc/codecs/rt5682-i2c.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,12 @@ static void rt5682_jd_check_handler(struct work_struct *work)
5959
struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv,
6060
jd_check_work.work);
6161

62-
if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL)
63-
& RT5682_JDH_RS_MASK) {
62+
if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK)
6463
/* jack out */
65-
rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0);
66-
67-
snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
68-
SND_JACK_HEADSET |
69-
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
70-
SND_JACK_BTN_2 | SND_JACK_BTN_3);
71-
} else {
64+
mod_delayed_work(system_power_efficient_wq,
65+
&rt5682->jack_detect_work, 0);
66+
else
7267
schedule_delayed_work(&rt5682->jd_check_work, 500);
73-
}
7468
}
7569

7670
static irqreturn_t rt5682_irq(int irq, void *data)
@@ -198,7 +192,6 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
198192
}
199193

200194
mutex_init(&rt5682->calibrate_mutex);
201-
mutex_init(&rt5682->jdet_mutex);
202195
rt5682_calibrate(rt5682);
203196

204197
rt5682_apply_patch_list(rt5682, &i2c->dev);

sound/soc/codecs/rt5682.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -922,15 +922,13 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component,
922922
*
923923
* Returns detect status.
924924
*/
925-
int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
925+
static int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
926926
{
927927
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
928928
struct snd_soc_dapm_context *dapm = &component->dapm;
929929
unsigned int val, count;
930930

931931
if (jack_insert) {
932-
snd_soc_dapm_mutex_lock(dapm);
933-
934932
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
935933
RT5682_PWR_VREF2 | RT5682_PWR_MB,
936934
RT5682_PWR_VREF2 | RT5682_PWR_MB);
@@ -981,8 +979,6 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
981979
snd_soc_component_update_bits(component, RT5682_MICBIAS_2,
982980
RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK,
983981
RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU);
984-
985-
snd_soc_dapm_mutex_unlock(dapm);
986982
} else {
987983
rt5682_enable_push_button_irq(component, false);
988984
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
@@ -1011,7 +1007,6 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
10111007
dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type);
10121008
return rt5682->jack_type;
10131009
}
1014-
EXPORT_SYMBOL_GPL(rt5682_headset_detect);
10151010

10161011
static int rt5682_set_jack_detect(struct snd_soc_component *component,
10171012
struct snd_soc_jack *hs_jack, void *data)
@@ -1094,6 +1089,7 @@ void rt5682_jack_detect_handler(struct work_struct *work)
10941089
{
10951090
struct rt5682_priv *rt5682 =
10961091
container_of(work, struct rt5682_priv, jack_detect_work.work);
1092+
struct snd_soc_dapm_context *dapm;
10971093
int val, btn_type;
10981094

10991095
while (!rt5682->component)
@@ -1102,7 +1098,9 @@ void rt5682_jack_detect_handler(struct work_struct *work)
11021098
while (!rt5682->component->card->instantiated)
11031099
usleep_range(10000, 15000);
11041100

1105-
mutex_lock(&rt5682->jdet_mutex);
1101+
dapm = snd_soc_component_get_dapm(rt5682->component);
1102+
1103+
snd_soc_dapm_mutex_lock(dapm);
11061104
mutex_lock(&rt5682->calibrate_mutex);
11071105

11081106
val = snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL)
@@ -1162,6 +1160,9 @@ void rt5682_jack_detect_handler(struct work_struct *work)
11621160
rt5682->irq_work_delay_time = 50;
11631161
}
11641162

1163+
mutex_unlock(&rt5682->calibrate_mutex);
1164+
snd_soc_dapm_mutex_unlock(dapm);
1165+
11651166
snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type,
11661167
SND_JACK_HEADSET |
11671168
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
@@ -1174,9 +1175,6 @@ void rt5682_jack_detect_handler(struct work_struct *work)
11741175
else
11751176
cancel_delayed_work_sync(&rt5682->jd_check_work);
11761177
}
1177-
1178-
mutex_unlock(&rt5682->calibrate_mutex);
1179-
mutex_unlock(&rt5682->jdet_mutex);
11801178
}
11811179
EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler);
11821180

@@ -1526,7 +1524,6 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w,
15261524
{
15271525
struct snd_soc_component *component =
15281526
snd_soc_dapm_to_component(w->dapm);
1529-
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
15301527

15311528
switch (event) {
15321529
case SND_SOC_DAPM_PRE_PMU:
@@ -1538,17 +1535,12 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w,
15381535
RT5682_DEPOP_1, 0x60, 0x60);
15391536
snd_soc_component_update_bits(component,
15401537
RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080);
1541-
1542-
mutex_lock(&rt5682->jdet_mutex);
1543-
15441538
snd_soc_component_update_bits(component, RT5682_HP_CTRL_2,
15451539
RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN,
15461540
RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN);
15471541
usleep_range(5000, 10000);
15481542
snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1,
15491543
RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L);
1550-
1551-
mutex_unlock(&rt5682->jdet_mutex);
15521544
break;
15531545

15541546
case SND_SOC_DAPM_POST_PMD:

sound/soc/codecs/rt5682.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,6 @@ struct rt5682_priv {
14631463

14641464
int jack_type;
14651465
int irq_work_delay_time;
1466-
struct mutex jdet_mutex;
14671466
};
14681467

14691468
extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES];
@@ -1473,7 +1472,6 @@ int rt5682_sel_asrc_clk_src(struct snd_soc_component *component,
14731472

14741473
void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev);
14751474

1476-
int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert);
14771475
void rt5682_jack_detect_handler(struct work_struct *work);
14781476

14791477
bool rt5682_volatile_register(struct device *dev, unsigned int reg);

0 commit comments

Comments
 (0)