mirror of https://gitee.com/openkylin/linux.git
ALSA: ctxfi - Replace atc lock to mutex
The spinlock in atc can cause a sleep in lock: Kernel failure message 1: BUG: sleeping function called from invalid context at mm/slub.c:1599 in_atomic(): 0, irqs_disabled(): 1, pid: 2537, name: gstreamer-prope Pid: 2537, comm: gstreamer-prope Tainted: P 2.6.29.4-167.fc11.x86_64 #1 Call Trace: [<ffffffff8103ff0f>] __might_sleep+0x10b/0x110 [<ffffffff810cd734>] __kmalloc+0x73/0x130 [<ffffffffa0b4b142>] ? daio_rsc_init+0xaa/0x125 [snd_ctxfi] [<ffffffffa0b4b212>] dao_rsc_init+0x55/0x1c0 [snd_ctxfi] [<ffffffffa0b4b3d2>] dao_rsc_reinit+0x55/0x5d [snd_ctxfi] [<ffffffff813abd6c>] ? _spin_lock_irqsave+0x32/0x3b [<ffffffffa0b454fe>] atc_spdif_out_passthru+0x92/0x136 [snd_ctxfi] ... Since the lock path is no critical path, it can be gracefully replaced with a mutex. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
a5990dc5b9
commit
635c265f32
|
@ -259,7 +259,6 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
int n_amixer = apcm->substream->runtime->channels, i = 0;
|
||||
int device = apcm->substream->pcm->device;
|
||||
unsigned int pitch;
|
||||
unsigned long flags;
|
||||
|
||||
if (NULL != apcm->src) {
|
||||
/* Prepared pcm playback */
|
||||
|
@ -311,10 +310,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
src = apcm->src;
|
||||
for (i = 0; i < n_amixer; i++) {
|
||||
amixer = apcm->amixers[i];
|
||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
||||
mutex_lock(&atc->atc_mutex);
|
||||
amixer->ops->setup(amixer, &src->rsc,
|
||||
INIT_VOL, atc->pcm[i+device*2]);
|
||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
||||
mutex_unlock(&atc->atc_mutex);
|
||||
src = src->ops->next_interleave(src);
|
||||
if (NULL == src)
|
||||
src = apcm->src;
|
||||
|
@ -865,7 +864,6 @@ static int
|
|||
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||
{
|
||||
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||
unsigned long flags;
|
||||
unsigned int rate = apcm->substream->runtime->rate;
|
||||
unsigned int status;
|
||||
int err;
|
||||
|
@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
||||
mutex_lock(&atc->atc_mutex);
|
||||
dao->ops->get_spos(dao, &status);
|
||||
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
|
||||
status &= ((~IEC958_AES3_CON_FS) << 24);
|
||||
|
@ -895,7 +893,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
}
|
||||
if ((rate != atc->pll_rate) && (32000 != rate))
|
||||
err = atc_pll_init(atc, rate);
|
||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
||||
mutex_unlock(&atc->atc_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
struct dao *dao;
|
||||
int err;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (NULL != apcm->src)
|
||||
return 0;
|
||||
|
@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||
src = apcm->src;
|
||||
}
|
||||
/* Connect to SPDIFOO */
|
||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
||||
mutex_lock(&atc->atc_mutex);
|
||||
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||
amixer = apcm->amixers[0];
|
||||
dao->ops->set_left_input(dao, &amixer->rsc);
|
||||
amixer = apcm->amixers[1];
|
||||
dao->ops->set_right_input(dao, &amixer->rsc);
|
||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
||||
mutex_unlock(&atc->atc_mutex);
|
||||
|
||||
ct_timer_prepare(apcm->timer);
|
||||
|
||||
|
@ -1088,7 +1085,6 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)
|
|||
|
||||
static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct dao_desc da_dsc = {0};
|
||||
struct dao *dao;
|
||||
int err;
|
||||
|
@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
|||
struct rsc *rscs[2] = {NULL};
|
||||
unsigned int spos = 0;
|
||||
|
||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
||||
mutex_lock(&atc->atc_mutex);
|
||||
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||
da_dsc.msr = state ? 1 : atc->msr;
|
||||
da_dsc.passthru = state ? 1 : 0;
|
||||
|
@ -1114,7 +1110,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
|||
}
|
||||
dao->ops->set_spos(dao, spos);
|
||||
dao->ops->commit_write(dao);
|
||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
||||
mutex_unlock(&atc->atc_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
|||
atc->msr = msr;
|
||||
atc->chip_type = chip_type;
|
||||
|
||||
spin_lock_init(&atc->atc_lock);
|
||||
mutex_init(&atc->atc_mutex);
|
||||
|
||||
/* Find card model */
|
||||
err = atc_identify_card(atc);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define CTATC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/timer.h>
|
||||
#include <sound/core.h>
|
||||
|
@ -90,7 +90,7 @@ struct ct_atc {
|
|||
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
|
||||
|
||||
spinlock_t atc_lock;
|
||||
struct mutex atc_mutex;
|
||||
|
||||
int (*pcm_playback_prepare)(struct ct_atc *atc,
|
||||
struct ct_atc_pcm *apcm);
|
||||
|
|
Loading…
Reference in New Issue