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