diff options
author | Vijay Kumar B <vijaykumar@bravegnu.org> | 2009-09-21 01:53:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 15:23:09 -0500 |
commit | b01faf05740884f915dd1b8652d8af1b6f458ccc (patch) | |
tree | b6671d121618dbf9c20efe8c1b9e9ed7f6f56f08 /drivers | |
parent | 16fbf4cba0880c31445d6414abbd7a1c51466b1f (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.c | 58 | ||||
-rw-r--r-- | drivers/staging/poch/poch.h | 9 |
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 | ||
22 | struct 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) | ||