From d643ad0642e3b00665cb1f339694a38521488eca Mon Sep 17 00:00:00 2001 From: "Dharageswari.R" Date: Thu, 6 Oct 2011 16:18:36 +0100 Subject: [PATCH] ASoC: mfld_machine: prevent the deadlock in interrupt handler of machine driver This patches uses spin_lock_irqsave to store and handle the jack and over current interrupts.There by it prevents the deadlock issue caused due to spin_lock in the threaded interrupt handler. Change-Id: I693c153d0a1f39d02d9d114a8ae0c99d19badebe Signed-off-by: Dharageswari.R --- sound/soc/mid-x86/mfld_machine.c | 67 ++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 43 deletions(-) diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 175d62c..028e24e 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c @@ -388,63 +388,44 @@ static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) return IRQ_WAKE_THREAD; } -static void jack_int_handler(struct mfld_mc_private *mc_drv_ctx) -{ - u8 status; - - spin_lock(&mc_drv_ctx->lock); - if (mc_drv_ctx->jack_interrupt_status) { - status = mc_drv_ctx->jack_interrupt_status; - mc_drv_ctx->jack_interrupt_status = 0; - spin_unlock(&mc_drv_ctx->lock); - pr_debug("jack_status:%x\n", status); - mfld_jack_check(status); - return; - } - spin_unlock(&mc_drv_ctx->lock); - return; -} - -static void oc_int_handler(struct mfld_mc_private *mc_drv_ctx) -{ - u8 status; - - spin_lock(&mc_drv_ctx->lock); - if (mc_drv_ctx->oc_interrupt_status) { - status = mc_drv_ctx->oc_interrupt_status; - mc_drv_ctx->oc_interrupt_status = 0; - spin_unlock(&mc_drv_ctx->lock); - pr_debug("oc_current\n"); - sn95031_oc_handler(mc_drv_ctx->codec, status); - return; - } - spin_unlock(&mc_drv_ctx->lock); - return; -} - static irqreturn_t snd_mfld_codec_intr_detection(int irq, void *data) { struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; + unsigned long flags; + u8 oc_int_value = 0, jack_int_value = 0; if (mfld_jack.codec == NULL) { pr_debug("codec NULL returning.."); - spin_lock(&mc_drv_ctx->lock); + spin_lock_irqsave(&mc_drv_ctx->lock, flags); mc_drv_ctx->jack_interrupt_status = 0; mc_drv_ctx->oc_interrupt_status = 0; - spin_unlock(&mc_drv_ctx->lock); - return IRQ_HANDLED; + spin_unlock_irqrestore(&mc_drv_ctx->lock, flags); + goto ret; } - spin_lock(&mc_drv_ctx->lock); + spin_lock_irqsave(&mc_drv_ctx->lock, flags); if (!((mc_drv_ctx->jack_interrupt_status) || (mc_drv_ctx->oc_interrupt_status))) { - spin_unlock(&mc_drv_ctx->lock); + spin_unlock_irqrestore(&mc_drv_ctx->lock, flags); pr_err("OC and Jack Intr with status 0, return....\n"); goto ret; } - spin_unlock(&mc_drv_ctx->lock); - mc_drv_ctx->codec = mfld_jack.codec; - oc_int_handler(mc_drv_ctx); - jack_int_handler(mc_drv_ctx); + if (mc_drv_ctx->oc_interrupt_status) { + oc_int_value = mc_drv_ctx->oc_interrupt_status; + mc_drv_ctx->oc_interrupt_status = 0; + } + if (mc_drv_ctx->jack_interrupt_status) { + jack_int_value = mc_drv_ctx->jack_interrupt_status; + mc_drv_ctx->jack_interrupt_status = 0; + } + spin_unlock_irqrestore(&mc_drv_ctx->lock, flags); + + if (oc_int_value) { + mc_drv_ctx->codec = mfld_jack.codec; + sn95031_oc_handler(mc_drv_ctx->codec, oc_int_value); + } + if (jack_int_value) + mfld_jack_check(jack_int_value); + ret: return IRQ_HANDLED; } -- 2.7.4