[PATCH] fix AB-BA deadlock inversion at cs46xx_dsp_remove_scb

There is a code sequence where the locking is substream->self_group.lock
-> ins->scbs[index].lock

substream->self_group.lock is interrupt safe, and taken from irq context
as well (trace is snipped for brevity)

so what can happen is

cpu 0 cpu 1
user context user context

take ins->scbs[index].lock without disabling interrupts

get substream->self_group.lock (irqsafe)
try to get ins->scbs[index].lock (spins)

interrupt happens
try to get substream->self_group.lock (spins)

which is an obvious AB-BA deadlock

fix is to just take the lock with _irqsafe

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Jaroslav Kysela <perex@suse.cz>
Acked-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Arjan van de Ven and committed by Linus Torvalds c6482dde a46f9484

+3 -2
+3 -2
sound/pci/cs46xx/dsp_spos_scb_lib.c
··· 180 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) 181 { 182 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 183 184 /* check integrety */ 185 snd_assert ( (scb->index >= 0 && ··· 195 goto _end); 196 #endif 197 198 - spin_lock(&scb->lock); 199 _dsp_unlink_scb (chip,scb); 200 - spin_unlock(&scb->lock); 201 202 cs46xx_dsp_proc_free_scb_desc(scb); 203 snd_assert (scb->scb_symbol != NULL, return );
··· 180 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) 181 { 182 struct dsp_spos_instance * ins = chip->dsp_spos_instance; 183 + unsigned long flags; 184 185 /* check integrety */ 186 snd_assert ( (scb->index >= 0 && ··· 194 goto _end); 195 #endif 196 197 + spin_lock_irqsave(&scb->lock, flags); 198 _dsp_unlink_scb (chip,scb); 199 + spin_unlock_irqrestore(&scb->lock, flags); 200 201 cs46xx_dsp_proc_free_scb_desc(scb); 202 snd_assert (scb->scb_symbol != NULL, return );