Skip to content

Commit e64bb3e

Browse files
marcanjannau
authored andcommitted
macaudio: Use an explicit mutex for the speaker volume lock
Otherwise we can end up recursively locking the controls lock in the start/stop path, since it can be called from a control change. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent d4b119b commit e64bb3e

1 file changed

Lines changed: 28 additions & 10 deletions

File tree

sound/soc/apple/macaudio.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct macaudio_snd_data {
9696
int speaker_sample_rate;
9797
struct snd_kcontrol *speaker_sample_rate_kctl;
9898

99+
struct mutex volume_lock_mutex;
99100
bool speaker_volume_unlocked;
100101
bool speaker_volume_was_locked;
101102
struct snd_kcontrol *speaker_lock_kctl;
@@ -284,10 +285,12 @@ static void macaudio_vlimit_update(struct macaudio_snd_data *ma)
284285

285286
static void macaudio_vlimit_enable_timeout(struct macaudio_snd_data *ma)
286287
{
287-
if (ma->speaker_lock_timeout_enabled)
288-
return;
288+
mutex_lock(&ma->volume_lock_mutex);
289289

290-
down_write(&ma->card.snd_card->controls_rwsem);
290+
if (ma->speaker_lock_timeout_enabled) {
291+
mutex_unlock(&ma->volume_lock_mutex);
292+
return;
293+
}
291294

292295
if (ma->speaker_lock_remain > 0) {
293296
ma->speaker_lock_timeout = ktime_add(ktime_get(), ma->speaker_lock_remain);
@@ -298,18 +301,22 @@ static void macaudio_vlimit_enable_timeout(struct macaudio_snd_data *ma)
298301

299302
macaudio_vlimit_update(ma);
300303

301-
up_write(&ma->card.snd_card->controls_rwsem);
302304
ma->speaker_lock_timeout_enabled = true;
305+
mutex_unlock(&ma->volume_lock_mutex);
303306
}
304307

305308
static void macaudio_vlimit_disable_timeout(struct macaudio_snd_data *ma)
306309
{
307-
ktime_t now = ktime_get();
310+
ktime_t now;
311+
312+
mutex_lock(&ma->volume_lock_mutex);
308313

309-
if (!ma->speaker_lock_timeout_enabled)
314+
if (!ma->speaker_lock_timeout_enabled) {
315+
mutex_unlock(&ma->volume_lock_mutex);
310316
return;
317+
}
311318

312-
down_write(&ma->card.snd_card->controls_rwsem);
319+
now = ktime_get();
313320

314321
cancel_delayed_work(&ma->lock_timeout_work);
315322

@@ -323,21 +330,22 @@ static void macaudio_vlimit_disable_timeout(struct macaudio_snd_data *ma)
323330

324331
macaudio_vlimit_update(ma);
325332

326-
up_write(&ma->card.snd_card->controls_rwsem);
327333
ma->speaker_lock_timeout_enabled = false;
334+
335+
mutex_unlock(&ma->volume_lock_mutex);
328336
}
329337

330338
static void macaudio_vlimit_timeout_work(struct work_struct *wrk)
331339
{
332340
struct macaudio_snd_data *ma = container_of(to_delayed_work(wrk),
333341
struct macaudio_snd_data, lock_timeout_work);
334342

335-
down_write(&ma->card.snd_card->controls_rwsem);
343+
mutex_lock(&ma->volume_lock_mutex);
336344

337345
ma->speaker_lock_remain = 0;
338346
macaudio_vlimit_update(ma);
339347

340-
up_write(&ma->card.snd_card->controls_rwsem);
348+
mutex_unlock(&ma->volume_lock_mutex);
341349
}
342350

343351
static void macaudio_vlimit_update_work(struct work_struct *wrk)
@@ -1095,7 +1103,9 @@ static int macaudio_late_probe(struct snd_soc_card *card)
10951103
ma->speaker_sample_rate_kctl = snd_soc_card_get_kcontrol(card, "Speaker Sample Rate");
10961104
ma->speaker_lock_kctl = snd_soc_card_get_kcontrol(card, "Speaker Volume Unlock");
10971105

1106+
mutex_lock(&ma->volume_lock_mutex);
10981107
macaudio_vlimit_unlock(ma, false);
1108+
mutex_unlock(&ma->volume_lock_mutex);
10991109

11001110
return 0;
11011111
}
@@ -1336,6 +1346,8 @@ static int macaudio_slk_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
13361346
return -ETIMEDOUT;
13371347
}
13381348

1349+
mutex_lock(&ma->volume_lock_mutex);
1350+
13391351
cancel_delayed_work(&ma->lock_timeout_work);
13401352

13411353
ma->speaker_lock_remain = ms_to_ktime(SPEAKER_LOCK_TIMEOUT);
@@ -1348,6 +1360,8 @@ static int macaudio_slk_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
13481360
schedule_delayed_work(&ma->lock_timeout_work, usecs_to_jiffies(ktime_to_us(ma->speaker_lock_remain)));
13491361
}
13501362

1363+
mutex_unlock(&ma->volume_lock_mutex);
1364+
13511365
return 0;
13521366
}
13531367

@@ -1366,6 +1380,7 @@ static int macaudio_slk_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_file
13661380
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
13671381
struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(card);
13681382

1383+
mutex_lock(&ma->volume_lock_mutex);
13691384
ma->speaker_lock_owner = owner;
13701385
macaudio_vlimit_update(ma);
13711386

@@ -1377,6 +1392,8 @@ static int macaudio_slk_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_file
13771392
*/
13781393
ma->speaker_volume_was_locked = false;
13791394

1395+
mutex_unlock(&ma->volume_lock_mutex);
1396+
13801397
return 0;
13811398
}
13821399

@@ -1469,6 +1486,7 @@ static int macaudio_snd_platform_probe(struct platform_device *pdev)
14691486
card = &data->card;
14701487
snd_soc_card_set_drvdata(card, data);
14711488
dev_set_drvdata(&pdev->dev, data);
1489+
mutex_init(&data->volume_lock_mutex);
14721490

14731491
card->owner = THIS_MODULE;
14741492
card->driver_name = "macaudio";

0 commit comments

Comments
 (0)