aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVijay Kumar B <vijaykumar@bravegnu.org>2009-09-21 01:53:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 15:23:09 -0500
commitb01faf05740884f915dd1b8652d8af1b6f458ccc (patch)
treeb6671d121618dbf9c20efe8c1b9e9ed7f6f56f08 /drivers
parent16fbf4cba0880c31445d6414abbd7a1c51466b1f (diff)
Staging: poch: Fetch Flush IOCTL interface
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/poch/poch.c58
-rw-r--r--drivers/staging/poch/poch.h9
2 files changed, 65 insertions, 2 deletions
diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c
index 1308c7bada8..6b4aa5f1d51 100644
--- a/drivers/staging/poch/poch.c
+++ b/drivers/staging/poch/poch.c
@@ -201,6 +201,8 @@ struct channel_info {
201 struct page *header_pg; 201 struct page *header_pg;
202 unsigned long header_size; 202 unsigned long header_size;
203 203
204 /* Last group consumed by user space. */
205 unsigned int consumed;
204 /* Last group indicated as 'complete' to user space. */ 206 /* Last group indicated as 'complete' to user space. */
205 unsigned int transfer; 207 unsigned int transfer;
206 208
@@ -589,6 +591,7 @@ static int poch_channel_init(struct channel_info *channel,
589 if (ret != 0) 591 if (ret != 0)
590 goto out; 592 goto out;
591 593
594 channel->consumed = 0;
592 channel->transfer = 0; 595 channel->transfer = 0;
593 596
594 /* Allocate memory to hold group information. */ 597 /* Allocate memory to hold group information. */
@@ -1033,6 +1036,51 @@ static int poch_ioctl(struct inode *inode, struct file *filp,
1033 break; 1036 break;
1034 } 1037 }
1035 break; 1038 break;
1039 case POCH_IOC_CONSUME:
1040 {
1041 int available;
1042 int nfetch;
1043 unsigned int from;
1044 unsigned int count;
1045 unsigned int i, j;
1046 struct poch_consume consume;
1047 struct poch_consume *uconsume;
1048
1049 uconsume = argp;
1050 ret = copy_from_user(&consume, uconsume, sizeof(consume));
1051 if (ret)
1052 return ret;
1053
1054 spin_lock_irq(&channel->group_offsets_lock);
1055
1056 channel->consumed += consume.nflush;
1057 channel->consumed %= channel->group_count;
1058
1059 available = channel->transfer - channel->consumed;
1060 if (available < 0)
1061 available += channel->group_count;
1062
1063 from = channel->consumed;
1064
1065 spin_unlock_irq(&channel->group_offsets_lock);
1066
1067 nfetch = consume.nfetch;
1068 count = min(available, nfetch);
1069
1070 for (i = 0; i < count; i++) {
1071 j = (from + i) % channel->group_count;
1072 ret = put_user(channel->groups[j].user_offset,
1073 &consume.offsets[i]);
1074 if (ret)
1075 return -EFAULT;
1076 }
1077
1078 ret = put_user(count, &uconsume->nfetch);
1079 if (ret)
1080 return -EFAULT;
1081
1082 break;
1083 }
1036 case POCH_IOC_GET_COUNTERS: 1084 case POCH_IOC_GET_COUNTERS:
1037 if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters))) 1085 if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))
1038 return -EFAULT; 1086 return -EFAULT;
@@ -1108,12 +1156,18 @@ static void poch_irq_dma(struct channel_info *channel)
1108 for (i = 0; i < groups_done; i++) { 1156 for (i = 0; i < groups_done; i++) {
1109 j = (prev_transfer + i) % channel->group_count; 1157 j = (prev_transfer + i) % channel->group_count;
1110 group_offsets[j] = groups[j].user_offset; 1158 group_offsets[j] = groups[j].user_offset;
1159
1160 channel->transfer += 1;
1161 channel->transfer %= channel->group_count;
1162
1163 if (channel->transfer == channel->consumed) {
1164 channel->consumed += 1;
1165 channel->consumed %= channel->group_count;
1166 }
1111 } 1167 }
1112 1168
1113 spin_unlock(&channel->group_offsets_lock); 1169 spin_unlock(&channel->group_offsets_lock);
1114 1170
1115 channel->transfer = curr_transfer;
1116
1117 wake_up_interruptible(&channel->wq); 1171 wake_up_interruptible(&channel->wq);
1118} 1172}
1119 1173
diff --git a/drivers/staging/poch/poch.h b/drivers/staging/poch/poch.h
index 51a2d145798..ba1490b4252 100644
--- a/drivers/staging/poch/poch.h
+++ b/drivers/staging/poch/poch.h
@@ -19,6 +19,12 @@ struct poch_counters {
19 __u32 pll_unlock; 19 __u32 pll_unlock;
20}; 20};
21 21
22struct poch_consume {
23 __u32 __user *offsets;
24 __u32 nfetch;
25 __u32 nflush;
26};
27
22#define POCH_IOC_NUM '9' 28#define POCH_IOC_NUM '9'
23 29
24#define POCH_IOC_TRANSFER_START _IO(POCH_IOC_NUM, 0) 30#define POCH_IOC_TRANSFER_START _IO(POCH_IOC_NUM, 0)
@@ -27,3 +33,6 @@ struct poch_counters {
27 struct poch_counters) 33 struct poch_counters)
28#define POCH_IOC_SYNC_GROUP_FOR_USER _IO(POCH_IOC_NUM, 3) 34#define POCH_IOC_SYNC_GROUP_FOR_USER _IO(POCH_IOC_NUM, 3)
29#define POCH_IOC_SYNC_GROUP_FOR_DEVICE _IO(POCH_IOC_NUM, 4) 35#define POCH_IOC_SYNC_GROUP_FOR_DEVICE _IO(POCH_IOC_NUM, 4)
36
37#define POCH_IOC_CONSUME _IOWR(POCH_IOC_NUM, 5, \
38 struct poch_consume)