From: Vladimir Barinov Date: Thu, 22 Sep 2005 21:03:22 +0000 (-0700) Subject: ARM: OMAP: audio driver: convert semaphores to completions X-Git-Tag: v2.6.15-omap2~202^2~1 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=96e5e362004eaba40e1cc4497475595736393463;p=linux-2.6-omap-h63xx.git ARM: OMAP: audio driver: convert semaphores to completions Signed-off-by: Vladimir Barinov Signed-off-by: Kevin Hilman --- diff --git a/sound/oss/omap-audio-dma-intfc.c b/sound/oss/omap-audio-dma-intfc.c index 6ccab9a5af3..f5e324e5ada 100644 --- a/sound/oss/omap-audio-dma-intfc.c +++ b/sound/oss/omap-audio-dma-intfc.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -210,7 +211,8 @@ int audio_setup_buf(audio_stream_t * s) s->started = 0; s->bytecount = 0; s->fragcount = 0; - sema_init(&s->sem, s->nbfrags); + init_completion(&s->wfc); + s->wfc.done = s->nbfrags; FN_OUT(0); return 0; err: @@ -469,7 +471,9 @@ void audio_prime_rx(audio_state_t * state) audio_process_dma(state->output_stream); } is->pending_frags = is->nbfrags; - sema_init(&is->sem, 0); + init_completion(&is->wfc); + is->wfc.done = 0; + is->active = 1; audio_process_dma(is); @@ -535,7 +539,9 @@ int audio_sync(struct file *file) */ b = &s->buffers[s->usr_head]; if (b->offset &= ~3) { - down(&s->sem); + /* Wait for a buffer to become free */ + if (wait_for_completion_interruptible(&s->wfc)) + return 0; /* * HACK ALERT ! * To avoid increased complexity in the rest of the code @@ -568,7 +574,7 @@ int audio_sync(struct file *file) /* Let's wait for all buffers to complete */ set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&s->wq, &wait); - while ((s->pending_frags || (atomic_read(&s->sem.count) < s->nbfrags)) + while ((s->pending_frags || (s->wfc.done < s->nbfrags)) && !signal_pending(current)) { schedule(); set_current_state(TASK_INTERRUPTIBLE); @@ -652,7 +658,8 @@ void audio_reset(audio_stream_t * s) s->buffers[s->usr_head].offset = 0; s->usr_head = s->dma_head; s->pending_frags = 0; - sema_init(&s->sem, s->nbfrags); + init_completion(&s->wfc); + s->wfc.done = s->nbfrags; } s->active = 0; s->stopped = 0; @@ -864,7 +871,6 @@ static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status, void *data) tasklet_schedule(&audio_isr_work2); work_item_running = 0; } - FN_OUT(0); return; } @@ -893,14 +899,13 @@ static void audio_dma_callback(int lch, u16 ch_status, void *data) s->dma_tail = 0; if (!s->mapped) - up(&s->sem); + complete(&s->wfc); else s->pending_frags++; wake_up(&s->wq); } - audio_process_dma(s); FN_OUT(0); return; diff --git a/sound/oss/omap-audio.c b/sound/oss/omap-audio.c index bd10ae6a3d4..afcf98d8600 100644 --- a/sound/oss/omap-audio.c +++ b/sound/oss/omap-audio.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -442,6 +443,7 @@ int audio_register_codec(audio_state_t * codec_state) } memcpy(&audio_state, codec_state, sizeof(audio_state_t)); + sema_init(&audio_state.sem, 1); ret = platform_device_register(&omap_audio_device); if (ret != 0) { @@ -531,13 +533,12 @@ audio_write(struct file *file, const char __user *buffer, /* Wait for a buffer to become free */ if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; - if (down_trylock(&s->sem)) - break; - } else { - ret = -ERESTARTSYS; - if (down_interruptible(&s->sem)) + if (!s->wfc.done) break; } + ret = -ERESTARTSYS; + if (wait_for_completion_interruptible(&s->wfc)) + break; /* Feed the current buffer */ chunksize = s->fragsize - b->offset; @@ -546,7 +547,7 @@ audio_write(struct file *file, const char __user *buffer, DPRINTK("write %d to %d\n", chunksize, s->usr_head); if (copy_from_user(b->data + b->offset, buffer, chunksize)) { printk(KERN_ERR "Audio: CopyFrom User failed \n"); - up(&s->sem); + complete(&s->wfc); return -EFAULT; } @@ -555,7 +556,7 @@ audio_write(struct file *file, const char __user *buffer, b->offset += chunksize; if (b->offset < s->fragsize) { - up(&s->sem); + complete(&s->wfc); break; } @@ -617,13 +618,12 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) /* Wait for a buffer to become full */ if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; - if (down_trylock(&s->sem)) - break; - } else { - ret = -ERESTARTSYS; - if (down_interruptible(&s->sem)) + if (!s->wfc.done) break; } + ret = -ERESTARTSYS; + if (wait_for_completion_interruptible(&s->wfc)) + break; /* Grab data from the current buffer */ chunksize = s->fragsize - b->offset; @@ -631,14 +631,14 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) chunksize = count; DPRINTK("read %d from %d\n", chunksize, s->usr_head); if (copy_to_user(buffer, b->data + b->offset, chunksize)) { - up(&s->sem); + complete(&s->wfc); return -EFAULT; } buffer += chunksize; count -= chunksize; b->offset += chunksize; if (b->offset < s->fragsize) { - up(&s->sem); + complete(&s->wfc); break; } @@ -748,12 +748,12 @@ audio_poll(struct file *file, struct poll_table_struct *wait) if (file->f_mode & FMODE_READ) if ((is->mapped && is->bytecount > 0) || - (!is->mapped && atomic_read(&is->sem.count) > 0)) + (!is->mapped && is->wfc.done > 0)) mask |= POLLIN | POLLRDNORM; if (file->f_mode & FMODE_WRITE) if ((os->mapped && os->bytecount > 0) || - (!os->mapped && atomic_read(&os->sem.count) > 0)) + (!os->mapped && os->wfc.done > 0)) mask |= POLLOUT | POLLWRNORM; DPRINTK("audio_poll() returned mask of %s%s\n", @@ -897,7 +897,8 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) local_irq_save(flags); if (os->mapped && !os->pending_frags) { os->pending_frags = os->nbfrags; - sema_init(&os->sem, 0); + init_completion(&os->wfc); + os->wfc.done = 0; os->active = 1; } os->stopped = 0; @@ -958,7 +959,7 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) FN_OUT(19); return -ENOMEM; } - inf.bytes = atomic_read(&s->sem.count) * s->fragsize; + inf.bytes = s->wfc.done * s->fragsize; inf.fragments = inf.bytes / s->fragsize; inf.fragsize = s->fragsize; diff --git a/sound/oss/omap-audio.h b/sound/oss/omap-audio.h index 42adef8bcf6..d3cc11b456f 100644 --- a/sound/oss/omap-audio.h +++ b/sound/oss/omap-audio.h @@ -67,7 +67,7 @@ typedef struct { int input_or_output; /* Direction of this data stream */ int bytecount; /* nbr of processed bytes */ int fragcount; /* nbr of fragment transitions */ - struct semaphore sem; /* account for fragment usage */ + struct completion wfc; /* wait for "nbfrags" fragment completion */ wait_queue_head_t wq; /* for poll */ int dma_spinref; /* DMA is spinning */ unsigned mapped:1; /* mmap()'ed buffers */