Message ID | 20241024215612.92147-1-hdegoede@redhat.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 032532f91a1d06d0750f16c49a9698ef5374a68f |
Headers | show |
Series | ASoC: codecs: rt5640: Always disable IRQs from rt5640_cancel_work() | expand |
On Thu, 24 Oct 2024 23:56:12 +0200, Hans de Goede wrote: > 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] > > [...] Applied to https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Thanks! [1/1] ASoC: codecs: rt5640: Always disable IRQs from rt5640_cancel_work() commit: 032532f91a1d06d0750f16c49a9698ef5374a68f All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 16f3425a3e35..855139348edb 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2419,10 +2419,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data) return IRQ_HANDLED; } -static void rt5640_cancel_work(void *data) +static void rt5640_disable_irq_and_cancel_work(void *data) { struct rt5640_priv *rt5640 = data; + if (rt5640->jd_gpio_irq_requested) { + free_irq(rt5640->jd_gpio_irq, rt5640); + rt5640->jd_gpio_irq_requested = false; + } + + if (rt5640->irq_requested) { + free_irq(rt5640->irq, rt5640); + rt5640->irq_requested = false; + } + cancel_delayed_work_sync(&rt5640->jack_work); cancel_delayed_work_sync(&rt5640->bp_work); } @@ -2463,13 +2473,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component) if (!rt5640->jack) return; - if (rt5640->jd_gpio_irq_requested) - free_irq(rt5640->jd_gpio_irq, rt5640); - - if (rt5640->irq_requested) - free_irq(rt5640->irq, rt5640); - - rt5640_cancel_work(rt5640); + rt5640_disable_irq_and_cancel_work(rt5640); if (rt5640->jack->status & SND_JACK_MICROPHONE) { rt5640_disable_micbias1_ovcd_irq(component); @@ -2477,8 +2481,6 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component) snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0); } - rt5640->jd_gpio_irq_requested = false; - rt5640->irq_requested = false; rt5640->jd_gpio = NULL; rt5640->jack = NULL; } @@ -2798,7 +2800,8 @@ static int rt5640_suspend(struct snd_soc_component *component) if (rt5640->jack) { /* disable jack interrupts during system suspend */ disable_irq(rt5640->irq); - rt5640_cancel_work(rt5640); + cancel_delayed_work_sync(&rt5640->jack_work); + cancel_delayed_work_sync(&rt5640->bp_work); } snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); @@ -3032,7 +3035,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c) INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work); /* Make sure work is stopped on probe-error / remove */ - ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640); + ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640); if (ret) return ret;
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 <hdegoede@redhat.com> --- sound/soc/codecs/rt5640.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)