mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-03-07 12:12:07 +00:00
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 n_amixer = apcm->substream->runtime->channels, i = 0;
|
||||||
int device = apcm->substream->pcm->device;
|
int device = apcm->substream->pcm->device;
|
||||||
unsigned int pitch;
|
unsigned int pitch;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (NULL != apcm->src) {
|
if (NULL != apcm->src) {
|
||||||
/* Prepared pcm playback */
|
/* 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;
|
src = apcm->src;
|
||||||
for (i = 0; i < n_amixer; i++) {
|
for (i = 0; i < n_amixer; i++) {
|
||||||
amixer = apcm->amixers[i];
|
amixer = apcm->amixers[i];
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
amixer->ops->setup(amixer, &src->rsc,
|
amixer->ops->setup(amixer, &src->rsc,
|
||||||
INIT_VOL, atc->pcm[i+device*2]);
|
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);
|
src = src->ops->next_interleave(src);
|
||||||
if (NULL == src)
|
if (NULL == src)
|
||||||
src = apcm->src;
|
src = apcm->src;
|
||||||
@ -865,7 +864,6 @@ static int
|
|||||||
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
{
|
{
|
||||||
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
unsigned long flags;
|
|
||||||
unsigned int rate = apcm->substream->runtime->rate;
|
unsigned int rate = apcm->substream->runtime->rate;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
int err;
|
int err;
|
||||||
@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
dao->ops->get_spos(dao, &status);
|
dao->ops->get_spos(dao, &status);
|
||||||
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
|
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
|
||||||
status &= ((~IEC958_AES3_CON_FS) << 24);
|
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))
|
if ((rate != atc->pll_rate) && (32000 != rate))
|
||||||
err = atc_pll_init(atc, rate);
|
err = atc_pll_init(atc, rate);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||||||
struct dao *dao;
|
struct dao *dao;
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (NULL != apcm->src)
|
if (NULL != apcm->src)
|
||||||
return 0;
|
return 0;
|
||||||
@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
|||||||
src = apcm->src;
|
src = apcm->src;
|
||||||
}
|
}
|
||||||
/* Connect to SPDIFOO */
|
/* Connect to SPDIFOO */
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
amixer = apcm->amixers[0];
|
amixer = apcm->amixers[0];
|
||||||
dao->ops->set_left_input(dao, &amixer->rsc);
|
dao->ops->set_left_input(dao, &amixer->rsc);
|
||||||
amixer = apcm->amixers[1];
|
amixer = apcm->amixers[1];
|
||||||
dao->ops->set_right_input(dao, &amixer->rsc);
|
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);
|
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)
|
static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct dao_desc da_dsc = {0};
|
struct dao_desc da_dsc = {0};
|
||||||
struct dao *dao;
|
struct dao *dao;
|
||||||
int err;
|
int err;
|
||||||
@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
|||||||
struct rsc *rscs[2] = {NULL};
|
struct rsc *rscs[2] = {NULL};
|
||||||
unsigned int spos = 0;
|
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);
|
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
da_dsc.msr = state ? 1 : atc->msr;
|
da_dsc.msr = state ? 1 : atc->msr;
|
||||||
da_dsc.passthru = state ? 1 : 0;
|
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->set_spos(dao, spos);
|
||||||
dao->ops->commit_write(dao);
|
dao->ops->commit_write(dao);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
|||||||
atc->msr = msr;
|
atc->msr = msr;
|
||||||
atc->chip_type = chip_type;
|
atc->chip_type = chip_type;
|
||||||
|
|
||||||
spin_lock_init(&atc->atc_lock);
|
mutex_init(&atc->atc_mutex);
|
||||||
|
|
||||||
/* Find card model */
|
/* Find card model */
|
||||||
err = atc_identify_card(atc);
|
err = atc_identify_card(atc);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#define CTATC_H
|
#define CTATC_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/spinlock_types.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <sound/core.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);
|
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||||
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
|
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,
|
int (*pcm_playback_prepare)(struct ct_atc *atc,
|
||||||
struct ct_atc_pcm *apcm);
|
struct ct_atc_pcm *apcm);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user