Merge branch 'topic/ctxfi' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Tue, 16 Jun 2009 15:38:40 +0000 (17:38 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 16 Jun 2009 15:38:40 +0000 (17:38 +0200)
* topic/ctxfi:
  ALSA: ctxfi - Fix deadlock with xfi-timer
  ALSA: ctxfi - Replace atc lock to mutex

sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctatc.h
sound/pci/ctxfi/cttimer.c

index 80fb2ba..b0adc80 100644 (file)
@@ -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);
index a033472..9fe620e 100644 (file)
@@ -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);
index 779c6c3..93b0aed 100644 (file)
@@ -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);
 }