Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 635c265f authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent a5990dc5
Loading
Loading
Loading
Loading
+9 −13
Original line number Original line Diff line number Diff line
@@ -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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -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);