Update of /cvsroot/alsa/alsa-kernel/pci/korg1212
In directory sc8-pr-cvs1:/tmp/cvs-serv21356
Modified Files:
korg1212.c
Log Message:
- fixed sleep in spinlocks.
- removed redundant locks.
- moved the dsp completion code outside of the interrupt handler.
- use mutex for open / close check.
- fixed comments.
Index: korg1212.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/korg1212/korg1212.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- korg1212.c 16 Feb 2003 18:03:31 -0000 1.27
+++ korg1212.c 27 Mar 2003 09:38:53 -0000 1.28
@@ -149,9 +149,9 @@
#define MAILBOX1_OFFSET 0x44 // location of mailbox 1 relative to base
address
#define MAILBOX2_OFFSET 0x48 // location of mailbox 2 relative to base
address
#define MAILBOX3_OFFSET 0x4c // location of mailbox 3 relative to base
address
-#define OUT_DOORBELL_OFFSET 0x60 // location of PCI to local doorbell "
-#define IN_DOORBELL_OFFSET 0x64 // location of local to PCI doorbell "
-#define STATUS_REG_OFFSET 0x68 // location of interrupt control/status
register "
+#define OUT_DOORBELL_OFFSET 0x60 // location of PCI to local doorbell
+#define IN_DOORBELL_OFFSET 0x64 // location of local to PCI doorbell
+#define STATUS_REG_OFFSET 0x68 // location of interrupt control/status
register
#define PCI_CONTROL_OFFSET 0x6c // location of the EEPROM, PCI, User I/O, init
control
// register
#define SENS_CONTROL_OFFSET 0x6e // location of the input sensitivity setting
register.
@@ -329,6 +329,10 @@
int irq;
spinlock_t lock;
+ struct semaphore open_mutex;
+
+ struct timer_list timer; /* timer callback for checking ack of stop
request */
+ int stop_pending_cnt; /* counter for stop pending check */
wait_queue_head_t wait;
@@ -602,66 +606,79 @@
return rc;
}
-static void snd_korg1212_WaitForCardStopAck(korg1212_t *korg1212)
+/* spinlock already held */
+static void snd_korg1212_SendStop(korg1212_t *korg1212)
{
- u32 endtime = jiffies + 2 * HZ;
-
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: WaitForCardStopAck.in [%s] %lu %lu\n",
stateName[korg1212->cardState], jiffies, korg1212->inIRQ);
-#endif
+ if (! korg1212->stop_pending_cnt) {
+ writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
+ /* program the timer */
+ korg1212->stop_pending_cnt = HZ;
+ korg1212->timer.expires = jiffies + 1;
+ add_timer(&korg1212->timer);
+ }
+}
- if (korg1212->inIRQ)
- return;
+static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&korg1212->lock, flags);
+ snd_korg1212_SendStop(korg1212);
+ spin_unlock_irqrestore(&korg1212->lock, flags);
+ sleep_on_timeout(&korg1212->wait, (HZ * 3) / 2);
+}
- do {
- if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: WaitForCardStopAck.out [%s]
%lu %lu\n", stateName[korg1212->cardState], jiffies, korg1212->inIRQ);
+/* timer callback for checking the ack of stop request */
+static void snd_korg1212_timer_func(unsigned long data)
+{
+ korg1212_t *korg1212 = snd_magic_cast(korg1212_t, (void*)data, return);
+
+ spin_lock(&korg1212->lock);
+ if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
+ /* ack'ed */
+ korg1212->stop_pending_cnt = 0;
+ wake_up(&korg1212->wait);
+#if K1212_DEBUG_LEVEL > 1
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n",
stateName[korg1212->cardState]);
#endif
- return;
- }
- if (!korg1212->inIRQ)
- schedule();
- } while (time_before(jiffies, endtime));
-
+ } else {
+ if (--korg1212->stop_pending_cnt > 0) {
+ /* reprogram timer */
+ korg1212->timer.expires = jiffies + 1;
+ add_timer(&korg1212->timer);
+ } else {
+ snd_printd("korg1212_timer_func timeout\n");
+ writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ wake_up(&korg1212->wait);
#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: WaitForCardStopAck.out TO [%s] %lu %lu\n",
stateName[korg1212->cardState], jiffies, korg1212->inIRQ);
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n",
stateName[korg1212->cardState]);
#endif
- writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ }
+ }
+ spin_unlock(&korg1212->lock);
}
static void snd_korg1212_TurnOnIdleMonitor(korg1212_t *korg1212)
{
+ unsigned long flags;
+
udelay(INTERCOMMAND_DELAY);
+ spin_lock_irqsave(&korg1212->lock, flags);
korg1212->idleMonitorOn = 1;
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
- K1212_MODE_MonitorOn, 0, 0, 0);
+ K1212_MODE_MonitorOn, 0, 0, 0);
+ spin_unlock_irqrestore(&korg1212->lock, flags);
}
static void snd_korg1212_TurnOffIdleMonitor(korg1212_t *korg1212)
{
if (korg1212->idleMonitorOn) {
- writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
- snd_korg1212_WaitForCardStopAck(korg1212);
+ snd_korg1212_SendStopAndWait(korg1212);
korg1212->idleMonitorOn = 0;
}
}
-static void snd_korg1212_setCardState(korg1212_t * korg1212, CardState csState)
+static inline void snd_korg1212_setCardState(korg1212_t * korg1212, CardState csState)
{
- switch (csState) {
- case K1212_STATE_READY:
- snd_korg1212_TurnOnIdleMonitor(korg1212);
- break;
-
- case K1212_STATE_OPEN:
- snd_korg1212_TurnOffIdleMonitor(korg1212);
- break;
-
- default:
- break;
- }
-
korg1212->cardState = csState;
}
@@ -670,8 +687,13 @@
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n",
stateName[korg1212->cardState], korg1212->opencnt);
#endif
- if (korg1212->opencnt++ == 0)
+ down(&korg1212->open_mutex);
+ if (korg1212->opencnt++ == 0) {
+ snd_korg1212_TurnOffIdleMonitor(korg1212);
snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
+ }
+
+ up(&korg1212->open_mutex);
return 1;
}
@@ -681,8 +703,11 @@
K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n",
stateName[korg1212->cardState], korg1212->opencnt);
#endif
- if (--(korg1212->opencnt))
+ down(&korg1212->open_mutex);
+ if (--(korg1212->opencnt)) {
+ up(&korg1212->open_mutex);
return 0;
+ }
if (korg1212->cardState == K1212_STATE_SETUP) {
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
@@ -691,19 +716,24 @@
if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", rc,
stateName[korg1212->cardState]);
#endif
- if (rc != K1212_CMDRET_Success)
+ if (rc != K1212_CMDRET_Success) {
+ up(&korg1212->open_mutex);
return 0;
+ }
} else if (korg1212->cardState > K1212_STATE_SETUP) {
- writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
- snd_korg1212_WaitForCardStopAck(korg1212);
+ snd_korg1212_SendStopAndWait(korg1212);
}
- if (korg1212->cardState > K1212_STATE_READY)
+ if (korg1212->cardState > K1212_STATE_READY) {
+ snd_korg1212_TurnOnIdleMonitor(korg1212);
snd_korg1212_setCardState(korg1212, K1212_STATE_READY);
+ }
+ up(&korg1212->open_mutex);
return 0;
}
+/* spinlock already held */
static int snd_korg1212_SetupForPlay(korg1212_t * korg1212)
{
#if K1212_DEBUG_LEVEL > 0
@@ -726,6 +756,7 @@
return 0;
}
+/* spinlock already held */
static int snd_korg1212_TriggerPlay(korg1212_t * korg1212)
{
#if K1212_DEBUG_LEVEL > 0
@@ -748,6 +779,7 @@
return 0;
}
+/* spinlock already held */
static int snd_korg1212_StopPlay(korg1212_t * korg1212)
{
#if K1212_DEBUG_LEVEL > 0
@@ -759,11 +791,10 @@
korg1212->setcnt = 0;
- if (korg1212->cardState != K1212_STATE_ERRORSTOP) {
- writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
- snd_korg1212_WaitForCardStopAck(korg1212);
- }
- snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
+ if (korg1212->cardState != K1212_STATE_ERRORSTOP)
+ snd_korg1212_SendStop(korg1212);
+
+ snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
return 0;
}
@@ -789,8 +820,7 @@
if (korg1212->cardState != K1212_STATE_MONITOR) {
return 0;
} else {
- writel(0xffffffff,
&korg1212->sharedBufferPtr->cardCommand);
- snd_korg1212_WaitForCardStopAck(korg1212);
+ snd_korg1212_SendStopAndWait(korg1212);
snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
}
break;
@@ -884,6 +914,7 @@
u16 controlValue; // this keeps the current value to be written to
// the card's eeprom control register.
u16 count;
+ unsigned long flags;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n",
stateName[korg1212->cardState]);
@@ -900,12 +931,13 @@
// make sure the card is not in monitor mode when we do this update.
//
----------------------------------------------------------------------------
if (korg1212->cardState == K1212_STATE_MONITOR || korg1212->idleMonitorOn) {
- writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
monModeSet = 1;
- snd_korg1212_WaitForCardStopAck(korg1212);
+ snd_korg1212_SendStopAndWait(korg1212);
} else
monModeSet = 0;
+ spin_lock_irqsave(&korg1212->lock, flags);
+
//
----------------------------------------------------------------------------
// we are about to send new values to the card, so clear the new values queued
// flag. Also, clear out mailbox 3, so we don't lockup.
@@ -1016,6 +1048,8 @@
}
+ spin_unlock_irqrestore(&korg1212->lock, flags);
+
return 1;
}
@@ -1089,13 +1123,14 @@
if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d
[%s]\n", rc, stateName[korg1212->cardState]);
#endif
+ snd_korg1212_TurnOnIdleMonitor(korg1212);
snd_korg1212_setCardState(korg1212, K1212_STATE_READY);
#if K1212_DEBUG_LEVEL > 0
if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n", rc,
stateName[korg1212->cardState]);
#endif
- wake_up_interruptible(&korg1212->wait);
+ snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE);
}
static void snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -1111,6 +1146,8 @@
if (!doorbellValue)
return;
+ spin_lock(&korg1212->lock);
+
writel(doorbellValue, korg1212->inDoorbellPtr);
korg1212->irqcount++;
@@ -1123,10 +1160,8 @@
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x,
[%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
#endif
- if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) {
- snd_korg1212_setCardState(korg1212,
K1212_STATE_DSP_COMPLETE);
- snd_korg1212_OnDSPDownloadComplete(korg1212);
- }
+ if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS)
+ wake_up(&korg1212->wait);
break;
//
------------------------------------------------------------------------
@@ -1166,17 +1201,23 @@
break;
if (korg1212->capture_substream) {
+ spin_unlock(&korg1212->lock);
snd_pcm_period_elapsed(korg1212->capture_substream);
+ spin_lock(&korg1212->lock);
}
if (korg1212->playback_substream) {
+ spin_unlock(&korg1212->lock);
snd_pcm_period_elapsed(korg1212->playback_substream);
+ spin_lock(&korg1212->lock);
}
}
break;
}
korg1212->inIRQ--;
+
+ spin_unlock(&korg1212->lock);
}
static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
@@ -1205,7 +1246,10 @@
if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n",
rc, stateName[korg1212->cardState]);
#endif
- interruptible_sleep_on_timeout(&korg1212->wait, HZ * 4);
+ if (! sleep_on_timeout(&korg1212->wait, HZ * 4))
+ return -EBUSY; /* timeout */
+
+ snd_korg1212_OnDSPDownloadComplete(korg1212);
return 0;
}
@@ -1363,14 +1407,14 @@
snd_pcm_set_sync(substream); // ???
- spin_lock_irqsave(&korg1212->lock, flags);
-
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_playback_info;
runtime->dma_area = (char *) korg1212->playDataBufsPtr;
runtime->dma_bytes = K1212_BUF_SIZE;
+ spin_lock_irqsave(&korg1212->lock, flags);
+
korg1212->playback_substream = substream;
korg1212->periodsize = K1212_PERIODS;
korg1212->channels = K1212_CHANNELS;
@@ -1394,14 +1438,14 @@
snd_pcm_set_sync(substream); // ???
- spin_lock_irqsave(&korg1212->lock, flags);
-
snd_korg1212_OpenCard(korg1212);
runtime->hw = snd_korg1212_capture_info;
runtime->dma_area = (char *) korg1212->recordDataBufsPtr;
runtime->dma_bytes = K1212_BUF_SIZE;
+ spin_lock_irqsave(&korg1212->lock, flags);
+
korg1212->capture_substream = substream;
korg1212->periodsize = K1212_PERIODS;
korg1212->channels = K1212_CHANNELS;
@@ -1428,9 +1472,9 @@
korg1212->playback_substream = NULL;
korg1212->periodsize = 0;
- snd_korg1212_CloseCard(korg1212);
-
spin_unlock_irqrestore(&korg1212->lock, flags);
+
+ snd_korg1212_CloseCard(korg1212);
return 0;
}
@@ -1448,9 +1492,9 @@
korg1212->capture_substream = NULL;
korg1212->periodsize = 0;
- snd_korg1212_CloseCard(korg1212);
-
spin_unlock_irqrestore(&korg1212->lock, flags);
+
+ snd_korg1212_CloseCard(korg1212);
return 0;
}
@@ -1508,19 +1552,33 @@
static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
{
korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
- unsigned long flags;
int rc;
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n",
stateName[korg1212->cardState]);
#endif
- spin_lock_irqsave(&korg1212->lock, flags);
+ spin_lock(&korg1212->lock);
+
+ /* FIXME: we should wait for ack! */
+ if (korg1212->stop_pending_cnt > 0) {
+#if K1212_DEBUG_LEVEL > 0
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is
pending... [%s]\n", stateName[korg1212->cardState]);
+#endif
+ spin_unlock(&korg1212->lock);
+ return -EAGAIN;
+ /*
+ writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ del_timer(&korg1212->timer);
+ korg1212->stop_pending_cnt = 0;
+ */
+ }
rc = snd_korg1212_SetupForPlay(korg1212);
+
korg1212->currentBuffer = 0;
- spin_unlock_irqrestore(&korg1212->lock, flags);
+ spin_unlock(&korg1212->lock);
return rc ? -EINVAL : 0;
}
@@ -1535,6 +1593,7 @@
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n",
stateName[korg1212->cardState], cmd);
#endif
+ spin_lock(&korg1212->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
/*
@@ -1566,6 +1625,7 @@
rc = 1;
break;
}
+ spin_unlock(&korg1212->lock);
return rc ? -EINVAL : 0;
}
@@ -1894,11 +1954,11 @@
change = 1;
}
+ spin_unlock_irqrestore(&korg1212->lock, flags);
+
if (change)
snd_korg1212_WriteADCSensitivity(korg1212);
- spin_unlock_irqrestore(&korg1212->lock, flags);
-
return change;
}
@@ -2151,6 +2211,10 @@
init_waitqueue_head(&korg1212->wait);
spin_lock_init(&korg1212->lock);
+ init_MUTEX(&korg1212->open_mutex);
+ init_timer(&korg1212->timer);
+ korg1212->timer.function = snd_korg1212_timer_func;
+ korg1212->timer.data = (unsigned long)korg1212;
korg1212->irq = -1;
korg1212->clkSource = K1212_CLKIDX_Local;
-------------------------------------------------------
This SF.net email is sponsored by:
The Definitive IT and Networking Event. Be There!
NetWorld+Interop Las Vegas 2003 -- Register today!
http://ads.sourceforge.net/cgi-bin/redirect.pl?keyn0001en
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog