From d3a7dcfeeb6856215412065bd0f774de83f43414 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 17 Sep 2009 18:46:26 +0200 Subject: ALSA: pcm - Simplify snd_pcm_drain() implementation Simplify snd_pcm_drain() implementation and avoid unneeded array- allocation for waitqueues. Instead, one waitqueue is used for the first draining stream, and wait until all streams finished. Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 73 ++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59e5fbe6af5..561d6d95a2d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1387,11 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = { .post_action = snd_pcm_post_drain_init }; -struct drain_rec { - struct snd_pcm_substream *substream; - wait_queue_t wait; -}; - static int snd_pcm_drop(struct snd_pcm_substream *substream); /* @@ -1407,10 +1402,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, struct snd_card *card; struct snd_pcm_runtime *runtime; struct snd_pcm_substream *s; + wait_queue_t wait; int result = 0; - int i, num_drecs; int nonblock = 0; - struct drain_rec *drec, drec_tmp, *d; card = substream->pcm->card; runtime = substream->runtime; @@ -1433,38 +1427,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, } else if (substream->f_flags & O_NONBLOCK) nonblock = 1; - if (nonblock) - goto lock; /* no need to allocate waitqueues */ - - /* allocate temporary record for drain sync */ down_read(&snd_pcm_link_rwsem); - if (snd_pcm_stream_linked(substream)) { - drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); - if (! drec) { - up_read(&snd_pcm_link_rwsem); - snd_power_unlock(card); - return -ENOMEM; - } - } else - drec = &drec_tmp; - - /* count only playback streams */ - num_drecs = 0; - snd_pcm_group_for_each_entry(s, substream) { - runtime = s->runtime; - if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { - d = &drec[num_drecs++]; - d->substream = s; - init_waitqueue_entry(&d->wait, current); - add_wait_queue(&runtime->sleep, &d->wait); - } - } - up_read(&snd_pcm_link_rwsem); - - lock: snd_pcm_stream_lock_irq(substream); /* resume pause */ - if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) + if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) snd_pcm_pause(substream, 0); /* pre-start/stop - all running streams are changed to DRAINING state */ @@ -1479,25 +1445,35 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, for (;;) { long tout; + struct snd_pcm_runtime *to_check; if (signal_pending(current)) { result = -ERESTARTSYS; break; } - /* all finished? */ - for (i = 0; i < num_drecs; i++) { - runtime = drec[i].substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + /* find a substream to drain */ + to_check = NULL; + snd_pcm_group_for_each_entry(s, substream) { + if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) + continue; + runtime = s->runtime; + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + to_check = runtime; break; + } } - if (i == num_drecs) - break; /* yes, all drained */ - + if (!to_check) + break; /* all drained */ + init_waitqueue_entry(&wait, current); + add_wait_queue(&to_check->sleep, &wait); set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); + up_read(&snd_pcm_link_rwsem); snd_power_unlock(card); tout = schedule_timeout(10 * HZ); snd_power_lock(card); + down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); + remove_wait_queue(&to_check->sleep, &wait); if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -1512,16 +1488,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, unlock: snd_pcm_stream_unlock_irq(substream); - - if (!nonblock) { - for (i = 0; i < num_drecs; i++) { - d = &drec[i]; - runtime = d->substream->runtime; - remove_wait_queue(&runtime->sleep, &d->wait); - } - if (drec != &drec_tmp) - kfree(drec); - } + up_read(&snd_pcm_link_rwsem); snd_power_unlock(card); return result; -- cgit v1.2.3 From 95eff499c96ac728307fd34cbf1a28ea20a5b615 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Mon, 21 Sep 2009 15:00:22 +0200 Subject: ALSA: lx6464es - cleanup of rmh message bus function the rmh bus is not used asynchronously, so it is safe to remove the specific code pieces. Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx6464es.h | 1 - sound/pci/lx6464es/lx_core.c | 98 +------------------------------------------ 2 files changed, 1 insertion(+), 98 deletions(-) diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h index 012c010c8c8..16442dad58d 100644 --- a/sound/pci/lx6464es/lx6464es.h +++ b/sound/pci/lx6464es/lx6464es.h @@ -86,7 +86,6 @@ struct lx6464es { /* messaging */ spinlock_t msg_lock; /* message spinlock */ - atomic_t send_message_locked; struct lx_rmh rmh; /* configuration */ diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 5812780d6e8..3086b751da4 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -314,98 +314,6 @@ static inline void lx_message_dump(struct lx_rmh *rmh) #define XILINX_POLL_NO_SLEEP 100 #define XILINX_POLL_ITERATIONS 150 -#if 0 /* not used now */ -static int lx_message_send(struct lx6464es *chip, struct lx_rmh *rmh) -{ - u32 reg = ED_DSP_TIMED_OUT; - int dwloop; - int answer_received; - - if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) { - snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg); - return -EBUSY; - } - - /* write command */ - lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len); - - snd_BUG_ON(atomic_read(&chip->send_message_locked) != 0); - atomic_set(&chip->send_message_locked, 1); - - /* MicoBlaze gogogo */ - lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); - - /* wait for interrupt to answer */ - for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS; ++dwloop) { - answer_received = atomic_read(&chip->send_message_locked); - if (answer_received == 0) - break; - msleep(1); - } - - if (answer_received == 0) { - /* in Debug mode verify Reg_CSM_MR */ - snd_BUG_ON(!(lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)); - - /* command finished, read status */ - if (rmh->dsp_stat == 0) - reg = lx_dsp_reg_read(chip, eReg_CRM1); - else - reg = 0; - } else { - int i; - snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! " - "Interrupts disabled?\n"); - - /* attente bit Reg_CSM_MR */ - for (i = 0; i != XILINX_POLL_ITERATIONS; i++) { - if ((lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)) { - if (rmh->dsp_stat == 0) - reg = lx_dsp_reg_read(chip, eReg_CRM1); - else - reg = 0; - goto polling_successful; - } - - if (i > XILINX_POLL_NO_SLEEP) - msleep(1); - } - snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! " - "polling failed\n"); - -polling_successful: - atomic_set(&chip->send_message_locked, 0); - } - - if ((reg & ERROR_VALUE) == 0) { - /* read response */ - if (rmh->stat_len) { - snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1)); - - lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat, - rmh->stat_len); - } - } else - snd_printk(KERN_WARNING LXP "lx_message_send: error_value %x\n", - reg); - - /* clear Reg_CSM_MR */ - lx_dsp_reg_write(chip, eReg_CSM, 0); - - switch (reg) { - case ED_DSP_TIMED_OUT: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n"); - return -ETIMEDOUT; - - case ED_DSP_CRASHED: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n"); - return -EAGAIN; - } - - lx_message_dump(rmh); - return 0; -} -#endif /* not used now */ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) { @@ -423,7 +331,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) /* MicoBlaze gogogo */ lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); - /* wait for interrupt to answer */ + /* wait for device to answer */ for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) { if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) { if (rmh->dsp_stat == 0) @@ -1175,10 +1083,6 @@ static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc, *r_async_escmd = 1; } - if (irqsrc & MASK_SYS_STATUS_CMD_DONE) - /* xilinx command notification */ - atomic_set(&chip->send_message_locked, 0); - if (irq_async) { /* snd_printd("interrupt: async event pending\n"); */ *r_async_pending = 1; -- cgit v1.2.3 From 8fdc9e870c07054bc34a62a4655cdb078953255d Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Mon, 21 Sep 2009 15:00:57 +0200 Subject: ALSA: lx6464es - remove unused struct member we cannot set the sampling rate of the device, but can only read it from the board, so we don't need the member for it. Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx6464es.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h index 16442dad58d..51afc048961 100644 --- a/sound/pci/lx6464es/lx6464es.h +++ b/sound/pci/lx6464es/lx6464es.h @@ -94,7 +94,6 @@ struct lx6464es { uint hardware_running[2]; u32 board_sample_rate; /* sample rate read from * board */ - u32 sample_rate; /* our sample rate */ u16 pcm_granularity; /* board blocksize */ /* dma */ -- cgit v1.2.3