Skip to content

Commit 032532f

Browse files
jwrdegoedebroonie
authored andcommitted
ASoC: codecs: rt5640: Always disable IRQs from rt5640_cancel_work()
Disable IRQs from rt5640_cancel_work(), this fixes a crash caused by the IRQ never getting freed when the driver is unbound from the i2c_client with jack-detection active: [ 193.138780] rt5640 i2c-rt5640: ASoC: unknown pin LDO2 [ 193.138830] rt5640 i2c-rt5640: ASoC: unknown pin MICBIAS1 [ 193.671218] BUG: kernel NULL pointer dereference, address: 0000000000000078 [ 193.671239] #PF: supervisor read access in kernel mode [ 193.671248] #PF: error_code(0x0000) - not-present page ... [ 193.671531] ? asm_exc_page_fault+0x22/0x30 [ 193.671551] ? rt5640_jack_inserted+0x10/0x80 [snd_soc_rt5640] [ 193.671574] rt5640_detect_headset+0x93/0x130 [snd_soc_rt5640] [ 193.671596] rt5640_jack_work+0x93/0x355 [snd_soc_rt5640] Signed-off-by: Hans de Goede <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent db7e59e commit 032532f

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

sound/soc/codecs/rt5640.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,10 +2419,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
24192419
return IRQ_HANDLED;
24202420
}
24212421

2422-
static void rt5640_cancel_work(void *data)
2422+
static void rt5640_disable_irq_and_cancel_work(void *data)
24232423
{
24242424
struct rt5640_priv *rt5640 = data;
24252425

2426+
if (rt5640->jd_gpio_irq_requested) {
2427+
free_irq(rt5640->jd_gpio_irq, rt5640);
2428+
rt5640->jd_gpio_irq_requested = false;
2429+
}
2430+
2431+
if (rt5640->irq_requested) {
2432+
free_irq(rt5640->irq, rt5640);
2433+
rt5640->irq_requested = false;
2434+
}
2435+
24262436
cancel_delayed_work_sync(&rt5640->jack_work);
24272437
cancel_delayed_work_sync(&rt5640->bp_work);
24282438
}
@@ -2463,22 +2473,14 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
24632473
if (!rt5640->jack)
24642474
return;
24652475

2466-
if (rt5640->jd_gpio_irq_requested)
2467-
free_irq(rt5640->jd_gpio_irq, rt5640);
2468-
2469-
if (rt5640->irq_requested)
2470-
free_irq(rt5640->irq, rt5640);
2471-
2472-
rt5640_cancel_work(rt5640);
2476+
rt5640_disable_irq_and_cancel_work(rt5640);
24732477

24742478
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
24752479
rt5640_disable_micbias1_ovcd_irq(component);
24762480
rt5640_disable_micbias1_for_ovcd(component);
24772481
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
24782482
}
24792483

2480-
rt5640->jd_gpio_irq_requested = false;
2481-
rt5640->irq_requested = false;
24822484
rt5640->jd_gpio = NULL;
24832485
rt5640->jack = NULL;
24842486
}
@@ -2798,7 +2800,8 @@ static int rt5640_suspend(struct snd_soc_component *component)
27982800
if (rt5640->jack) {
27992801
/* disable jack interrupts during system suspend */
28002802
disable_irq(rt5640->irq);
2801-
rt5640_cancel_work(rt5640);
2803+
cancel_delayed_work_sync(&rt5640->jack_work);
2804+
cancel_delayed_work_sync(&rt5640->bp_work);
28022805
}
28032806

28042807
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
@@ -3032,7 +3035,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c)
30323035
INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work);
30333036

30343037
/* Make sure work is stopped on probe-error / remove */
3035-
ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640);
3038+
ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640);
30363039
if (ret)
30373040
return ret;
30383041

0 commit comments

Comments
 (0)