]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/plat-omap/dsp/task.c
DSPGW: Use kfifo APIs instead of homemade ones
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / task.c
index b43f70409928bfe063dcc97bc220da88fd5c4c70..0e2b5c78048ba8fcda3fa0a34910a8cedddbea5f 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/interrupt.h>
+#include <linux/kfifo.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/arch/mailbox.h>
@@ -41,7 +42,6 @@
 #include "dsp_mbcmd.h"
 #include "dsp.h"
 #include "ipbuf.h"
-#include "fifo.h"
 #include "proclist.h"
 
 #define is_aligned(adr,align)  (!((adr)&((align)-1)))
@@ -125,8 +125,9 @@ struct taskdev {
        /* read stuff */
        wait_queue_head_t read_wait_q;
        struct mutex read_mutex;
+       spinlock_t read_lock;
        union {
-               struct fifo_struct fifo;        /* for active word */
+               struct kfifo *fifo;     /* for active word */
                struct rcvdt_bk_struct bk;
        } rcvdt;
 
@@ -356,7 +357,7 @@ static int taskdev_flush_buf(struct taskdev *dev)
 
        if (sndtyp_wd(ttyp)) {
                /* word receiving */
-               flush_fifo(&dev->rcvdt.fifo);
+               kfifo_reset(dev->rcvdt.fifo);
        } else {
                /* block receiving */
                struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
@@ -379,7 +380,6 @@ static int taskdev_flush_buf(struct taskdev *dev)
 static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
 {
        u16 ttyp = dev->task->ttyp;
-       int stat;
 
        if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
                printk(KERN_ERR
@@ -393,15 +393,18 @@ static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
                return -EINVAL;
        }
 
-       stat = realloc_fifo(&dev->rcvdt.fifo, sz);
-       if (stat == -EBUSY) {
+       if (kfifo_len(dev->rcvdt.fifo)) {
                printk(KERN_ERR "omapdsp: buffer is not empty!\n");
-               return stat;
-       } else if (stat < 0) {
+               return -EIO;
+       }
+
+       kfifo_free(dev->rcvdt.fifo);
+       dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock);
+       if (IS_ERR(dev->rcvdt.fifo)) {
                printk(KERN_ERR
                       "omapdsp: unable to change receive buffer size. "
                       "(%ld bytes for %s)\n", sz, dev->name);
-               return stat;
+               return -ENOMEM;
        }
 
        return 0;
@@ -670,10 +673,10 @@ static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
 
 
        prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
-       if (fifo_empty(&dev->rcvdt.fifo))
+       if (kfifo_len(dev->rcvdt.fifo) == 0)
                schedule();
        finish_wait(&dev->read_wait_q, &wait);
-       if (fifo_empty(&dev->rcvdt.fifo)) {
+       if (kfifo_len(dev->rcvdt.fifo) == 0) {
                /* failure */
                if (signal_pending(current))
                        ret = -EINTR;
@@ -681,7 +684,7 @@ static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
        }
 
 
-       ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
+       ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 
  up_out:
        taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
@@ -837,14 +840,14 @@ static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
 
        mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
 
-       if (fifo_empty(&dev->rcvdt.fifo)) {
+       if (kfifo_len(dev->rcvdt.fifo) == 0) {
                /* failure */
                if (signal_pending(current))
                        ret = -EINTR;
                goto up_out;
        }
 
-       ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
+       ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
 
 up_out:
        taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
@@ -1125,7 +1128,7 @@ static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
        poll_wait(file, &dev->read_wait_q, wait);
        poll_wait(file, &dev->write_wait_q, wait);
        if (sndtyp_psv(task->ttyp) ||
-           (sndtyp_wd(task->ttyp) && !fifo_empty(&dev->rcvdt.fifo)) ||
+           (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) ||
            (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
                mask |= POLLIN | POLLRDNORM;
        if (dev->wsz)
@@ -1764,7 +1767,7 @@ static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
        task_dev = device_create(dsp_task_class, NULL,
                                 MKDEV(OMAP_DSP_TASK_MAJOR, minor),
                                 "dsptask%d", (int)minor);
-       
+
        if (unlikely(IS_ERR(task_dev))) {
                ret = -EINVAL;
                goto fail_create_taskclass;
@@ -1815,11 +1818,11 @@ static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
                /* sndtyp_bk */   dsp_task_read_bk_psv;
        if (sndtyp_wd(ttyp)) {
                /* word */
-               size_t fifosz;
+               size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */
 
-               fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
-                       32;     /* active */
-               if (init_fifo(&dev->rcvdt.fifo, fifosz) < 0) {
+               dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL,
+                                             &dev->read_lock);
+               if (IS_ERR(dev->rcvdt.fifo)) {
                        printk(KERN_ERR
                               "omapdsp: unable to allocate receive buffer. "
                               "(%d bytes for %s)\n", fifosz, dev->name);
@@ -1896,7 +1899,7 @@ static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
        taskdev_flush_buf(dev);
 
        if (sndtyp_wd(ttyp))
-               free_fifo(&dev->rcvdt.fifo);
+               kfifo_free(dev->rcvdt.fifo);
 
        dev->task = NULL;
 
@@ -1923,7 +1926,7 @@ static void taskdev_detach_task(struct taskdev *dev)
        dev->fops.read = NULL;
        taskdev_flush_buf(dev);
        if (sndtyp_wd(ttyp))
-               free_fifo(&dev->rcvdt.fifo);
+               kfifo_free(dev->rcvdt.fifo);
 
        dev->fops.write = NULL;
        dev->wsz = 0;
@@ -2246,7 +2249,9 @@ long taskdev_state_stale(unsigned char minor)
  */
 void mbox_wdsnd(struct mbcmd *mb)
 {
+       unsigned int n;
        u8 tid = mb->cmd_l;
+       u16 data = mb->data;
        struct dsptask *task = dsptask[tid];
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
@@ -2266,7 +2271,11 @@ void mbox_wdsnd(struct mbcmd *mb)
                return;
        }
 
-       write_word_to_fifo(&task->dev->rcvdt.fifo, mb->data);
+       n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data,
+                     sizeof(data));
+       if (n != sizeof(data))
+               printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid);
+
        wake_up_interruptible(&task->dev->read_wait_q);
 }
 
@@ -2883,8 +2892,8 @@ static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
 static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
                           char *buf)
 {
-       struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
-       return sprintf(buf, "%d\n", fifo->sz);
+       struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
+       return sprintf(buf, "%d\n", fifo->size);
 }
 
 static int fifosz_store(struct device *d, struct device_attribute *attr,
@@ -2895,7 +2904,10 @@ static int fifosz_store(struct device *d, struct device_attribute *attr,
        int ret;
 
        fifosz = simple_strtol(buf, NULL, 10);
+       if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+               return -ENODEV;
        ret = taskdev_set_fifosz(dev, fifosz);
+       taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
 
        return (ret < 0) ? ret : strlen(buf);
 }
@@ -2904,8 +2916,8 @@ static int fifosz_store(struct device *d, struct device_attribute *attr,
 static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
-       struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
-       return sprintf(buf, "%d\n", fifo->cnt);
+       struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
+       return sprintf(buf, "%d\n", fifo->size);
 }
 
 /* ipblink */