mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
Merge branch 'topic/ctxfi' into for-linus
* topic/ctxfi: ALSA: ctxfi - Fix deadlock with xfi-timer ALSA: ctxfi - Replace atc lock to mutex
This commit is contained in:
commit
3d2aa66dda
3 changed files with 21 additions and 23 deletions
|
@ -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);
|
||||
|
|
|
@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer)
|
|||
*
|
||||
* call this inside the lock and irq disabled
|
||||
*/
|
||||
static int ct_xfitimer_reprogram(struct ct_timer *atimer)
|
||||
static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update)
|
||||
{
|
||||
struct ct_timer_instance *ti;
|
||||
unsigned int min_intr = (unsigned int)-1;
|
||||
|
@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer)
|
|||
ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
|
||||
rate - 1, rate);
|
||||
}
|
||||
if (ti->need_update && !can_update)
|
||||
min_intr = 0; /* pending to the next irq */
|
||||
if (ti->frag_count < min_intr)
|
||||
min_intr = ti->frag_count;
|
||||
}
|
||||
|
@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer)
|
|||
|
||||
spin_lock_irqsave(&atimer->list_lock, flags);
|
||||
list_for_each_entry(ti, &atimer->instance_head, instance_list) {
|
||||
if (ti->need_update) {
|
||||
if (ti->running && ti->need_update) {
|
||||
ti->need_update = 0;
|
||||
ti->apcm->interrupt(ti->apcm);
|
||||
}
|
||||
|
@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
|
|||
spin_lock_irqsave(&atimer->lock, flags);
|
||||
atimer->irq_handling = 1;
|
||||
do {
|
||||
update = ct_xfitimer_reprogram(atimer);
|
||||
update = ct_xfitimer_reprogram(atimer, 1);
|
||||
spin_unlock(&atimer->lock);
|
||||
if (update)
|
||||
ct_xfitimer_check_period(atimer);
|
||||
|
@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
|
|||
static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
|
||||
{
|
||||
ti->frag_count = ti->substream->runtime->period_size;
|
||||
ti->running = 0;
|
||||
ti->need_update = 0;
|
||||
}
|
||||
|
||||
|
@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
|
|||
static void ct_xfitimer_update(struct ct_timer *atimer)
|
||||
{
|
||||
unsigned long flags;
|
||||
int update;
|
||||
|
||||
spin_lock_irqsave(&atimer->lock, flags);
|
||||
if (atimer->irq_handling) {
|
||||
|
@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer)
|
|||
}
|
||||
|
||||
ct_xfitimer_irq_stop(atimer);
|
||||
update = ct_xfitimer_reprogram(atimer);
|
||||
ct_xfitimer_reprogram(atimer, 0);
|
||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||
if (update)
|
||||
ct_xfitimer_check_period(atimer);
|
||||
}
|
||||
|
||||
static void ct_xfitimer_start(struct ct_timer_instance *ti)
|
||||
|
@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti)
|
|||
spin_lock_irqsave(&atimer->lock, flags);
|
||||
if (list_empty(&ti->running_list))
|
||||
atimer->wc = ct_xfitimer_get_wc(atimer);
|
||||
ti->running = 1;
|
||||
ti->need_update = 0;
|
||||
list_add(&ti->running_list, &atimer->running_head);
|
||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||
ct_xfitimer_update(atimer);
|
||||
|
@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti)
|
|||
|
||||
spin_lock_irqsave(&atimer->lock, flags);
|
||||
list_del_init(&ti->running_list);
|
||||
ti->need_update = 0;
|
||||
ti->running = 0;
|
||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||
ct_xfitimer_update(atimer);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue