From: Hiroshi DOYU Date: Mon, 30 Jul 2007 11:04:02 +0000 (+0300) Subject: DSPGW: Use kfifo APIs instead of homemade ones X-Git-Tag: v2.6.23-omap1~274 X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=024765d0d2d63dee04b319d497e30cc7e54535b9;p=linux-2.6-omap-h63xx.git DSPGW: Use kfifo APIs instead of homemade ones Signed-off-by: Hiroshi DOYU Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/plat-omap/dsp/fifo.h b/arch/arm/plat-omap/dsp/fifo.h deleted file mode 100644 index c0dc26c81d6..00000000000 --- a/arch/arm/plat-omap/dsp/fifo.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __PLAT_OMAP_DSP_FIFO_H -#define __PLAT_OMAP_DSP_FIFO_H - -struct fifo_struct { - spinlock_t lock; - char *buf; - size_t sz; - size_t cnt; - unsigned int wp; -}; - -static inline int alloc_fifo(struct fifo_struct *fifo, size_t sz) -{ - if ((fifo->buf = kmalloc(sz, GFP_KERNEL)) == NULL) { - fifo->sz = 0; - return -ENOMEM; - } - fifo->sz = sz; - fifo->cnt = 0; - fifo->wp = 0; - return 0; -} - -static inline int init_fifo(struct fifo_struct *fifo, size_t sz) -{ - spin_lock_init(&fifo->lock); - return alloc_fifo(fifo, sz); -} - -static inline void free_fifo(struct fifo_struct *fifo) -{ - spin_lock(&fifo->lock); - if (fifo->buf == NULL) { - spin_unlock(&fifo->lock); - return; - } - - kfree(fifo->buf); - fifo->buf = NULL; - fifo->sz = 0; - spin_unlock(&fifo->lock); -} - -static inline void flush_fifo(struct fifo_struct *fifo) -{ - spin_lock(&fifo->lock); - fifo->cnt = 0; - fifo->wp = 0; - spin_unlock(&fifo->lock); -} - -#define fifo_empty(fifo) ((fifo)->cnt == 0) - -static inline int realloc_fifo(struct fifo_struct *fifo, size_t sz) -{ - int ret = sz; - - spin_lock(&fifo->lock); - if (!fifo_empty(fifo)) { - ret = -EBUSY; - goto out; - } - - /* free */ - if (fifo->buf) - kfree(fifo->buf); - - /* alloc */ - ret = alloc_fifo(fifo, sz); - -out: - spin_unlock(&fifo->lock); - return ret; -} - -static inline void write_word_to_fifo(struct fifo_struct *fifo, u16 word) -{ - spin_lock(&fifo->lock); - *(u16 *)&fifo->buf[fifo->wp] = word; - if ((fifo->wp += 2) == fifo->sz) - fifo->wp = 0; - if ((fifo->cnt += 2) > fifo->sz) - fifo->cnt = fifo->sz; - spin_unlock(&fifo->lock); -} - -/* - * (before) - * - * [*******----------*************] - * ^wp - * <----------------------------> sz = 30 - * <-----> <-----------> cnt = 20 - * - * (read: count=16) - * <-> <-----------> count = 16 - * <-----------> cnt1 = 13 - * ^rp - * - * (after) - * [---****-----------------------] - * ^wp - */ -static inline ssize_t copy_to_user_fm_fifo(char *dst, struct fifo_struct *fifo, - size_t count) -{ - int rp; - ssize_t ret; - - /* fifo size can be zero */ - if (fifo->sz == 0) - return 0; - - spin_lock(&fifo->lock); - if (count > fifo->cnt) - count = fifo->cnt; - - if ((rp = fifo->wp - fifo->cnt) >= 0) { - /* valid area is straight */ - if (copy_to_user(dst, &fifo->buf[rp], count)) { - ret = -EFAULT; - goto out; - } - } else { - int cnt1 = -rp; - rp += fifo->sz; - if (cnt1 >= count) { - /* requested area is straight */ - if (copy_to_user(dst, &fifo->buf[rp], count)) { - ret = -EFAULT; - goto out; - } - } else { - if (copy_to_user(dst, &fifo->buf[rp], cnt1)) { - ret = -EFAULT; - goto out; - } - if (copy_to_user(dst+cnt1, fifo->buf, count-cnt1)) { - ret = -EFAULT; - goto out; - } - } - } - fifo->cnt -= count; - ret = count; - -out: - spin_unlock(&fifo->lock); - return ret; -} - -#endif /* __PLAT_OMAP_DSP_FIFO_H */ diff --git a/arch/arm/plat-omap/dsp/task.c b/arch/arm/plat-omap/dsp/task.c index b43f7040992..0e2b5c78048 100644 --- a/arch/arm/plat-omap/dsp/task.c +++ b/arch/arm/plat-omap/dsp/task.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -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 */