diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-06-16 11:38:40 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-06-16 11:38:40 -0400 |
commit | 3d2aa66ddaa3008ae2c71bca07eb5e8b08170c4a (patch) | |
tree | 4d9bfc4017f038a7f94358c4061afcb264ba6d08 /sound | |
parent | 21ce3cd63365b0d07794adeb4325944bfa86fb4e (diff) | |
parent | 8dca419721d188bfee5f19fad45275856c619a5c (diff) |
Merge branch 'topic/ctxfi' into for-linus
* topic/ctxfi:
ALSA: ctxfi - Fix deadlock with xfi-timer
ALSA: ctxfi - Replace atc lock to mutex
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/ctxfi/ctatc.c | 22 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctatc.h | 4 | ||||
-rw-r--r-- | sound/pci/ctxfi/cttimer.c | 18 |
3 files changed, 21 insertions, 23 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 80fb2baed7a7..b0adc8094009 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -259,7 +259,6 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
259 | int n_amixer = apcm->substream->runtime->channels, i = 0; | 259 | int n_amixer = apcm->substream->runtime->channels, i = 0; |
260 | int device = apcm->substream->pcm->device; | 260 | int device = apcm->substream->pcm->device; |
261 | unsigned int pitch; | 261 | unsigned int pitch; |
262 | unsigned long flags; | ||
263 | 262 | ||
264 | if (NULL != apcm->src) { | 263 | if (NULL != apcm->src) { |
265 | /* Prepared pcm playback */ | 264 | /* Prepared pcm playback */ |
@@ -311,10 +310,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
311 | src = apcm->src; | 310 | src = apcm->src; |
312 | for (i = 0; i < n_amixer; i++) { | 311 | for (i = 0; i < n_amixer; i++) { |
313 | amixer = apcm->amixers[i]; | 312 | amixer = apcm->amixers[i]; |
314 | spin_lock_irqsave(&atc->atc_lock, flags); | 313 | mutex_lock(&atc->atc_mutex); |
315 | amixer->ops->setup(amixer, &src->rsc, | 314 | amixer->ops->setup(amixer, &src->rsc, |
316 | INIT_VOL, atc->pcm[i+device*2]); | 315 | INIT_VOL, atc->pcm[i+device*2]); |
317 | spin_unlock_irqrestore(&atc->atc_lock, flags); | 316 | mutex_unlock(&atc->atc_mutex); |
318 | src = src->ops->next_interleave(src); | 317 | src = src->ops->next_interleave(src); |
319 | if (NULL == src) | 318 | if (NULL == src) |
320 | src = apcm->src; | 319 | src = apcm->src; |
@@ -865,7 +864,6 @@ static int | |||
865 | spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) | 864 | spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) |
866 | { | 865 | { |
867 | struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); | 866 | struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); |
868 | unsigned long flags; | ||
869 | unsigned int rate = apcm->substream->runtime->rate; | 867 | unsigned int rate = apcm->substream->runtime->rate; |
870 | unsigned int status; | 868 | unsigned int status; |
871 | int err; | 869 | int err; |
@@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
885 | return -ENOENT; | 883 | return -ENOENT; |
886 | } | 884 | } |
887 | 885 | ||
888 | spin_lock_irqsave(&atc->atc_lock, flags); | 886 | mutex_lock(&atc->atc_mutex); |
889 | dao->ops->get_spos(dao, &status); | 887 | dao->ops->get_spos(dao, &status); |
890 | if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { | 888 | if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { |
891 | status &= ((~IEC958_AES3_CON_FS) << 24); | 889 | status &= ((~IEC958_AES3_CON_FS) << 24); |
@@ -895,7 +893,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
895 | } | 893 | } |
896 | if ((rate != atc->pll_rate) && (32000 != rate)) | 894 | if ((rate != atc->pll_rate) && (32000 != rate)) |
897 | err = atc_pll_init(atc, rate); | 895 | err = atc_pll_init(atc, rate); |
898 | spin_unlock_irqrestore(&atc->atc_lock, flags); | 896 | mutex_unlock(&atc->atc_mutex); |
899 | 897 | ||
900 | return err; | 898 | return err; |
901 | } | 899 | } |
@@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
908 | struct dao *dao; | 906 | struct dao *dao; |
909 | int err; | 907 | int err; |
910 | int i; | 908 | int i; |
911 | unsigned long flags; | ||
912 | 909 | ||
913 | if (NULL != apcm->src) | 910 | if (NULL != apcm->src) |
914 | return 0; | 911 | return 0; |
@@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
934 | src = apcm->src; | 931 | src = apcm->src; |
935 | } | 932 | } |
936 | /* Connect to SPDIFOO */ | 933 | /* Connect to SPDIFOO */ |
937 | spin_lock_irqsave(&atc->atc_lock, flags); | 934 | mutex_lock(&atc->atc_mutex); |
938 | dao = container_of(atc->daios[SPDIFOO], struct dao, daio); | 935 | dao = container_of(atc->daios[SPDIFOO], struct dao, daio); |
939 | amixer = apcm->amixers[0]; | 936 | amixer = apcm->amixers[0]; |
940 | dao->ops->set_left_input(dao, &amixer->rsc); | 937 | dao->ops->set_left_input(dao, &amixer->rsc); |
941 | amixer = apcm->amixers[1]; | 938 | amixer = apcm->amixers[1]; |
942 | dao->ops->set_right_input(dao, &amixer->rsc); | 939 | dao->ops->set_right_input(dao, &amixer->rsc); |
943 | spin_unlock_irqrestore(&atc->atc_lock, flags); | 940 | mutex_unlock(&atc->atc_mutex); |
944 | 941 | ||
945 | ct_timer_prepare(apcm->timer); | 942 | ct_timer_prepare(apcm->timer); |
946 | 943 | ||
@@ -1088,7 +1085,6 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status) | |||
1088 | 1085 | ||
1089 | static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) | 1086 | static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) |
1090 | { | 1087 | { |
1091 | unsigned long flags; | ||
1092 | struct dao_desc da_dsc = {0}; | 1088 | struct dao_desc da_dsc = {0}; |
1093 | struct dao *dao; | 1089 | struct dao *dao; |
1094 | int err; | 1090 | int err; |
@@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) | |||
1096 | struct rsc *rscs[2] = {NULL}; | 1092 | struct rsc *rscs[2] = {NULL}; |
1097 | unsigned int spos = 0; | 1093 | unsigned int spos = 0; |
1098 | 1094 | ||
1099 | spin_lock_irqsave(&atc->atc_lock, flags); | 1095 | mutex_lock(&atc->atc_mutex); |
1100 | dao = container_of(atc->daios[SPDIFOO], struct dao, daio); | 1096 | dao = container_of(atc->daios[SPDIFOO], struct dao, daio); |
1101 | da_dsc.msr = state ? 1 : atc->msr; | 1097 | da_dsc.msr = state ? 1 : atc->msr; |
1102 | da_dsc.passthru = state ? 1 : 0; | 1098 | da_dsc.passthru = state ? 1 : 0; |
@@ -1114,7 +1110,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) | |||
1114 | } | 1110 | } |
1115 | dao->ops->set_spos(dao, spos); | 1111 | dao->ops->set_spos(dao, spos); |
1116 | dao->ops->commit_write(dao); | 1112 | dao->ops->commit_write(dao); |
1117 | spin_unlock_irqrestore(&atc->atc_lock, flags); | 1113 | mutex_unlock(&atc->atc_mutex); |
1118 | 1114 | ||
1119 | return err; | 1115 | return err; |
1120 | } | 1116 | } |
@@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, | |||
1572 | atc->msr = msr; | 1568 | atc->msr = msr; |
1573 | atc->chip_type = chip_type; | 1569 | atc->chip_type = chip_type; |
1574 | 1570 | ||
1575 | spin_lock_init(&atc->atc_lock); | 1571 | mutex_init(&atc->atc_mutex); |
1576 | 1572 | ||
1577 | /* Find card model */ | 1573 | /* Find card model */ |
1578 | err = atc_identify_card(atc); | 1574 | err = atc_identify_card(atc); |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index a03347232e84..9fe620ea5f3f 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
@@ -19,7 +19,7 @@ | |||
19 | #define CTATC_H | 19 | #define CTATC_H |
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/spinlock_types.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -90,7 +90,7 @@ struct ct_atc { | |||
90 | void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); | 90 | void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); |
91 | unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index); | 91 | unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index); |
92 | 92 | ||
93 | spinlock_t atc_lock; | 93 | struct mutex atc_mutex; |
94 | 94 | ||
95 | int (*pcm_playback_prepare)(struct ct_atc *atc, | 95 | int (*pcm_playback_prepare)(struct ct_atc *atc, |
96 | struct ct_atc_pcm *apcm); | 96 | struct ct_atc_pcm *apcm); |
diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c index 779c6c3591a5..93b0aedc36d4 100644 --- a/sound/pci/ctxfi/cttimer.c +++ b/sound/pci/ctxfi/cttimer.c | |||
@@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) | |||
180 | * | 180 | * |
181 | * call this inside the lock and irq disabled | 181 | * call this inside the lock and irq disabled |
182 | */ | 182 | */ |
183 | static int ct_xfitimer_reprogram(struct ct_timer *atimer) | 183 | static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update) |
184 | { | 184 | { |
185 | struct ct_timer_instance *ti; | 185 | struct ct_timer_instance *ti; |
186 | unsigned int min_intr = (unsigned int)-1; | 186 | unsigned int min_intr = (unsigned int)-1; |
@@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer) | |||
216 | ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + | 216 | ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + |
217 | rate - 1, rate); | 217 | rate - 1, rate); |
218 | } | 218 | } |
219 | if (ti->need_update && !can_update) | ||
220 | min_intr = 0; /* pending to the next irq */ | ||
219 | if (ti->frag_count < min_intr) | 221 | if (ti->frag_count < min_intr) |
220 | min_intr = ti->frag_count; | 222 | min_intr = ti->frag_count; |
221 | } | 223 | } |
@@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer) | |||
235 | 237 | ||
236 | spin_lock_irqsave(&atimer->list_lock, flags); | 238 | spin_lock_irqsave(&atimer->list_lock, flags); |
237 | list_for_each_entry(ti, &atimer->instance_head, instance_list) { | 239 | list_for_each_entry(ti, &atimer->instance_head, instance_list) { |
238 | if (ti->need_update) { | 240 | if (ti->running && ti->need_update) { |
239 | ti->need_update = 0; | 241 | ti->need_update = 0; |
240 | ti->apcm->interrupt(ti->apcm); | 242 | ti->apcm->interrupt(ti->apcm); |
241 | } | 243 | } |
@@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer) | |||
252 | spin_lock_irqsave(&atimer->lock, flags); | 254 | spin_lock_irqsave(&atimer->lock, flags); |
253 | atimer->irq_handling = 1; | 255 | atimer->irq_handling = 1; |
254 | do { | 256 | do { |
255 | update = ct_xfitimer_reprogram(atimer); | 257 | update = ct_xfitimer_reprogram(atimer, 1); |
256 | spin_unlock(&atimer->lock); | 258 | spin_unlock(&atimer->lock); |
257 | if (update) | 259 | if (update) |
258 | ct_xfitimer_check_period(atimer); | 260 | ct_xfitimer_check_period(atimer); |
@@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer) | |||
265 | static void ct_xfitimer_prepare(struct ct_timer_instance *ti) | 267 | static void ct_xfitimer_prepare(struct ct_timer_instance *ti) |
266 | { | 268 | { |
267 | ti->frag_count = ti->substream->runtime->period_size; | 269 | ti->frag_count = ti->substream->runtime->period_size; |
270 | ti->running = 0; | ||
268 | ti->need_update = 0; | 271 | ti->need_update = 0; |
269 | } | 272 | } |
270 | 273 | ||
@@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti) | |||
273 | static void ct_xfitimer_update(struct ct_timer *atimer) | 276 | static void ct_xfitimer_update(struct ct_timer *atimer) |
274 | { | 277 | { |
275 | unsigned long flags; | 278 | unsigned long flags; |
276 | int update; | ||
277 | 279 | ||
278 | spin_lock_irqsave(&atimer->lock, flags); | 280 | spin_lock_irqsave(&atimer->lock, flags); |
279 | if (atimer->irq_handling) { | 281 | if (atimer->irq_handling) { |
@@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer) | |||
284 | } | 286 | } |
285 | 287 | ||
286 | ct_xfitimer_irq_stop(atimer); | 288 | ct_xfitimer_irq_stop(atimer); |
287 | update = ct_xfitimer_reprogram(atimer); | 289 | ct_xfitimer_reprogram(atimer, 0); |
288 | spin_unlock_irqrestore(&atimer->lock, flags); | 290 | spin_unlock_irqrestore(&atimer->lock, flags); |
289 | if (update) | ||
290 | ct_xfitimer_check_period(atimer); | ||
291 | } | 291 | } |
292 | 292 | ||
293 | static void ct_xfitimer_start(struct ct_timer_instance *ti) | 293 | static void ct_xfitimer_start(struct ct_timer_instance *ti) |
@@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti) | |||
298 | spin_lock_irqsave(&atimer->lock, flags); | 298 | spin_lock_irqsave(&atimer->lock, flags); |
299 | if (list_empty(&ti->running_list)) | 299 | if (list_empty(&ti->running_list)) |
300 | atimer->wc = ct_xfitimer_get_wc(atimer); | 300 | atimer->wc = ct_xfitimer_get_wc(atimer); |
301 | ti->running = 1; | ||
302 | ti->need_update = 0; | ||
301 | list_add(&ti->running_list, &atimer->running_head); | 303 | list_add(&ti->running_list, &atimer->running_head); |
302 | spin_unlock_irqrestore(&atimer->lock, flags); | 304 | spin_unlock_irqrestore(&atimer->lock, flags); |
303 | ct_xfitimer_update(atimer); | 305 | ct_xfitimer_update(atimer); |
@@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti) | |||
310 | 312 | ||
311 | spin_lock_irqsave(&atimer->lock, flags); | 313 | spin_lock_irqsave(&atimer->lock, flags); |
312 | list_del_init(&ti->running_list); | 314 | list_del_init(&ti->running_list); |
313 | ti->need_update = 0; | 315 | ti->running = 0; |
314 | spin_unlock_irqrestore(&atimer->lock, flags); | 316 | spin_unlock_irqrestore(&atimer->lock, flags); |
315 | ct_xfitimer_update(atimer); | 317 | ct_xfitimer_update(atimer); |
316 | } | 318 | } |