Staging: poch: Fetch Flush IOCTL interface
authorVijay Kumar B <vijaykumar@bravegnu.org>
Mon, 21 Sep 2009 05:53:55 +0000 (11:23 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Dec 2009 20:23:09 +0000 (12:23 -0800)
Change user space interface to an IOCTL based interface instead of a
memory mapped circular buffer. The circular buffer had some serious
cache(?) issues and never worked.

Signed-off-by: Vijay Kumar B. <vijaykumar@bravegnu.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/poch/poch.c
drivers/staging/poch/poch.h

index 1308c7bada8a32654663191dd39107b84ba61082..6b4aa5f1d51da4a1cd51349fecab4ef5bba574e5 100644 (file)
@@ -201,6 +201,8 @@ struct channel_info {
        struct page *header_pg;
        unsigned long header_size;
 
+       /* Last group consumed by user space. */
+       unsigned int consumed;
        /* Last group indicated as 'complete' to user space. */
        unsigned int transfer;
 
@@ -589,6 +591,7 @@ static int poch_channel_init(struct channel_info *channel,
        if (ret != 0)
                goto out;
 
+       channel->consumed = 0;
        channel->transfer = 0;
 
        /* Allocate memory to hold group information. */
@@ -1033,6 +1036,51 @@ static int poch_ioctl(struct inode *inode, struct file *filp,
                        break;
                }
                break;
+       case POCH_IOC_CONSUME:
+       {
+               int available;
+               int nfetch;
+               unsigned int from;
+               unsigned int count;
+               unsigned int i, j;
+               struct poch_consume consume;
+               struct poch_consume *uconsume;
+
+               uconsume = argp;
+               ret = copy_from_user(&consume, uconsume, sizeof(consume));
+               if (ret)
+                       return ret;
+
+               spin_lock_irq(&channel->group_offsets_lock);
+
+               channel->consumed += consume.nflush;
+               channel->consumed %= channel->group_count;
+
+               available = channel->transfer - channel->consumed;
+               if (available < 0)
+                       available += channel->group_count;
+
+               from = channel->consumed;
+
+               spin_unlock_irq(&channel->group_offsets_lock);
+
+               nfetch = consume.nfetch;
+               count = min(available, nfetch);
+
+               for (i = 0; i < count; i++) {
+                       j = (from + i) % channel->group_count;
+                       ret = put_user(channel->groups[j].user_offset,
+                                      &consume.offsets[i]);
+                       if (ret)
+                               return -EFAULT;
+               }
+
+               ret = put_user(count, &uconsume->nfetch);
+               if (ret)
+                       return -EFAULT;
+
+               break;
+       }
        case POCH_IOC_GET_COUNTERS:
                if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))
                        return -EFAULT;
@@ -1108,12 +1156,18 @@ static void poch_irq_dma(struct channel_info *channel)
        for (i = 0; i < groups_done; i++) {
                j = (prev_transfer + i) % channel->group_count;
                group_offsets[j] = groups[j].user_offset;
+
+               channel->transfer += 1;
+               channel->transfer %= channel->group_count;
+
+               if (channel->transfer == channel->consumed) {
+                       channel->consumed += 1;
+                       channel->consumed %= channel->group_count;
+               }
        }
 
        spin_unlock(&channel->group_offsets_lock);
 
-       channel->transfer = curr_transfer;
-
        wake_up_interruptible(&channel->wq);
 }
 
index 51a2d145798efbf600826eec6064d7c42129d375..ba1490b4252bfb4d1548066ac9cd25aaf20cfcd5 100644 (file)
@@ -19,6 +19,12 @@ struct poch_counters {
        __u32 pll_unlock;
 };
 
+struct poch_consume {
+       __u32 __user *offsets;
+       __u32 nfetch;
+       __u32 nflush;
+};
+
 #define POCH_IOC_NUM                   '9'
 
 #define POCH_IOC_TRANSFER_START                _IO(POCH_IOC_NUM, 0)
@@ -27,3 +33,6 @@ struct poch_counters {
                                             struct poch_counters)
 #define POCH_IOC_SYNC_GROUP_FOR_USER   _IO(POCH_IOC_NUM, 3)
 #define POCH_IOC_SYNC_GROUP_FOR_DEVICE _IO(POCH_IOC_NUM, 4)
+
+#define POCH_IOC_CONSUME               _IOWR(POCH_IOC_NUM, 5, \
+                                             struct poch_consume)