aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-09-10 06:21:38 -0400
committerTakashi Iwai <tiwai@suse.de>2014-09-15 09:52:09 -0400
commit9bef72bdb26e291d6dffb04768741a0e49582666 (patch)
tree84d04d67bd5b9c2a7785ae4e9dc65f3e125fe548
parent8d3a8b5cb57da4e327bdaf7c81a90d4105b73205 (diff)
ALSA: pcxhr: Use nonatomic PCM ops
This time PCXHR, another Digigram boards: like the previous patches, the conversion is straightforward, replacing spinlocks with mutexes, merging the irq tasklet into the threaded irq handler and the PCM trigger tasklet back to the trigger callback. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/pcxhr/pcxhr.c43
-rw-r--r--sound/pci/pcxhr/pcxhr.h8
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c102
-rw-r--r--sound/pci/pcxhr/pcxhr_core.h2
4 files changed, 77 insertions, 78 deletions
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 68a37a7906c1..b854fc5e01f5 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -702,13 +702,11 @@ static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream,
702 return 0; 702 return 0;
703} 703}
704 704
705static void pcxhr_trigger_tasklet(unsigned long arg) 705static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
706{ 706{
707 unsigned long flags;
708 int i, j, err; 707 int i, j, err;
709 struct pcxhr_pipe *pipe; 708 struct pcxhr_pipe *pipe;
710 struct snd_pcxhr *chip; 709 struct snd_pcxhr *chip;
711 struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg);
712 int capture_mask = 0; 710 int capture_mask = 0;
713 int playback_mask = 0; 711 int playback_mask = 0;
714 712
@@ -736,11 +734,11 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
736 } 734 }
737 if (capture_mask == 0 && playback_mask == 0) { 735 if (capture_mask == 0 && playback_mask == 0) {
738 mutex_unlock(&mgr->setup_mutex); 736 mutex_unlock(&mgr->setup_mutex);
739 dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : no pipes\n"); 737 dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
740 return; 738 return;
741 } 739 }
742 740
743 dev_dbg(&mgr->pci->dev, "pcxhr_trigger_tasklet : " 741 dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
744 "playback_mask=%x capture_mask=%x\n", 742 "playback_mask=%x capture_mask=%x\n",
745 playback_mask, capture_mask); 743 playback_mask, capture_mask);
746 744
@@ -748,7 +746,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
748 err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); 746 err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
749 if (err) { 747 if (err) {
750 mutex_unlock(&mgr->setup_mutex); 748 mutex_unlock(&mgr->setup_mutex);
751 dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " 749 dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
752 "error stop pipes (P%x C%x)\n", 750 "error stop pipes (P%x C%x)\n",
753 playback_mask, capture_mask); 751 playback_mask, capture_mask);
754 return; 752 return;
@@ -793,7 +791,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
793 err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); 791 err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
794 if (err) { 792 if (err) {
795 mutex_unlock(&mgr->setup_mutex); 793 mutex_unlock(&mgr->setup_mutex);
796 dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : " 794 dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
797 "error start pipes (P%x C%x)\n", 795 "error start pipes (P%x C%x)\n",
798 playback_mask, capture_mask); 796 playback_mask, capture_mask);
799 return; 797 return;
@@ -802,7 +800,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
802 /* put the streams into the running state now 800 /* put the streams into the running state now
803 * (increment pointer by interrupt) 801 * (increment pointer by interrupt)
804 */ 802 */
805 spin_lock_irqsave(&mgr->lock, flags); 803 mutex_lock(&mgr->lock);
806 for ( i =0; i < mgr->num_cards; i++) { 804 for ( i =0; i < mgr->num_cards; i++) {
807 struct pcxhr_stream *stream; 805 struct pcxhr_stream *stream;
808 chip = mgr->chip[i]; 806 chip = mgr->chip[i];
@@ -820,13 +818,13 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
820 } 818 }
821 } 819 }
822 } 820 }
823 spin_unlock_irqrestore(&mgr->lock, flags); 821 mutex_unlock(&mgr->lock);
824 822
825 mutex_unlock(&mgr->setup_mutex); 823 mutex_unlock(&mgr->setup_mutex);
826 824
827#ifdef CONFIG_SND_DEBUG_VERBOSE 825#ifdef CONFIG_SND_DEBUG_VERBOSE
828 do_gettimeofday(&my_tv2); 826 do_gettimeofday(&my_tv2);
829 dev_dbg(&mgr->pci->dev, "***TRIGGER TASKLET*** TIME = %ld (err = %x)\n", 827 dev_dbg(&mgr->pci->dev, "***TRIGGER START*** TIME = %ld (err = %x)\n",
830 (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); 828 (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
831#endif 829#endif
832} 830}
@@ -853,7 +851,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
853 PCXHR_STREAM_STATUS_SCHEDULE_RUN; 851 PCXHR_STREAM_STATUS_SCHEDULE_RUN;
854 snd_pcm_trigger_done(s, subs); 852 snd_pcm_trigger_done(s, subs);
855 } 853 }
856 tasklet_schedule(&chip->mgr->trigger_taskq); 854 pcxhr_start_linked_stream(chip->mgr);
857 } else { 855 } else {
858 stream = subs->runtime->private_data; 856 stream = subs->runtime->private_data;
859 snd_printdd("Only one Substream %c %d\n", 857 snd_printdd("Only one Substream %c %d\n",
@@ -1127,20 +1125,19 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
1127 1125
1128static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) 1126static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
1129{ 1127{
1130 unsigned long flags;
1131 u_int32_t timer_period_frag; 1128 u_int32_t timer_period_frag;
1132 int timer_buf_periods; 1129 int timer_buf_periods;
1133 struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); 1130 struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
1134 struct snd_pcm_runtime *runtime = subs->runtime; 1131 struct snd_pcm_runtime *runtime = subs->runtime;
1135 struct pcxhr_stream *stream = runtime->private_data; 1132 struct pcxhr_stream *stream = runtime->private_data;
1136 1133
1137 spin_lock_irqsave(&chip->mgr->lock, flags); 1134 mutex_lock(&chip->mgr->lock);
1138 1135
1139 /* get the period fragment and the nb of periods in the buffer */ 1136 /* get the period fragment and the nb of periods in the buffer */
1140 timer_period_frag = stream->timer_period_frag; 1137 timer_period_frag = stream->timer_period_frag;
1141 timer_buf_periods = stream->timer_buf_periods; 1138 timer_buf_periods = stream->timer_buf_periods;
1142 1139
1143 spin_unlock_irqrestore(&chip->mgr->lock, flags); 1140 mutex_unlock(&chip->mgr->lock);
1144 1141
1145 return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) + 1142 return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +
1146 timer_period_frag); 1143 timer_period_frag);
@@ -1181,6 +1178,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip)
1181 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops); 1178 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);
1182 1179
1183 pcm->info_flags = 0; 1180 pcm->info_flags = 0;
1181 pcm->nonatomic = true;
1184 strcpy(pcm->name, name); 1182 strcpy(pcm->name, name);
1185 1183
1186 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1184 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1588,8 +1586,9 @@ static int pcxhr_probe(struct pci_dev *pci,
1588 mgr->pci = pci; 1586 mgr->pci = pci;
1589 mgr->irq = -1; 1587 mgr->irq = -1;
1590 1588
1591 if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, 1589 if (request_threaded_irq(pci->irq, pcxhr_interrupt,
1592 KBUILD_MODNAME, mgr)) { 1590 pcxhr_threaded_irq, IRQF_SHARED,
1591 KBUILD_MODNAME, mgr)) {
1593 dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq); 1592 dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
1594 pcxhr_free(mgr); 1593 pcxhr_free(mgr);
1595 return -EBUSY; 1594 return -EBUSY;
@@ -1601,19 +1600,13 @@ static int pcxhr_probe(struct pci_dev *pci,
1601 mgr->shortname, 1600 mgr->shortname,
1602 mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq); 1601 mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
1603 1602
1604 /* ISR spinlock */ 1603 /* ISR lock */
1605 spin_lock_init(&mgr->lock); 1604 mutex_init(&mgr->lock);
1606 spin_lock_init(&mgr->msg_lock); 1605 mutex_init(&mgr->msg_lock);
1607 1606
1608 /* init setup mutex*/ 1607 /* init setup mutex*/
1609 mutex_init(&mgr->setup_mutex); 1608 mutex_init(&mgr->setup_mutex);
1610 1609
1611 /* init taslket */
1612 tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
1613 (unsigned long) mgr);
1614 tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
1615 (unsigned long) mgr);
1616
1617 mgr->prmh = kmalloc(sizeof(*mgr->prmh) + 1610 mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
1618 sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - 1611 sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
1619 PCXHR_SIZE_MAX_STATUS), 1612 PCXHR_SIZE_MAX_STATUS),
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index a4c602c45173..9e39e509a3ef 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -78,14 +78,10 @@ struct pcxhr_mgr {
78 char shortname[32]; /* short name of this soundcard */ 78 char shortname[32]; /* short name of this soundcard */
79 char longname[96]; /* name of this soundcard */ 79 char longname[96]; /* name of this soundcard */
80 80
81 /* message tasklet */
82 struct tasklet_struct msg_taskq;
83 struct pcxhr_rmh *prmh; 81 struct pcxhr_rmh *prmh;
84 /* trigger tasklet */
85 struct tasklet_struct trigger_taskq;
86 82
87 spinlock_t lock; /* interrupt spinlock */ 83 struct mutex lock; /* interrupt lock */
88 spinlock_t msg_lock; /* message spinlock */ 84 struct mutex msg_lock; /* message lock */
89 85
90 struct mutex setup_mutex; /* mutex used in hw_params, open and close */ 86 struct mutex setup_mutex; /* mutex used in hw_params, open and close */
91 struct mutex mixer_mutex; /* mutex for mixer */ 87 struct mutex mixer_mutex; /* mutex for mixer */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index df9371918601..a584acb61c00 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -767,11 +767,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,
767 */ 767 */
768int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 768int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
769{ 769{
770 unsigned long flags;
771 int err; 770 int err;
772 spin_lock_irqsave(&mgr->msg_lock, flags); 771
772 mutex_lock(&mgr->msg_lock);
773 err = pcxhr_send_msg_nolock(mgr, rmh); 773 err = pcxhr_send_msg_nolock(mgr, rmh);
774 spin_unlock_irqrestore(&mgr->msg_lock, flags); 774 mutex_unlock(&mgr->msg_lock);
775 return err; 775 return err;
776} 776}
777 777
@@ -971,17 +971,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
971 unsigned int value, int *changed) 971 unsigned int value, int *changed)
972{ 972{
973 struct pcxhr_rmh rmh; 973 struct pcxhr_rmh rmh;
974 unsigned long flags;
975 int err; 974 int err;
976 975
977 spin_lock_irqsave(&mgr->msg_lock, flags); 976 mutex_lock(&mgr->msg_lock);
978 if ((mgr->io_num_reg_cont & mask) == value) { 977 if ((mgr->io_num_reg_cont & mask) == value) {
979 dev_dbg(&mgr->pci->dev, 978 dev_dbg(&mgr->pci->dev,
980 "IO_NUM_REG_CONT mask %x already is set to %x\n", 979 "IO_NUM_REG_CONT mask %x already is set to %x\n",
981 mask, value); 980 mask, value);
982 if (changed) 981 if (changed)
983 *changed = 0; 982 *changed = 0;
984 spin_unlock_irqrestore(&mgr->msg_lock, flags); 983 mutex_unlock(&mgr->msg_lock);
985 return 0; /* already programmed */ 984 return 0; /* already programmed */
986 } 985 }
987 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); 986 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
@@ -996,7 +995,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
996 if (changed) 995 if (changed)
997 *changed = 1; 996 *changed = 1;
998 } 997 }
999 spin_unlock_irqrestore(&mgr->msg_lock, flags); 998 mutex_unlock(&mgr->msg_lock);
1000 return err; 999 return err;
1001} 1000}
1002 1001
@@ -1043,22 +1042,21 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
1043} 1042}
1044 1043
1045 1044
1046void pcxhr_msg_tasklet(unsigned long arg) 1045static void pcxhr_msg_thread(struct pcxhr_mgr *mgr)
1047{ 1046{
1048 struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg);
1049 struct pcxhr_rmh *prmh = mgr->prmh; 1047 struct pcxhr_rmh *prmh = mgr->prmh;
1050 int err; 1048 int err;
1051 int i, j; 1049 int i, j;
1052 1050
1053 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) 1051 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE)
1054 dev_dbg(&mgr->pci->dev, 1052 dev_dbg(&mgr->pci->dev,
1055 "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); 1053 "PCXHR_IRQ_FREQ_CHANGE event occurred\n");
1056 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) 1054 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE)
1057 dev_dbg(&mgr->pci->dev, 1055 dev_dbg(&mgr->pci->dev,
1058 "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); 1056 "PCXHR_IRQ_TIME_CODE event occurred\n");
1059 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) 1057 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
1060 dev_dbg(&mgr->pci->dev, 1058 dev_dbg(&mgr->pci->dev,
1061 "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); 1059 "PCXHR_IRQ_NOTIFY event occurred\n");
1062 if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { 1060 if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
1063 /* clear events FREQ_CHANGE and TIME_CODE */ 1061 /* clear events FREQ_CHANGE and TIME_CODE */
1064 pcxhr_init_rmh(prmh, CMD_TEST_IT); 1062 pcxhr_init_rmh(prmh, CMD_TEST_IT);
@@ -1068,7 +1066,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
1068 } 1066 }
1069 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { 1067 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
1070 dev_dbg(&mgr->pci->dev, 1068 dev_dbg(&mgr->pci->dev,
1071 "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); 1069 "PCXHR_IRQ_ASYNC event occurred\n");
1072 1070
1073 pcxhr_init_rmh(prmh, CMD_ASYNC); 1071 pcxhr_init_rmh(prmh, CMD_ASYNC);
1074 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ 1072 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */
@@ -1076,7 +1074,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
1076 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; 1074 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
1077 err = pcxhr_send_msg(mgr, prmh); 1075 err = pcxhr_send_msg(mgr, prmh);
1078 if (err) 1076 if (err)
1079 dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n", 1077 dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n",
1080 err); 1078 err);
1081 i = 1; 1079 i = 1;
1082 while (i < prmh->stat_len) { 1080 while (i < prmh->stat_len) {
@@ -1220,9 +1218,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
1220 } 1218 }
1221 1219
1222 if (elapsed) { 1220 if (elapsed) {
1223 spin_unlock(&mgr->lock); 1221 mutex_unlock(&mgr->lock);
1224 snd_pcm_period_elapsed(stream->substream); 1222 snd_pcm_period_elapsed(stream->substream);
1225 spin_lock(&mgr->lock); 1223 mutex_lock(&mgr->lock);
1226 } 1224 }
1227 } 1225 }
1228} 1226}
@@ -1231,14 +1229,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1231{ 1229{
1232 struct pcxhr_mgr *mgr = dev_id; 1230 struct pcxhr_mgr *mgr = dev_id;
1233 unsigned int reg; 1231 unsigned int reg;
1234 int i, j; 1232 bool wake_thread = false;
1235 struct snd_pcxhr *chip;
1236
1237 spin_lock(&mgr->lock);
1238 1233
1239 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 1234 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
1240 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { 1235 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
1241 spin_unlock(&mgr->lock);
1242 /* this device did not cause the interrupt */ 1236 /* this device did not cause the interrupt */
1243 return IRQ_NONE; 1237 return IRQ_NONE;
1244 } 1238 }
@@ -1250,6 +1244,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1250 /* timer irq occurred */ 1244 /* timer irq occurred */
1251 if (reg & PCXHR_IRQ_TIMER) { 1245 if (reg & PCXHR_IRQ_TIMER) {
1252 int timer_toggle = reg & PCXHR_IRQ_TIMER; 1246 int timer_toggle = reg & PCXHR_IRQ_TIMER;
1247 if (timer_toggle == mgr->timer_toggle) {
1248 dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
1249 mgr->dsp_time_err++;
1250 }
1251
1252 mgr->timer_toggle = timer_toggle;
1253 mgr->src_it_dsp = reg;
1254 wake_thread = true;
1255 }
1256
1257 /* other irq's handled in the thread */
1258 if (reg & PCXHR_IRQ_MASK) {
1259 if (reg & PCXHR_IRQ_ASYNC) {
1260 /* as we didn't request any async notifications,
1261 * some kind of xrun error will probably occurred
1262 */
1263 /* better resynchronize all streams next interrupt : */
1264 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
1265 }
1266 mgr->src_it_dsp = reg;
1267 wake_thread = true;
1268 }
1269#ifdef CONFIG_SND_DEBUG_VERBOSE
1270 if (reg & PCXHR_FATAL_DSP_ERR)
1271 dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
1272#endif
1273
1274 return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
1275}
1276
1277irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id)
1278{
1279 struct pcxhr_mgr *mgr = dev_id;
1280 int i, j;
1281 struct snd_pcxhr *chip;
1282
1283 mutex_lock(&mgr->lock);
1284 if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) {
1253 /* is a 24 bit counter */ 1285 /* is a 24 bit counter */
1254 int dsp_time_new = 1286 int dsp_time_new =
1255 PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; 1287 PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
@@ -1290,13 +1322,6 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1290#endif 1322#endif
1291 mgr->dsp_time_last = dsp_time_new; 1323 mgr->dsp_time_last = dsp_time_new;
1292 1324
1293 if (timer_toggle == mgr->timer_toggle) {
1294 dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
1295 mgr->dsp_time_err++;
1296 }
1297 mgr->timer_toggle = timer_toggle;
1298
1299 reg &= ~PCXHR_IRQ_TIMER;
1300 for (i = 0; i < mgr->num_cards; i++) { 1325 for (i = 0; i < mgr->num_cards; i++) {
1301 chip = mgr->chip[i]; 1326 chip = mgr->chip[i];
1302 for (j = 0; j < chip->nb_streams_capt; j++) 1327 for (j = 0; j < chip->nb_streams_capt; j++)
@@ -1312,22 +1337,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
1312 dsp_time_diff); 1337 dsp_time_diff);
1313 } 1338 }
1314 } 1339 }
1315 /* other irq's handled in the tasklet */ 1340
1316 if (reg & PCXHR_IRQ_MASK) { 1341 pcxhr_msg_thread(mgr);
1317 if (reg & PCXHR_IRQ_ASYNC) { 1342 return IRQ_HANDLED;
1318 /* as we didn't request any async notifications,
1319 * some kind of xrun error will probably occurred
1320 */
1321 /* better resynchronize all streams next interrupt : */
1322 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
1323 }
1324 mgr->src_it_dsp = reg;
1325 tasklet_schedule(&mgr->msg_taskq);
1326 }
1327#ifdef CONFIG_SND_DEBUG_VERBOSE
1328 if (reg & PCXHR_FATAL_DSP_ERR)
1329 dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
1330#endif
1331 spin_unlock(&mgr->lock);
1332 return IRQ_HANDLED; /* this device caused the interrupt */
1333} 1343}
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index a81ab6b811e7..dc267e4c1074 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -200,6 +200,6 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
200 200
201/* interrupt handling */ 201/* interrupt handling */
202irqreturn_t pcxhr_interrupt(int irq, void *dev_id); 202irqreturn_t pcxhr_interrupt(int irq, void *dev_id);
203void pcxhr_msg_tasklet(unsigned long arg); 203irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id);
204 204
205#endif /* __SOUND_PCXHR_CORE_H */ 205#endif /* __SOUND_PCXHR_CORE_H */