aboutsummaryrefslogtreecommitdiffstats
path: root/sound/sparc
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2006-09-05 14:25:05 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:45:57 -0400
commitea543f1ee61bbfdf6cac4b79d66c7840d5b00037 (patch)
tree9afd4cc03826e32f6abd2145c77c7e9d8311a183 /sound/sparc
parent679e28eef835cbd30de78c2f80bf488cba1b7e40 (diff)
[ALSA] sparc dbri: SMP fixes
The dbri driver hangs when used in kernel compiled with SMP support due to inproper locking. The patch fixes it. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/sparc')
-rw-r--r--sound/sparc/dbri.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 82d5e8072f2b..e4935fca12df 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -635,10 +635,16 @@ to send them to the DBRI.
635static void dbri_cmdwait(struct snd_dbri *dbri) 635static void dbri_cmdwait(struct snd_dbri *dbri)
636{ 636{
637 int maxloops = MAXLOOPS; 637 int maxloops = MAXLOOPS;
638 unsigned long flags;
638 639
639 /* Delay if previous commands are still being processed */ 640 /* Delay if previous commands are still being processed */
640 while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) 641 spin_lock_irqsave(&dbri->lock, flags);
642 while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) {
643 spin_unlock_irqrestore(&dbri->lock, flags);
641 msleep_interruptible(1); 644 msleep_interruptible(1);
645 spin_lock_irqsave(&dbri->lock, flags);
646 }
647 spin_unlock_irqrestore(&dbri->lock, flags);
642 648
643 if (maxloops == 0) { 649 if (maxloops == 0) {
644 printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); 650 printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
@@ -671,11 +677,12 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
671 * the last WAIT cmd and force DBRI to reread the cmd. 677 * the last WAIT cmd and force DBRI to reread the cmd.
672 * The JUMP cmd points to the new cmd string. 678 * The JUMP cmd points to the new cmd string.
673 * It also releases the cmdlock spinlock. 679 * It also releases the cmdlock spinlock.
680 *
681 * Lock must not be held before calling this.
674 */ 682 */
675static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) 683static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
676{ 684{
677 s32 tmp, addr; 685 s32 tmp, addr;
678 unsigned long flags;
679 static int wait_id = 0; 686 static int wait_id = 0;
680 687
681 wait_id++; 688 wait_id++;
@@ -706,12 +713,10 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
706 } 713 }
707#endif 714#endif
708 715
709 spin_lock_irqsave(&dbri->lock, flags);
710 /* Reread the last command */ 716 /* Reread the last command */
711 tmp = sbus_readl(dbri->regs + REG0); 717 tmp = sbus_readl(dbri->regs + REG0);
712 tmp |= D_P; 718 tmp |= D_P;
713 sbus_writel(tmp, dbri->regs + REG0); 719 sbus_writel(tmp, dbri->regs + REG0);
714 spin_unlock_irqrestore(&dbri->lock, flags);
715 720
716 dbri->cmdptr = cmd; 721 dbri->cmdptr = cmd;
717 spin_unlock(&dbri->cmdlock); 722 spin_unlock(&dbri->cmdlock);
@@ -777,9 +782,9 @@ static void dbri_initialize(struct snd_dbri * dbri)
777 dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0); 782 dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0);
778 sbus_writel(dma_addr, dbri->regs + REG8); 783 sbus_writel(dma_addr, dbri->regs + REG8);
779 spin_unlock(&dbri->cmdlock); 784 spin_unlock(&dbri->cmdlock);
780 dbri_cmdwait(dbri);
781 785
782 spin_unlock_irqrestore(&dbri->lock, flags); 786 spin_unlock_irqrestore(&dbri->lock, flags);
787 dbri_cmdwait(dbri);
783} 788}
784 789
785/* 790/*
@@ -840,6 +845,9 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe)
840 dbri->pipes[pipe].first_desc = -1; 845 dbri->pipes[pipe].first_desc = -1;
841} 846}
842 847
848/*
849 * Lock must be held before calling this.
850 */
843static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) 851static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
844{ 852{
845 if (pipe < 0 || pipe > DBRI_MAX_PIPE) { 853 if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
@@ -866,6 +874,9 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
866 reset_pipe(dbri, pipe); 874 reset_pipe(dbri, pipe);
867} 875}
868 876
877/*
878 * Lock must be held before calling this.
879 */
869static void link_time_slot(struct snd_dbri * dbri, int pipe, 880static void link_time_slot(struct snd_dbri * dbri, int pipe,
870 int prevpipe, int nextpipe, 881 int prevpipe, int nextpipe,
871 int length, int cycle) 882 int length, int cycle)
@@ -920,6 +931,10 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe,
920 dbri_cmdsend(dbri, cmd, 4); 931 dbri_cmdsend(dbri, cmd, 4);
921} 932}
922 933
934#if 0
935/*
936 * Lock must be held before calling this.
937 */
923static void unlink_time_slot(struct snd_dbri * dbri, int pipe, 938static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
924 enum in_or_out direction, int prevpipe, 939 enum in_or_out direction, int prevpipe,
925 int nextpipe) 940 int nextpipe)
@@ -952,6 +967,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
952 967
953 dbri_cmdsend(dbri, cmd, 4); 968 dbri_cmdsend(dbri, cmd, 4);
954} 969}
970#endif
955 971
956/* xmit_fixed() / recv_fixed() 972/* xmit_fixed() / recv_fixed()
957 * 973 *
@@ -965,11 +981,14 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
965 * the actual time slot is. The interrupt handler takes care of bit 981 * the actual time slot is. The interrupt handler takes care of bit
966 * ordering and alignment. An 8-bit time slot will always end up 982 * ordering and alignment. An 8-bit time slot will always end up
967 * in the low-order 8 bits, filled either MSB-first or LSB-first, 983 * in the low-order 8 bits, filled either MSB-first or LSB-first,
968 * depending on the settings passed to setup_pipe() 984 * depending on the settings passed to setup_pipe().
985 *
986 * Lock must not be held before calling it.
969 */ 987 */
970static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) 988static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
971{ 989{
972 s32 *cmd; 990 s32 *cmd;
991 unsigned long flags;
973 992
974 if (pipe < 16 || pipe > DBRI_MAX_PIPE) { 993 if (pipe < 16 || pipe > DBRI_MAX_PIPE) {
975 printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n"); 994 printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
@@ -1002,8 +1021,11 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
1002 *(cmd++) = data; 1021 *(cmd++) = data;
1003 *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); 1022 *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
1004 1023
1024 spin_lock_irqsave(&dbri->lock, flags);
1005 dbri_cmdsend(dbri, cmd, 3); 1025 dbri_cmdsend(dbri, cmd, 3);
1026 spin_unlock_irqrestore(&dbri->lock, flags);
1006 dbri_cmdwait(dbri); 1027 dbri_cmdwait(dbri);
1028
1007} 1029}
1008 1030
1009static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) 1031static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
@@ -1039,6 +1061,8 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
1039 * be spread across multiple descriptors. 1061 * be spread across multiple descriptors.
1040 * 1062 *
1041 * All descriptors create a ring buffer. 1063 * All descriptors create a ring buffer.
1064 *
1065 * Lock must be held before calling this.
1042 */ 1066 */
1043static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) 1067static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period)
1044{ 1068{
@@ -1186,6 +1210,9 @@ multiplexed serial interface which the DBRI can operate in either master
1186 1210
1187enum master_or_slave { CHImaster, CHIslave }; 1211enum master_or_slave { CHImaster, CHIslave };
1188 1212
1213/*
1214 * Lock must not be held before calling it.
1215 */
1189static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, 1216static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave,
1190 int bits_per_frame) 1217 int bits_per_frame)
1191{ 1218{
@@ -1258,9 +1285,14 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla
1258In the standard SPARC audio configuration, the CS4215 codec is attached 1285In the standard SPARC audio configuration, the CS4215 codec is attached
1259to the DBRI via the CHI interface and few of the DBRI's PIO pins. 1286to the DBRI via the CHI interface and few of the DBRI's PIO pins.
1260 1287
1288 * Lock must not be held before calling it.
1289
1261*/ 1290*/
1262static void cs4215_setup_pipes(struct snd_dbri * dbri) 1291static void cs4215_setup_pipes(struct snd_dbri * dbri)
1263{ 1292{
1293 unsigned long flags;
1294
1295 spin_lock_irqsave(&dbri->lock, flags);
1264 /* 1296 /*
1265 * Data mode: 1297 * Data mode:
1266 * Pipe 4: Send timeslots 1-4 (audio data) 1298 * Pipe 4: Send timeslots 1-4 (audio data)
@@ -1284,6 +1316,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri)
1284 setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); 1316 setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB);
1285 setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); 1317 setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
1286 setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); 1318 setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
1319 spin_unlock_irqrestore(&dbri->lock, flags);
1287 1320
1288 dbri_cmdwait(dbri); 1321 dbri_cmdwait(dbri);
1289} 1322}
@@ -1358,6 +1391,7 @@ static void cs4215_open(struct snd_dbri * dbri)
1358{ 1391{
1359 int data_width; 1392 int data_width;
1360 u32 tmp; 1393 u32 tmp;
1394 unsigned long flags;
1361 1395
1362 dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", 1396 dprintk(D_MM, "cs4215_open: %d channels, %d bits\n",
1363 dbri->mm.channels, dbri->mm.precision); 1397 dbri->mm.channels, dbri->mm.precision);
@@ -1382,6 +1416,7 @@ static void cs4215_open(struct snd_dbri * dbri)
1382 * bits. The CS4215, it seems, observes TSIN (the delayed signal) 1416 * bits. The CS4215, it seems, observes TSIN (the delayed signal)
1383 * even if it's the CHI master. Don't ask me... 1417 * even if it's the CHI master. Don't ask me...
1384 */ 1418 */
1419 spin_lock_irqsave(&dbri->lock, flags);
1385 tmp = sbus_readl(dbri->regs + REG0); 1420 tmp = sbus_readl(dbri->regs + REG0);
1386 tmp &= ~(D_C); /* Disable CHI */ 1421 tmp &= ~(D_C); /* Disable CHI */
1387 sbus_writel(tmp, dbri->regs + REG0); 1422 sbus_writel(tmp, dbri->regs + REG0);
@@ -1409,6 +1444,7 @@ static void cs4215_open(struct snd_dbri * dbri)
1409 tmp = sbus_readl(dbri->regs + REG0); 1444 tmp = sbus_readl(dbri->regs + REG0);
1410 tmp |= D_C; /* Enable CHI */ 1445 tmp |= D_C; /* Enable CHI */
1411 sbus_writel(tmp, dbri->regs + REG0); 1446 sbus_writel(tmp, dbri->regs + REG0);
1447 spin_unlock_irqrestore(&dbri->lock, flags);
1412 1448
1413 cs4215_setdata(dbri, 0); 1449 cs4215_setdata(dbri, 0);
1414} 1450}
@@ -1420,6 +1456,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
1420{ 1456{
1421 int i, val; 1457 int i, val;
1422 u32 tmp; 1458 u32 tmp;
1459 unsigned long flags;
1423 1460
1424 /* FIXME - let the CPU do something useful during these delays */ 1461 /* FIXME - let the CPU do something useful during these delays */
1425 1462
@@ -1456,6 +1493,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
1456 * done in hardware by a TI 248 that delays the DBRI->4215 1493 * done in hardware by a TI 248 that delays the DBRI->4215
1457 * frame sync signal by eight clock cycles. Anybody know why? 1494 * frame sync signal by eight clock cycles. Anybody know why?
1458 */ 1495 */
1496 spin_lock_irqsave(&dbri->lock, flags);
1459 tmp = sbus_readl(dbri->regs + REG0); 1497 tmp = sbus_readl(dbri->regs + REG0);
1460 tmp &= ~D_C; /* Disable CHI */ 1498 tmp &= ~D_C; /* Disable CHI */
1461 sbus_writel(tmp, dbri->regs + REG0); 1499 sbus_writel(tmp, dbri->regs + REG0);
@@ -1472,14 +1510,17 @@ static int cs4215_setctrl(struct snd_dbri * dbri)
1472 link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); 1510 link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset);
1473 link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); 1511 link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset);
1474 link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); 1512 link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48);
1513 spin_unlock_irqrestore(&dbri->lock, flags);
1475 1514
1476 /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ 1515 /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */
1477 dbri->mm.ctrl[0] &= ~CS4215_CLB; 1516 dbri->mm.ctrl[0] &= ~CS4215_CLB;
1478 xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); 1517 xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
1479 1518
1519 spin_lock_irqsave(&dbri->lock, flags);
1480 tmp = sbus_readl(dbri->regs + REG0); 1520 tmp = sbus_readl(dbri->regs + REG0);
1481 tmp |= D_C; /* Enable CHI */ 1521 tmp |= D_C; /* Enable CHI */
1482 sbus_writel(tmp, dbri->regs + REG0); 1522 sbus_writel(tmp, dbri->regs + REG0);
1523 spin_unlock_irqrestore(&dbri->lock, flags);
1483 1524
1484 for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { 1525 for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
1485 msleep_interruptible(1); 1526 msleep_interruptible(1);
@@ -1688,6 +1729,7 @@ static void xmit_descs(struct snd_dbri *dbri)
1688 dbri->pipes[info->pipe].desc = first_td; 1729 dbri->pipes[info->pipe].desc = first_td;
1689 } 1730 }
1690 } 1731 }
1732
1691 spin_unlock_irqrestore(&dbri->lock, flags); 1733 spin_unlock_irqrestore(&dbri->lock, flags);
1692} 1734}
1693 1735
@@ -2093,7 +2135,6 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream)
2093{ 2135{
2094 struct snd_dbri *dbri = snd_pcm_substream_chip(substream); 2136 struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2095 struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); 2137 struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
2096 struct snd_pcm_runtime *runtime = substream->runtime;
2097 int ret; 2138 int ret;
2098 2139
2099 info->size = snd_pcm_lib_buffer_bytes(substream); 2140 info->size = snd_pcm_lib_buffer_bytes(substream);
@@ -2232,7 +2273,6 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
2232{ 2273{
2233 struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); 2274 struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
2234 struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; 2275 struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value];
2235 unsigned long flags;
2236 int changed = 0; 2276 int changed = 0;
2237 2277
2238 if (info->left_gain != ucontrol->value.integer.value[0]) { 2278 if (info->left_gain != ucontrol->value.integer.value[0]) {
@@ -2247,13 +2287,9 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
2247 /* First mute outputs, and wait 1/8000 sec (125 us) 2287 /* First mute outputs, and wait 1/8000 sec (125 us)
2248 * to make sure this takes. This avoids clicking noises. 2288 * to make sure this takes. This avoids clicking noises.
2249 */ 2289 */
2250 spin_lock_irqsave(&dbri->lock, flags);
2251
2252 cs4215_setdata(dbri, 1); 2290 cs4215_setdata(dbri, 1);
2253 udelay(125); 2291 udelay(125);
2254 cs4215_setdata(dbri, 0); 2292 cs4215_setdata(dbri, 0);
2255
2256 spin_unlock_irqrestore(&dbri->lock, flags);
2257 } 2293 }
2258 return changed; 2294 return changed;
2259} 2295}
@@ -2300,7 +2336,6 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
2300 struct snd_ctl_elem_value *ucontrol) 2336 struct snd_ctl_elem_value *ucontrol)
2301{ 2337{
2302 struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); 2338 struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
2303 unsigned long flags;
2304 int elem = kcontrol->private_value & 0xff; 2339 int elem = kcontrol->private_value & 0xff;
2305 int shift = (kcontrol->private_value >> 8) & 0xff; 2340 int shift = (kcontrol->private_value >> 8) & 0xff;
2306 int mask = (kcontrol->private_value >> 16) & 0xff; 2341 int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -2333,13 +2368,9 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
2333 /* First mute outputs, and wait 1/8000 sec (125 us) 2368 /* First mute outputs, and wait 1/8000 sec (125 us)
2334 * to make sure this takes. This avoids clicking noises. 2369 * to make sure this takes. This avoids clicking noises.
2335 */ 2370 */
2336 spin_lock_irqsave(&dbri->lock, flags);
2337
2338 cs4215_setdata(dbri, 1); 2371 cs4215_setdata(dbri, 1);
2339 udelay(125); 2372 udelay(125);
2340 cs4215_setdata(dbri, 0); 2373 cs4215_setdata(dbri, 0);
2341
2342 spin_unlock_irqrestore(&dbri->lock, flags);
2343 } 2374 }
2344 return changed; 2375 return changed;
2345} 2376}