Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / ppc / 8xx_io / cs4218_tdm.c
index 514e7de..a892356 100644 (file)
@@ -55,6 +55,8 @@ static int irq_installed = 0;
 static char **sound_buffers = NULL;
 static char **sound_read_buffers = NULL;
 
+static DEFINE_SPINLOCK(cs4218_lock);
+
 /* Local copies of things we put in the control register.  Output
  * volume, like most codecs is really attenuation.
  */
@@ -124,11 +126,11 @@ static int numReadBufs = 4, readbufSize = 32;
 */
 static volatile cbd_t  *rx_base, *rx_cur, *tx_base, *tx_cur;
 
-MODULE_PARM(catchRadius, "i");
-MODULE_PARM(numBufs, "i");
-MODULE_PARM(bufSize, "i");
-MODULE_PARM(numreadBufs, "i");
-MODULE_PARM(readbufSize, "i");
+module_param(catchRadius, int, 0);
+module_param(numBufs, int, 0);
+module_param(bufSize, int, 0);
+module_param(numreadBufs, int, 0);
+module_param(readbufSize, int, 0);
 
 #define arraysize(x)   (sizeof(x)/sizeof(*(x)))
 #define le2be16(x)     (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
@@ -316,7 +318,7 @@ struct cs_sound_settings {
 
 static struct cs_sound_settings sound;
 
-static void *CS_Alloc(unsigned int size, int flags);
+static void *CS_Alloc(unsigned int size, gfp_t flags);
 static void CS_Free(void *ptr, unsigned int size);
 static int CS_IrqInit(void);
 #ifdef MODULE
@@ -957,7 +959,7 @@ static TRANS transCSNormalRead = {
 
 /*** Low level stuff *********************************************************/
 
-static void *CS_Alloc(unsigned int size, int flags)
+static void *CS_Alloc(unsigned int size, gfp_t flags)
 {
        int     order;
 
@@ -1011,8 +1013,7 @@ static void CS_IrqCleanup(void)
        */
        cpm_free_handler(CPMVEC_SMC2);
 
-       if (beep_buf)
-               kfree(beep_buf);
+       kfree(beep_buf);
        kd_mksound = orig_mksound;
 }
 #endif /* MODULE */
@@ -1206,7 +1207,8 @@ static void CS_Play(void)
        volatile cbd_t  *bdp;
        volatile cpm8xx_t *cp;
 
-       save_flags(flags); cli();
+       /* Protect buffer */
+       spin_lock_irqsave(&cs4218_lock, flags);
 #if 0
        if (awacs_beep_state) {
                /* sound takes precedence over beeps */
@@ -1263,7 +1265,7 @@ static void CS_Play(void)
 
                ++sq.active;
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&cs4218_lock, flags);
 }
 
 
@@ -1275,7 +1277,8 @@ static void CS_Record(void)
        if (read_sq.active)
                return;
 
-       save_flags(flags); cli();
+       /* Protect buffer */
+       spin_lock_irqsave(&cs4218_lock, flags);
 
        /* This is all we have to do......Just start it up.
        */
@@ -1284,7 +1287,7 @@ static void CS_Record(void)
 
        read_sq.active = 1;
 
-        restore_flags(flags);
+        spin_unlock_irqrestore(&cs4218_lock, flags);
 }
 
 
@@ -1365,17 +1368,18 @@ static void cs_nosound(unsigned long xx)
 {
        unsigned long flags;
 
-       save_flags(flags); cli();
+       /* not sure if this is needed, since hardware command is #if 0'd */
+       spin_lock_irqsave(&cs4218_lock, flags);
        if (beep_playing) {
 #if 0
                st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
 #endif
                beep_playing = 0;
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&cs4218_lock, flags);
 }
 
-static struct timer_list beep_timer = TIMER_INITIALIZER(cs_nosound, 0, 0);
+static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0);
 };
 
 static void cs_mksound(unsigned int hz, unsigned int ticks)
@@ -1401,21 +1405,22 @@ static void cs_mksound(unsigned int hz, unsigned int ticks)
                return;
 #endif
        }
-       save_flags(flags); cli();
+       /* lock while modifying beep_timer */
+       spin_lock_irqsave(&cs4218_lock, flags);
        del_timer(&beep_timer);
        if (ticks) {
                beep_timer.expires = jiffies + ticks;
                add_timer(&beep_timer);
        }
        if (beep_playing || sq.active || beep_buf == NULL) {
-               restore_flags(flags);
+               spin_unlock_irqrestore(&cs4218_lock, flags);
                return;         /* too hard, sorry :-( */
        }
        beep_playing = 1;
 #if 0
        st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
 #endif
-       restore_flags(flags);
+       spin_unlock_irqrestore(&cs4218_lock, flags);
 
        if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {
                nsamples = beep_nsamples_cache;
@@ -1442,7 +1447,7 @@ static void cs_mksound(unsigned int hz, unsigned int ticks)
        st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
        awacs_beep_state = 1;
 
-       save_flags(flags); cli();
+       spin_lock_irqsave(&cs4218_lock, flags);
        if (beep_playing) {     /* i.e. haven't been terminated already */
                out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
                out_le32(&awacs->control,
@@ -1452,8 +1457,8 @@ static void cs_mksound(unsigned int hz, unsigned int ticks)
                out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
                out_le32(&awacs_txdma->control, RUN | (RUN << 16));
        }
+       spin_unlock_irqrestore(&cs4218_lock, flags);
 #endif
-       restore_flags(flags);
 }
 
 static MACHINE mach_cs4218 = {