Commit 5dab600e6a153ceb64832f608069e6c08185411a
Committed by
Linus Torvalds
1 parent
d994ffc247
Exists in
master
and in
7 other branches
kfifo: document everywhere that size has to be power of two
On my first try using them I missed that the fifos need to be power of two, resulting in a runtime bug. Document that requirement everywhere (and fix one grammar bug) Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Stefani Seibold <stefani@seibold.net> Cc: Roland Dreier <rdreier@cisco.com> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: Andy Walls <awalls@radix.net> Cc: Vikram Dhillon <dhillonv10@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 3 additions and 3 deletions Inline Diff
include/linux/kfifo.h
1 | /* | 1 | /* |
2 | * A generic kernel FIFO implementation. | 2 | * A generic kernel FIFO implementation. |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> | 4 | * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> |
5 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> | 5 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Howto porting drivers to the new generic fifo API: | 24 | * Howto porting drivers to the new generic fifo API: |
25 | * | 25 | * |
26 | * - Modify the declaration of the "struct kfifo *" object into a | 26 | * - Modify the declaration of the "struct kfifo *" object into a |
27 | * in-place "struct kfifo" object | 27 | * in-place "struct kfifo" object |
28 | * - Init the in-place object with kfifo_alloc() or kfifo_init() | 28 | * - Init the in-place object with kfifo_alloc() or kfifo_init() |
29 | * Note: The address of the in-place "struct kfifo" object must be | 29 | * Note: The address of the in-place "struct kfifo" object must be |
30 | * passed as the first argument to this functions | 30 | * passed as the first argument to this functions |
31 | * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get | 31 | * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get |
32 | * into kfifo_out | 32 | * into kfifo_out |
33 | * - Replace the use of kfifo_put into kfifo_in_locked and kfifo_get | 33 | * - Replace the use of kfifo_put into kfifo_in_locked and kfifo_get |
34 | * into kfifo_out_locked | 34 | * into kfifo_out_locked |
35 | * Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc | 35 | * Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc |
36 | * must be passed now to the kfifo_in_locked and kfifo_out_locked | 36 | * must be passed now to the kfifo_in_locked and kfifo_out_locked |
37 | * as the last parameter. | 37 | * as the last parameter. |
38 | * - All formerly name __kfifo_* functions has been renamed into kfifo_* | 38 | * - All formerly name __kfifo_* functions has been renamed into kfifo_* |
39 | */ | 39 | */ |
40 | 40 | ||
41 | #ifndef _LINUX_KFIFO_H | 41 | #ifndef _LINUX_KFIFO_H |
42 | #define _LINUX_KFIFO_H | 42 | #define _LINUX_KFIFO_H |
43 | 43 | ||
44 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
45 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
46 | 46 | ||
47 | struct kfifo { | 47 | struct kfifo { |
48 | unsigned char *buffer; /* the buffer holding the data */ | 48 | unsigned char *buffer; /* the buffer holding the data */ |
49 | unsigned int size; /* the size of the allocated buffer */ | 49 | unsigned int size; /* the size of the allocated buffer */ |
50 | unsigned int in; /* data is added at offset (in % size) */ | 50 | unsigned int in; /* data is added at offset (in % size) */ |
51 | unsigned int out; /* data is extracted from off. (out % size) */ | 51 | unsigned int out; /* data is extracted from off. (out % size) */ |
52 | }; | 52 | }; |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Macros for declaration and initialization of the kfifo datatype | 55 | * Macros for declaration and initialization of the kfifo datatype |
56 | */ | 56 | */ |
57 | 57 | ||
58 | /* helper macro */ | 58 | /* helper macro */ |
59 | #define __kfifo_initializer(s, b) \ | 59 | #define __kfifo_initializer(s, b) \ |
60 | (struct kfifo) { \ | 60 | (struct kfifo) { \ |
61 | .size = s, \ | 61 | .size = s, \ |
62 | .in = 0, \ | 62 | .in = 0, \ |
63 | .out = 0, \ | 63 | .out = 0, \ |
64 | .buffer = b \ | 64 | .buffer = b \ |
65 | } | 65 | } |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer | 68 | * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer |
69 | * @name: name of the declared kfifo datatype | 69 | * @name: name of the declared kfifo datatype |
70 | * @size: size of the fifo buffer | 70 | * @size: size of the fifo buffer. Must be a power of two. |
71 | * | 71 | * |
72 | * Note1: the macro can be used inside struct or union declaration | 72 | * Note1: the macro can be used inside struct or union declaration |
73 | * Note2: the macro creates two objects: | 73 | * Note2: the macro creates two objects: |
74 | * A kfifo object with the given name and a buffer for the kfifo | 74 | * A kfifo object with the given name and a buffer for the kfifo |
75 | * object named name##kfifo_buffer | 75 | * object named name##kfifo_buffer |
76 | */ | 76 | */ |
77 | #define DECLARE_KFIFO(name, size) \ | 77 | #define DECLARE_KFIFO(name, size) \ |
78 | union { \ | 78 | union { \ |
79 | struct kfifo name; \ | 79 | struct kfifo name; \ |
80 | unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \ | 80 | unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \ |
81 | } | 81 | } |
82 | 82 | ||
83 | /** | 83 | /** |
84 | * INIT_KFIFO - Initialize a kfifo declared by DECLARE_KFIFO | 84 | * INIT_KFIFO - Initialize a kfifo declared by DECLARE_KFIFO |
85 | * @name: name of the declared kfifo datatype | 85 | * @name: name of the declared kfifo datatype |
86 | */ | 86 | */ |
87 | #define INIT_KFIFO(name) \ | 87 | #define INIT_KFIFO(name) \ |
88 | name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \ | 88 | name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \ |
89 | sizeof(struct kfifo), name##kfifo_buffer) | 89 | sizeof(struct kfifo), name##kfifo_buffer) |
90 | 90 | ||
91 | /** | 91 | /** |
92 | * DEFINE_KFIFO - macro to define and initialize a kfifo | 92 | * DEFINE_KFIFO - macro to define and initialize a kfifo |
93 | * @name: name of the declared kfifo datatype | 93 | * @name: name of the declared kfifo datatype |
94 | * @size: size of the fifo buffer | 94 | * @size: size of the fifo buffer. Must be a power of two. |
95 | * | 95 | * |
96 | * Note1: the macro can be used for global and local kfifo data type variables | 96 | * Note1: the macro can be used for global and local kfifo data type variables |
97 | * Note2: the macro creates two objects: | 97 | * Note2: the macro creates two objects: |
98 | * A kfifo object with the given name and a buffer for the kfifo | 98 | * A kfifo object with the given name and a buffer for the kfifo |
99 | * object named name##kfifo_buffer | 99 | * object named name##kfifo_buffer |
100 | */ | 100 | */ |
101 | #define DEFINE_KFIFO(name, size) \ | 101 | #define DEFINE_KFIFO(name, size) \ |
102 | unsigned char name##kfifo_buffer[size]; \ | 102 | unsigned char name##kfifo_buffer[size]; \ |
103 | struct kfifo name = __kfifo_initializer(size, name##kfifo_buffer) | 103 | struct kfifo name = __kfifo_initializer(size, name##kfifo_buffer) |
104 | 104 | ||
105 | #undef __kfifo_initializer | 105 | #undef __kfifo_initializer |
106 | 106 | ||
107 | extern void kfifo_init(struct kfifo *fifo, void *buffer, | 107 | extern void kfifo_init(struct kfifo *fifo, void *buffer, |
108 | unsigned int size); | 108 | unsigned int size); |
109 | extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, | 109 | extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, |
110 | gfp_t gfp_mask); | 110 | gfp_t gfp_mask); |
111 | extern void kfifo_free(struct kfifo *fifo); | 111 | extern void kfifo_free(struct kfifo *fifo); |
112 | extern unsigned int kfifo_in(struct kfifo *fifo, | 112 | extern unsigned int kfifo_in(struct kfifo *fifo, |
113 | const void *from, unsigned int len); | 113 | const void *from, unsigned int len); |
114 | extern __must_check unsigned int kfifo_out(struct kfifo *fifo, | 114 | extern __must_check unsigned int kfifo_out(struct kfifo *fifo, |
115 | void *to, unsigned int len); | 115 | void *to, unsigned int len); |
116 | extern __must_check unsigned int kfifo_out_peek(struct kfifo *fifo, | 116 | extern __must_check unsigned int kfifo_out_peek(struct kfifo *fifo, |
117 | void *to, unsigned int len, unsigned offset); | 117 | void *to, unsigned int len, unsigned offset); |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * kfifo_initialized - Check if kfifo is initialized. | 120 | * kfifo_initialized - Check if kfifo is initialized. |
121 | * @fifo: fifo to check | 121 | * @fifo: fifo to check |
122 | * Return %true if FIFO is initialized, otherwise %false. | 122 | * Return %true if FIFO is initialized, otherwise %false. |
123 | * Assumes the fifo was 0 before. | 123 | * Assumes the fifo was 0 before. |
124 | */ | 124 | */ |
125 | static inline bool kfifo_initialized(struct kfifo *fifo) | 125 | static inline bool kfifo_initialized(struct kfifo *fifo) |
126 | { | 126 | { |
127 | return fifo->buffer != 0; | 127 | return fifo->buffer != 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * kfifo_reset - removes the entire FIFO contents | 131 | * kfifo_reset - removes the entire FIFO contents |
132 | * @fifo: the fifo to be emptied. | 132 | * @fifo: the fifo to be emptied. |
133 | */ | 133 | */ |
134 | static inline void kfifo_reset(struct kfifo *fifo) | 134 | static inline void kfifo_reset(struct kfifo *fifo) |
135 | { | 135 | { |
136 | fifo->in = fifo->out = 0; | 136 | fifo->in = fifo->out = 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | /** | 139 | /** |
140 | * kfifo_reset_out - skip FIFO contents | 140 | * kfifo_reset_out - skip FIFO contents |
141 | * @fifo: the fifo to be emptied. | 141 | * @fifo: the fifo to be emptied. |
142 | */ | 142 | */ |
143 | static inline void kfifo_reset_out(struct kfifo *fifo) | 143 | static inline void kfifo_reset_out(struct kfifo *fifo) |
144 | { | 144 | { |
145 | smp_mb(); | 145 | smp_mb(); |
146 | fifo->out = fifo->in; | 146 | fifo->out = fifo->in; |
147 | } | 147 | } |
148 | 148 | ||
149 | /** | 149 | /** |
150 | * kfifo_size - returns the size of the fifo in bytes | 150 | * kfifo_size - returns the size of the fifo in bytes |
151 | * @fifo: the fifo to be used. | 151 | * @fifo: the fifo to be used. |
152 | */ | 152 | */ |
153 | static inline __must_check unsigned int kfifo_size(struct kfifo *fifo) | 153 | static inline __must_check unsigned int kfifo_size(struct kfifo *fifo) |
154 | { | 154 | { |
155 | return fifo->size; | 155 | return fifo->size; |
156 | } | 156 | } |
157 | 157 | ||
158 | /** | 158 | /** |
159 | * kfifo_len - returns the number of used bytes in the FIFO | 159 | * kfifo_len - returns the number of used bytes in the FIFO |
160 | * @fifo: the fifo to be used. | 160 | * @fifo: the fifo to be used. |
161 | */ | 161 | */ |
162 | static inline unsigned int kfifo_len(struct kfifo *fifo) | 162 | static inline unsigned int kfifo_len(struct kfifo *fifo) |
163 | { | 163 | { |
164 | register unsigned int out; | 164 | register unsigned int out; |
165 | 165 | ||
166 | out = fifo->out; | 166 | out = fifo->out; |
167 | smp_rmb(); | 167 | smp_rmb(); |
168 | return fifo->in - out; | 168 | return fifo->in - out; |
169 | } | 169 | } |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * kfifo_is_empty - returns true if the fifo is empty | 172 | * kfifo_is_empty - returns true if the fifo is empty |
173 | * @fifo: the fifo to be used. | 173 | * @fifo: the fifo to be used. |
174 | */ | 174 | */ |
175 | static inline __must_check int kfifo_is_empty(struct kfifo *fifo) | 175 | static inline __must_check int kfifo_is_empty(struct kfifo *fifo) |
176 | { | 176 | { |
177 | return fifo->in == fifo->out; | 177 | return fifo->in == fifo->out; |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * kfifo_is_full - returns true if the fifo is full | 181 | * kfifo_is_full - returns true if the fifo is full |
182 | * @fifo: the fifo to be used. | 182 | * @fifo: the fifo to be used. |
183 | */ | 183 | */ |
184 | static inline __must_check int kfifo_is_full(struct kfifo *fifo) | 184 | static inline __must_check int kfifo_is_full(struct kfifo *fifo) |
185 | { | 185 | { |
186 | return kfifo_len(fifo) == kfifo_size(fifo); | 186 | return kfifo_len(fifo) == kfifo_size(fifo); |
187 | } | 187 | } |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * kfifo_avail - returns the number of bytes available in the FIFO | 190 | * kfifo_avail - returns the number of bytes available in the FIFO |
191 | * @fifo: the fifo to be used. | 191 | * @fifo: the fifo to be used. |
192 | */ | 192 | */ |
193 | static inline __must_check unsigned int kfifo_avail(struct kfifo *fifo) | 193 | static inline __must_check unsigned int kfifo_avail(struct kfifo *fifo) |
194 | { | 194 | { |
195 | return kfifo_size(fifo) - kfifo_len(fifo); | 195 | return kfifo_size(fifo) - kfifo_len(fifo); |
196 | } | 196 | } |
197 | 197 | ||
198 | /** | 198 | /** |
199 | * kfifo_in_locked - puts some data into the FIFO using a spinlock for locking | 199 | * kfifo_in_locked - puts some data into the FIFO using a spinlock for locking |
200 | * @fifo: the fifo to be used. | 200 | * @fifo: the fifo to be used. |
201 | * @from: the data to be added. | 201 | * @from: the data to be added. |
202 | * @n: the length of the data to be added. | 202 | * @n: the length of the data to be added. |
203 | * @lock: pointer to the spinlock to use for locking. | 203 | * @lock: pointer to the spinlock to use for locking. |
204 | * | 204 | * |
205 | * This function copies at most @len bytes from the @from buffer into | 205 | * This function copies at most @len bytes from the @from buffer into |
206 | * the FIFO depending on the free space, and returns the number of | 206 | * the FIFO depending on the free space, and returns the number of |
207 | * bytes copied. | 207 | * bytes copied. |
208 | */ | 208 | */ |
209 | static inline unsigned int kfifo_in_locked(struct kfifo *fifo, | 209 | static inline unsigned int kfifo_in_locked(struct kfifo *fifo, |
210 | const void *from, unsigned int n, spinlock_t *lock) | 210 | const void *from, unsigned int n, spinlock_t *lock) |
211 | { | 211 | { |
212 | unsigned long flags; | 212 | unsigned long flags; |
213 | unsigned int ret; | 213 | unsigned int ret; |
214 | 214 | ||
215 | spin_lock_irqsave(lock, flags); | 215 | spin_lock_irqsave(lock, flags); |
216 | 216 | ||
217 | ret = kfifo_in(fifo, from, n); | 217 | ret = kfifo_in(fifo, from, n); |
218 | 218 | ||
219 | spin_unlock_irqrestore(lock, flags); | 219 | spin_unlock_irqrestore(lock, flags); |
220 | 220 | ||
221 | return ret; | 221 | return ret; |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | 224 | /** |
225 | * kfifo_out_locked - gets some data from the FIFO using a spinlock for locking | 225 | * kfifo_out_locked - gets some data from the FIFO using a spinlock for locking |
226 | * @fifo: the fifo to be used. | 226 | * @fifo: the fifo to be used. |
227 | * @to: where the data must be copied. | 227 | * @to: where the data must be copied. |
228 | * @n: the size of the destination buffer. | 228 | * @n: the size of the destination buffer. |
229 | * @lock: pointer to the spinlock to use for locking. | 229 | * @lock: pointer to the spinlock to use for locking. |
230 | * | 230 | * |
231 | * This function copies at most @len bytes from the FIFO into the | 231 | * This function copies at most @len bytes from the FIFO into the |
232 | * @to buffer and returns the number of copied bytes. | 232 | * @to buffer and returns the number of copied bytes. |
233 | */ | 233 | */ |
234 | static inline __must_check unsigned int kfifo_out_locked(struct kfifo *fifo, | 234 | static inline __must_check unsigned int kfifo_out_locked(struct kfifo *fifo, |
235 | void *to, unsigned int n, spinlock_t *lock) | 235 | void *to, unsigned int n, spinlock_t *lock) |
236 | { | 236 | { |
237 | unsigned long flags; | 237 | unsigned long flags; |
238 | unsigned int ret; | 238 | unsigned int ret; |
239 | 239 | ||
240 | spin_lock_irqsave(lock, flags); | 240 | spin_lock_irqsave(lock, flags); |
241 | 241 | ||
242 | ret = kfifo_out(fifo, to, n); | 242 | ret = kfifo_out(fifo, to, n); |
243 | 243 | ||
244 | spin_unlock_irqrestore(lock, flags); | 244 | spin_unlock_irqrestore(lock, flags); |
245 | 245 | ||
246 | return ret; | 246 | return ret; |
247 | } | 247 | } |
248 | 248 | ||
249 | extern void kfifo_skip(struct kfifo *fifo, unsigned int len); | 249 | extern void kfifo_skip(struct kfifo *fifo, unsigned int len); |
250 | 250 | ||
251 | extern __must_check int kfifo_from_user(struct kfifo *fifo, | 251 | extern __must_check int kfifo_from_user(struct kfifo *fifo, |
252 | const void __user *from, unsigned int n, unsigned *lenout); | 252 | const void __user *from, unsigned int n, unsigned *lenout); |
253 | 253 | ||
254 | extern __must_check int kfifo_to_user(struct kfifo *fifo, | 254 | extern __must_check int kfifo_to_user(struct kfifo *fifo, |
255 | void __user *to, unsigned int n, unsigned *lenout); | 255 | void __user *to, unsigned int n, unsigned *lenout); |
256 | 256 | ||
257 | /* | 257 | /* |
258 | * __kfifo_add_out internal helper function for updating the out offset | 258 | * __kfifo_add_out internal helper function for updating the out offset |
259 | */ | 259 | */ |
260 | static inline void __kfifo_add_out(struct kfifo *fifo, | 260 | static inline void __kfifo_add_out(struct kfifo *fifo, |
261 | unsigned int off) | 261 | unsigned int off) |
262 | { | 262 | { |
263 | smp_mb(); | 263 | smp_mb(); |
264 | fifo->out += off; | 264 | fifo->out += off; |
265 | } | 265 | } |
266 | 266 | ||
267 | /* | 267 | /* |
268 | * __kfifo_add_in internal helper function for updating the in offset | 268 | * __kfifo_add_in internal helper function for updating the in offset |
269 | */ | 269 | */ |
270 | static inline void __kfifo_add_in(struct kfifo *fifo, | 270 | static inline void __kfifo_add_in(struct kfifo *fifo, |
271 | unsigned int off) | 271 | unsigned int off) |
272 | { | 272 | { |
273 | smp_wmb(); | 273 | smp_wmb(); |
274 | fifo->in += off; | 274 | fifo->in += off; |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | 277 | /* |
278 | * __kfifo_off internal helper function for calculating the index of a | 278 | * __kfifo_off internal helper function for calculating the index of a |
279 | * given offeset | 279 | * given offeset |
280 | */ | 280 | */ |
281 | static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off) | 281 | static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off) |
282 | { | 282 | { |
283 | return off & (fifo->size - 1); | 283 | return off & (fifo->size - 1); |
284 | } | 284 | } |
285 | 285 | ||
286 | /* | 286 | /* |
287 | * __kfifo_peek_n internal helper function for determinate the length of | 287 | * __kfifo_peek_n internal helper function for determinate the length of |
288 | * the next record in the fifo | 288 | * the next record in the fifo |
289 | */ | 289 | */ |
290 | static inline unsigned int __kfifo_peek_n(struct kfifo *fifo, | 290 | static inline unsigned int __kfifo_peek_n(struct kfifo *fifo, |
291 | unsigned int recsize) | 291 | unsigned int recsize) |
292 | { | 292 | { |
293 | #define __KFIFO_GET(fifo, off, shift) \ | 293 | #define __KFIFO_GET(fifo, off, shift) \ |
294 | ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift)) | 294 | ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift)) |
295 | 295 | ||
296 | unsigned int l; | 296 | unsigned int l; |
297 | 297 | ||
298 | l = __KFIFO_GET(fifo, 0, 0); | 298 | l = __KFIFO_GET(fifo, 0, 0); |
299 | 299 | ||
300 | if (--recsize) | 300 | if (--recsize) |
301 | l |= __KFIFO_GET(fifo, 1, 8); | 301 | l |= __KFIFO_GET(fifo, 1, 8); |
302 | 302 | ||
303 | return l; | 303 | return l; |
304 | #undef __KFIFO_GET | 304 | #undef __KFIFO_GET |
305 | } | 305 | } |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * __kfifo_poke_n internal helper function for storing the length of | 308 | * __kfifo_poke_n internal helper function for storing the length of |
309 | * the next record into the fifo | 309 | * the next record into the fifo |
310 | */ | 310 | */ |
311 | static inline void __kfifo_poke_n(struct kfifo *fifo, | 311 | static inline void __kfifo_poke_n(struct kfifo *fifo, |
312 | unsigned int recsize, unsigned int n) | 312 | unsigned int recsize, unsigned int n) |
313 | { | 313 | { |
314 | #define __KFIFO_PUT(fifo, off, val, shift) \ | 314 | #define __KFIFO_PUT(fifo, off, val, shift) \ |
315 | ( \ | 315 | ( \ |
316 | (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \ | 316 | (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \ |
317 | (unsigned char)((val) >> (shift)) \ | 317 | (unsigned char)((val) >> (shift)) \ |
318 | ) | 318 | ) |
319 | 319 | ||
320 | __KFIFO_PUT(fifo, 0, n, 0); | 320 | __KFIFO_PUT(fifo, 0, n, 0); |
321 | 321 | ||
322 | if (--recsize) | 322 | if (--recsize) |
323 | __KFIFO_PUT(fifo, 1, n, 8); | 323 | __KFIFO_PUT(fifo, 1, n, 8); |
324 | #undef __KFIFO_PUT | 324 | #undef __KFIFO_PUT |
325 | } | 325 | } |
326 | 326 | ||
327 | /* | 327 | /* |
328 | * __kfifo_in_... internal functions for put date into the fifo | 328 | * __kfifo_in_... internal functions for put date into the fifo |
329 | * do not call it directly, use kfifo_in_rec() instead | 329 | * do not call it directly, use kfifo_in_rec() instead |
330 | */ | 330 | */ |
331 | extern unsigned int __kfifo_in_n(struct kfifo *fifo, | 331 | extern unsigned int __kfifo_in_n(struct kfifo *fifo, |
332 | const void *from, unsigned int n, unsigned int recsize); | 332 | const void *from, unsigned int n, unsigned int recsize); |
333 | 333 | ||
334 | extern unsigned int __kfifo_in_generic(struct kfifo *fifo, | 334 | extern unsigned int __kfifo_in_generic(struct kfifo *fifo, |
335 | const void *from, unsigned int n, unsigned int recsize); | 335 | const void *from, unsigned int n, unsigned int recsize); |
336 | 336 | ||
337 | static inline unsigned int __kfifo_in_rec(struct kfifo *fifo, | 337 | static inline unsigned int __kfifo_in_rec(struct kfifo *fifo, |
338 | const void *from, unsigned int n, unsigned int recsize) | 338 | const void *from, unsigned int n, unsigned int recsize) |
339 | { | 339 | { |
340 | unsigned int ret; | 340 | unsigned int ret; |
341 | 341 | ||
342 | ret = __kfifo_in_n(fifo, from, n, recsize); | 342 | ret = __kfifo_in_n(fifo, from, n, recsize); |
343 | 343 | ||
344 | if (likely(ret == 0)) { | 344 | if (likely(ret == 0)) { |
345 | if (recsize) | 345 | if (recsize) |
346 | __kfifo_poke_n(fifo, recsize, n); | 346 | __kfifo_poke_n(fifo, recsize, n); |
347 | __kfifo_add_in(fifo, n + recsize); | 347 | __kfifo_add_in(fifo, n + recsize); |
348 | } | 348 | } |
349 | return ret; | 349 | return ret; |
350 | } | 350 | } |
351 | 351 | ||
352 | /** | 352 | /** |
353 | * kfifo_in_rec - puts some record data into the FIFO | 353 | * kfifo_in_rec - puts some record data into the FIFO |
354 | * @fifo: the fifo to be used. | 354 | * @fifo: the fifo to be used. |
355 | * @from: the data to be added. | 355 | * @from: the data to be added. |
356 | * @n: the length of the data to be added. | 356 | * @n: the length of the data to be added. |
357 | * @recsize: size of record field | 357 | * @recsize: size of record field |
358 | * | 358 | * |
359 | * This function copies @n bytes from the @from into the FIFO and returns | 359 | * This function copies @n bytes from the @from into the FIFO and returns |
360 | * the number of bytes which cannot be copied. | 360 | * the number of bytes which cannot be copied. |
361 | * A returned value greater than the @n value means that the record doesn't | 361 | * A returned value greater than the @n value means that the record doesn't |
362 | * fit into the buffer. | 362 | * fit into the buffer. |
363 | * | 363 | * |
364 | * Note that with only one concurrent reader and one concurrent | 364 | * Note that with only one concurrent reader and one concurrent |
365 | * writer, you don't need extra locking to use these functions. | 365 | * writer, you don't need extra locking to use these functions. |
366 | */ | 366 | */ |
367 | static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo, | 367 | static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo, |
368 | void *from, unsigned int n, unsigned int recsize) | 368 | void *from, unsigned int n, unsigned int recsize) |
369 | { | 369 | { |
370 | if (!__builtin_constant_p(recsize)) | 370 | if (!__builtin_constant_p(recsize)) |
371 | return __kfifo_in_generic(fifo, from, n, recsize); | 371 | return __kfifo_in_generic(fifo, from, n, recsize); |
372 | return __kfifo_in_rec(fifo, from, n, recsize); | 372 | return __kfifo_in_rec(fifo, from, n, recsize); |
373 | } | 373 | } |
374 | 374 | ||
375 | /* | 375 | /* |
376 | * __kfifo_out_... internal functions for get date from the fifo | 376 | * __kfifo_out_... internal functions for get date from the fifo |
377 | * do not call it directly, use kfifo_out_rec() instead | 377 | * do not call it directly, use kfifo_out_rec() instead |
378 | */ | 378 | */ |
379 | extern unsigned int __kfifo_out_n(struct kfifo *fifo, | 379 | extern unsigned int __kfifo_out_n(struct kfifo *fifo, |
380 | void *to, unsigned int reclen, unsigned int recsize); | 380 | void *to, unsigned int reclen, unsigned int recsize); |
381 | 381 | ||
382 | extern unsigned int __kfifo_out_generic(struct kfifo *fifo, | 382 | extern unsigned int __kfifo_out_generic(struct kfifo *fifo, |
383 | void *to, unsigned int n, | 383 | void *to, unsigned int n, |
384 | unsigned int recsize, unsigned int *total); | 384 | unsigned int recsize, unsigned int *total); |
385 | 385 | ||
386 | static inline unsigned int __kfifo_out_rec(struct kfifo *fifo, | 386 | static inline unsigned int __kfifo_out_rec(struct kfifo *fifo, |
387 | void *to, unsigned int n, unsigned int recsize, | 387 | void *to, unsigned int n, unsigned int recsize, |
388 | unsigned int *total) | 388 | unsigned int *total) |
389 | { | 389 | { |
390 | unsigned int l; | 390 | unsigned int l; |
391 | 391 | ||
392 | if (!recsize) { | 392 | if (!recsize) { |
393 | l = n; | 393 | l = n; |
394 | if (total) | 394 | if (total) |
395 | *total = l; | 395 | *total = l; |
396 | } else { | 396 | } else { |
397 | l = __kfifo_peek_n(fifo, recsize); | 397 | l = __kfifo_peek_n(fifo, recsize); |
398 | if (total) | 398 | if (total) |
399 | *total = l; | 399 | *total = l; |
400 | if (n < l) | 400 | if (n < l) |
401 | return l; | 401 | return l; |
402 | } | 402 | } |
403 | 403 | ||
404 | return __kfifo_out_n(fifo, to, l, recsize); | 404 | return __kfifo_out_n(fifo, to, l, recsize); |
405 | } | 405 | } |
406 | 406 | ||
407 | /** | 407 | /** |
408 | * kfifo_out_rec - gets some record data from the FIFO | 408 | * kfifo_out_rec - gets some record data from the FIFO |
409 | * @fifo: the fifo to be used. | 409 | * @fifo: the fifo to be used. |
410 | * @to: where the data must be copied. | 410 | * @to: where the data must be copied. |
411 | * @n: the size of the destination buffer. | 411 | * @n: the size of the destination buffer. |
412 | * @recsize: size of record field | 412 | * @recsize: size of record field |
413 | * @total: pointer where the total number of to copied bytes should stored | 413 | * @total: pointer where the total number of to copied bytes should stored |
414 | * | 414 | * |
415 | * This function copies at most @n bytes from the FIFO to @to and returns the | 415 | * This function copies at most @n bytes from the FIFO to @to and returns the |
416 | * number of bytes which cannot be copied. | 416 | * number of bytes which cannot be copied. |
417 | * A returned value greater than the @n value means that the record doesn't | 417 | * A returned value greater than the @n value means that the record doesn't |
418 | * fit into the @to buffer. | 418 | * fit into the @to buffer. |
419 | * | 419 | * |
420 | * Note that with only one concurrent reader and one concurrent | 420 | * Note that with only one concurrent reader and one concurrent |
421 | * writer, you don't need extra locking to use these functions. | 421 | * writer, you don't need extra locking to use these functions. |
422 | */ | 422 | */ |
423 | static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo, | 423 | static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo, |
424 | void *to, unsigned int n, unsigned int recsize, | 424 | void *to, unsigned int n, unsigned int recsize, |
425 | unsigned int *total) | 425 | unsigned int *total) |
426 | 426 | ||
427 | { | 427 | { |
428 | if (!__builtin_constant_p(recsize)) | 428 | if (!__builtin_constant_p(recsize)) |
429 | return __kfifo_out_generic(fifo, to, n, recsize, total); | 429 | return __kfifo_out_generic(fifo, to, n, recsize, total); |
430 | return __kfifo_out_rec(fifo, to, n, recsize, total); | 430 | return __kfifo_out_rec(fifo, to, n, recsize, total); |
431 | } | 431 | } |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * __kfifo_from_user_... internal functions for transfer from user space into | 434 | * __kfifo_from_user_... internal functions for transfer from user space into |
435 | * the fifo. do not call it directly, use kfifo_from_user_rec() instead | 435 | * the fifo. do not call it directly, use kfifo_from_user_rec() instead |
436 | */ | 436 | */ |
437 | extern unsigned int __kfifo_from_user_n(struct kfifo *fifo, | 437 | extern unsigned int __kfifo_from_user_n(struct kfifo *fifo, |
438 | const void __user *from, unsigned int n, unsigned int recsize); | 438 | const void __user *from, unsigned int n, unsigned int recsize); |
439 | 439 | ||
440 | extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo, | 440 | extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo, |
441 | const void __user *from, unsigned int n, unsigned int recsize); | 441 | const void __user *from, unsigned int n, unsigned int recsize); |
442 | 442 | ||
443 | static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo, | 443 | static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo, |
444 | const void __user *from, unsigned int n, unsigned int recsize) | 444 | const void __user *from, unsigned int n, unsigned int recsize) |
445 | { | 445 | { |
446 | unsigned int ret; | 446 | unsigned int ret; |
447 | 447 | ||
448 | ret = __kfifo_from_user_n(fifo, from, n, recsize); | 448 | ret = __kfifo_from_user_n(fifo, from, n, recsize); |
449 | 449 | ||
450 | if (likely(ret == 0)) { | 450 | if (likely(ret == 0)) { |
451 | if (recsize) | 451 | if (recsize) |
452 | __kfifo_poke_n(fifo, recsize, n); | 452 | __kfifo_poke_n(fifo, recsize, n); |
453 | __kfifo_add_in(fifo, n + recsize); | 453 | __kfifo_add_in(fifo, n + recsize); |
454 | } | 454 | } |
455 | return ret; | 455 | return ret; |
456 | } | 456 | } |
457 | 457 | ||
458 | /** | 458 | /** |
459 | * kfifo_from_user_rec - puts some data from user space into the FIFO | 459 | * kfifo_from_user_rec - puts some data from user space into the FIFO |
460 | * @fifo: the fifo to be used. | 460 | * @fifo: the fifo to be used. |
461 | * @from: pointer to the data to be added. | 461 | * @from: pointer to the data to be added. |
462 | * @n: the length of the data to be added. | 462 | * @n: the length of the data to be added. |
463 | * @recsize: size of record field | 463 | * @recsize: size of record field |
464 | * | 464 | * |
465 | * This function copies @n bytes from the @from into the | 465 | * This function copies @n bytes from the @from into the |
466 | * FIFO and returns the number of bytes which cannot be copied. | 466 | * FIFO and returns the number of bytes which cannot be copied. |
467 | * | 467 | * |
468 | * If the returned value is equal or less the @n value, the copy_from_user() | 468 | * If the returned value is equal or less the @n value, the copy_from_user() |
469 | * functions has failed. Otherwise the record doesn't fit into the buffer. | 469 | * functions has failed. Otherwise the record doesn't fit into the buffer. |
470 | * | 470 | * |
471 | * Note that with only one concurrent reader and one concurrent | 471 | * Note that with only one concurrent reader and one concurrent |
472 | * writer, you don't need extra locking to use these functions. | 472 | * writer, you don't need extra locking to use these functions. |
473 | */ | 473 | */ |
474 | static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo, | 474 | static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo, |
475 | const void __user *from, unsigned int n, unsigned int recsize) | 475 | const void __user *from, unsigned int n, unsigned int recsize) |
476 | { | 476 | { |
477 | if (!__builtin_constant_p(recsize)) | 477 | if (!__builtin_constant_p(recsize)) |
478 | return __kfifo_from_user_generic(fifo, from, n, recsize); | 478 | return __kfifo_from_user_generic(fifo, from, n, recsize); |
479 | return __kfifo_from_user_rec(fifo, from, n, recsize); | 479 | return __kfifo_from_user_rec(fifo, from, n, recsize); |
480 | } | 480 | } |
481 | 481 | ||
482 | /* | 482 | /* |
483 | * __kfifo_to_user_... internal functions for transfer fifo data into user space | 483 | * __kfifo_to_user_... internal functions for transfer fifo data into user space |
484 | * do not call it directly, use kfifo_to_user_rec() instead | 484 | * do not call it directly, use kfifo_to_user_rec() instead |
485 | */ | 485 | */ |
486 | extern unsigned int __kfifo_to_user_n(struct kfifo *fifo, | 486 | extern unsigned int __kfifo_to_user_n(struct kfifo *fifo, |
487 | void __user *to, unsigned int n, unsigned int reclen, | 487 | void __user *to, unsigned int n, unsigned int reclen, |
488 | unsigned int recsize); | 488 | unsigned int recsize); |
489 | 489 | ||
490 | extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | 490 | extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo, |
491 | void __user *to, unsigned int n, unsigned int recsize, | 491 | void __user *to, unsigned int n, unsigned int recsize, |
492 | unsigned int *total); | 492 | unsigned int *total); |
493 | 493 | ||
494 | static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo, | 494 | static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo, |
495 | void __user *to, unsigned int n, | 495 | void __user *to, unsigned int n, |
496 | unsigned int recsize, unsigned int *total) | 496 | unsigned int recsize, unsigned int *total) |
497 | { | 497 | { |
498 | unsigned int l; | 498 | unsigned int l; |
499 | 499 | ||
500 | if (!recsize) { | 500 | if (!recsize) { |
501 | l = n; | 501 | l = n; |
502 | if (total) | 502 | if (total) |
503 | *total = l; | 503 | *total = l; |
504 | } else { | 504 | } else { |
505 | l = __kfifo_peek_n(fifo, recsize); | 505 | l = __kfifo_peek_n(fifo, recsize); |
506 | if (total) | 506 | if (total) |
507 | *total = l; | 507 | *total = l; |
508 | if (n < l) | 508 | if (n < l) |
509 | return l; | 509 | return l; |
510 | } | 510 | } |
511 | 511 | ||
512 | return __kfifo_to_user_n(fifo, to, n, l, recsize); | 512 | return __kfifo_to_user_n(fifo, to, n, l, recsize); |
513 | } | 513 | } |
514 | 514 | ||
515 | /** | 515 | /** |
516 | * kfifo_to_user_rec - gets data from the FIFO and write it to user space | 516 | * kfifo_to_user_rec - gets data from the FIFO and write it to user space |
517 | * @fifo: the fifo to be used. | 517 | * @fifo: the fifo to be used. |
518 | * @to: where the data must be copied. | 518 | * @to: where the data must be copied. |
519 | * @n: the size of the destination buffer. | 519 | * @n: the size of the destination buffer. |
520 | * @recsize: size of record field | 520 | * @recsize: size of record field |
521 | * @total: pointer where the total number of to copied bytes should stored | 521 | * @total: pointer where the total number of to copied bytes should stored |
522 | * | 522 | * |
523 | * This function copies at most @n bytes from the FIFO to the @to. | 523 | * This function copies at most @n bytes from the FIFO to the @to. |
524 | * In case of an error, the function returns the number of bytes which cannot | 524 | * In case of an error, the function returns the number of bytes which cannot |
525 | * be copied. | 525 | * be copied. |
526 | * If the returned value is equal or less the @n value, the copy_to_user() | 526 | * If the returned value is equal or less the @n value, the copy_to_user() |
527 | * functions has failed. Otherwise the record doesn't fit into the @to buffer. | 527 | * functions has failed. Otherwise the record doesn't fit into the @to buffer. |
528 | * | 528 | * |
529 | * Note that with only one concurrent reader and one concurrent | 529 | * Note that with only one concurrent reader and one concurrent |
530 | * writer, you don't need extra locking to use these functions. | 530 | * writer, you don't need extra locking to use these functions. |
531 | */ | 531 | */ |
532 | static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo, | 532 | static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo, |
533 | void __user *to, unsigned int n, unsigned int recsize, | 533 | void __user *to, unsigned int n, unsigned int recsize, |
534 | unsigned int *total) | 534 | unsigned int *total) |
535 | { | 535 | { |
536 | if (!__builtin_constant_p(recsize)) | 536 | if (!__builtin_constant_p(recsize)) |
537 | return __kfifo_to_user_generic(fifo, to, n, recsize, total); | 537 | return __kfifo_to_user_generic(fifo, to, n, recsize, total); |
538 | return __kfifo_to_user_rec(fifo, to, n, recsize, total); | 538 | return __kfifo_to_user_rec(fifo, to, n, recsize, total); |
539 | } | 539 | } |
540 | 540 | ||
541 | /* | 541 | /* |
542 | * __kfifo_peek_... internal functions for peek into the next fifo record | 542 | * __kfifo_peek_... internal functions for peek into the next fifo record |
543 | * do not call it directly, use kfifo_peek_rec() instead | 543 | * do not call it directly, use kfifo_peek_rec() instead |
544 | */ | 544 | */ |
545 | extern unsigned int __kfifo_peek_generic(struct kfifo *fifo, | 545 | extern unsigned int __kfifo_peek_generic(struct kfifo *fifo, |
546 | unsigned int recsize); | 546 | unsigned int recsize); |
547 | 547 | ||
548 | /** | 548 | /** |
549 | * kfifo_peek_rec - gets the size of the next FIFO record data | 549 | * kfifo_peek_rec - gets the size of the next FIFO record data |
550 | * @fifo: the fifo to be used. | 550 | * @fifo: the fifo to be used. |
551 | * @recsize: size of record field | 551 | * @recsize: size of record field |
552 | * | 552 | * |
553 | * This function returns the size of the next FIFO record in number of bytes | 553 | * This function returns the size of the next FIFO record in number of bytes |
554 | */ | 554 | */ |
555 | static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo, | 555 | static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo, |
556 | unsigned int recsize) | 556 | unsigned int recsize) |
557 | { | 557 | { |
558 | if (!__builtin_constant_p(recsize)) | 558 | if (!__builtin_constant_p(recsize)) |
559 | return __kfifo_peek_generic(fifo, recsize); | 559 | return __kfifo_peek_generic(fifo, recsize); |
560 | if (!recsize) | 560 | if (!recsize) |
561 | return kfifo_len(fifo); | 561 | return kfifo_len(fifo); |
562 | return __kfifo_peek_n(fifo, recsize); | 562 | return __kfifo_peek_n(fifo, recsize); |
563 | } | 563 | } |
564 | 564 | ||
565 | /* | 565 | /* |
566 | * __kfifo_skip_... internal functions for skip the next fifo record | 566 | * __kfifo_skip_... internal functions for skip the next fifo record |
567 | * do not call it directly, use kfifo_skip_rec() instead | 567 | * do not call it directly, use kfifo_skip_rec() instead |
568 | */ | 568 | */ |
569 | extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize); | 569 | extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize); |
570 | 570 | ||
571 | static inline void __kfifo_skip_rec(struct kfifo *fifo, | 571 | static inline void __kfifo_skip_rec(struct kfifo *fifo, |
572 | unsigned int recsize) | 572 | unsigned int recsize) |
573 | { | 573 | { |
574 | unsigned int l; | 574 | unsigned int l; |
575 | 575 | ||
576 | if (recsize) { | 576 | if (recsize) { |
577 | l = __kfifo_peek_n(fifo, recsize); | 577 | l = __kfifo_peek_n(fifo, recsize); |
578 | 578 | ||
579 | if (l + recsize <= kfifo_len(fifo)) { | 579 | if (l + recsize <= kfifo_len(fifo)) { |
580 | __kfifo_add_out(fifo, l + recsize); | 580 | __kfifo_add_out(fifo, l + recsize); |
581 | return; | 581 | return; |
582 | } | 582 | } |
583 | } | 583 | } |
584 | kfifo_reset_out(fifo); | 584 | kfifo_reset_out(fifo); |
585 | } | 585 | } |
586 | 586 | ||
587 | /** | 587 | /** |
588 | * kfifo_skip_rec - skip the next fifo out record | 588 | * kfifo_skip_rec - skip the next fifo out record |
589 | * @fifo: the fifo to be used. | 589 | * @fifo: the fifo to be used. |
590 | * @recsize: size of record field | 590 | * @recsize: size of record field |
591 | * | 591 | * |
592 | * This function skips the next FIFO record | 592 | * This function skips the next FIFO record |
593 | */ | 593 | */ |
594 | static inline void kfifo_skip_rec(struct kfifo *fifo, | 594 | static inline void kfifo_skip_rec(struct kfifo *fifo, |
595 | unsigned int recsize) | 595 | unsigned int recsize) |
596 | { | 596 | { |
597 | if (!__builtin_constant_p(recsize)) | 597 | if (!__builtin_constant_p(recsize)) |
598 | __kfifo_skip_generic(fifo, recsize); | 598 | __kfifo_skip_generic(fifo, recsize); |
599 | else | 599 | else |
600 | __kfifo_skip_rec(fifo, recsize); | 600 | __kfifo_skip_rec(fifo, recsize); |
601 | } | 601 | } |
602 | 602 | ||
603 | /** | 603 | /** |
604 | * kfifo_avail_rec - returns the number of bytes available in a record FIFO | 604 | * kfifo_avail_rec - returns the number of bytes available in a record FIFO |
605 | * @fifo: the fifo to be used. | 605 | * @fifo: the fifo to be used. |
606 | * @recsize: size of record field | 606 | * @recsize: size of record field |
607 | */ | 607 | */ |
608 | static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo, | 608 | static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo, |
609 | unsigned int recsize) | 609 | unsigned int recsize) |
610 | { | 610 | { |
611 | unsigned int l = kfifo_size(fifo) - kfifo_len(fifo); | 611 | unsigned int l = kfifo_size(fifo) - kfifo_len(fifo); |
612 | 612 | ||
613 | return (l > recsize) ? l - recsize : 0; | 613 | return (l > recsize) ? l - recsize : 0; |
614 | } | 614 | } |
615 | 615 | ||
616 | #endif | 616 | #endif |
617 | 617 |
kernel/kfifo.c
1 | /* | 1 | /* |
2 | * A generic kernel FIFO implementation. | 2 | * A generic kernel FIFO implementation. |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> | 4 | * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> |
5 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> | 5 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
27 | #include <linux/kfifo.h> | 27 | #include <linux/kfifo.h> |
28 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | 30 | ||
31 | static void _kfifo_init(struct kfifo *fifo, void *buffer, | 31 | static void _kfifo_init(struct kfifo *fifo, void *buffer, |
32 | unsigned int size) | 32 | unsigned int size) |
33 | { | 33 | { |
34 | fifo->buffer = buffer; | 34 | fifo->buffer = buffer; |
35 | fifo->size = size; | 35 | fifo->size = size; |
36 | 36 | ||
37 | kfifo_reset(fifo); | 37 | kfifo_reset(fifo); |
38 | } | 38 | } |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * kfifo_init - initialize a FIFO using a preallocated buffer | 41 | * kfifo_init - initialize a FIFO using a preallocated buffer |
42 | * @fifo: the fifo to assign the buffer | 42 | * @fifo: the fifo to assign the buffer |
43 | * @buffer: the preallocated buffer to be used. | 43 | * @buffer: the preallocated buffer to be used. |
44 | * @size: the size of the internal buffer, this have to be a power of 2. | 44 | * @size: the size of the internal buffer, this has to be a power of 2. |
45 | * | 45 | * |
46 | */ | 46 | */ |
47 | void kfifo_init(struct kfifo *fifo, void *buffer, unsigned int size) | 47 | void kfifo_init(struct kfifo *fifo, void *buffer, unsigned int size) |
48 | { | 48 | { |
49 | /* size must be a power of 2 */ | 49 | /* size must be a power of 2 */ |
50 | BUG_ON(!is_power_of_2(size)); | 50 | BUG_ON(!is_power_of_2(size)); |
51 | 51 | ||
52 | _kfifo_init(fifo, buffer, size); | 52 | _kfifo_init(fifo, buffer, size); |
53 | } | 53 | } |
54 | EXPORT_SYMBOL(kfifo_init); | 54 | EXPORT_SYMBOL(kfifo_init); |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * kfifo_alloc - allocates a new FIFO internal buffer | 57 | * kfifo_alloc - allocates a new FIFO internal buffer |
58 | * @fifo: the fifo to assign then new buffer | 58 | * @fifo: the fifo to assign then new buffer |
59 | * @size: the size of the buffer to be allocated, this have to be a power of 2. | 59 | * @size: the size of the buffer to be allocated, this have to be a power of 2. |
60 | * @gfp_mask: get_free_pages mask, passed to kmalloc() | 60 | * @gfp_mask: get_free_pages mask, passed to kmalloc() |
61 | * | 61 | * |
62 | * This function dynamically allocates a new fifo internal buffer | 62 | * This function dynamically allocates a new fifo internal buffer |
63 | * | 63 | * |
64 | * The size will be rounded-up to a power of 2. | 64 | * The size will be rounded-up to a power of 2. |
65 | * The buffer will be release with kfifo_free(). | 65 | * The buffer will be release with kfifo_free(). |
66 | * Return 0 if no error, otherwise the an error code | 66 | * Return 0 if no error, otherwise the an error code |
67 | */ | 67 | */ |
68 | int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask) | 68 | int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask) |
69 | { | 69 | { |
70 | unsigned char *buffer; | 70 | unsigned char *buffer; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * round up to the next power of 2, since our 'let the indices | 73 | * round up to the next power of 2, since our 'let the indices |
74 | * wrap' technique works only in this case. | 74 | * wrap' technique works only in this case. |
75 | */ | 75 | */ |
76 | if (!is_power_of_2(size)) { | 76 | if (!is_power_of_2(size)) { |
77 | BUG_ON(size > 0x80000000); | 77 | BUG_ON(size > 0x80000000); |
78 | size = roundup_pow_of_two(size); | 78 | size = roundup_pow_of_two(size); |
79 | } | 79 | } |
80 | 80 | ||
81 | buffer = kmalloc(size, gfp_mask); | 81 | buffer = kmalloc(size, gfp_mask); |
82 | if (!buffer) { | 82 | if (!buffer) { |
83 | _kfifo_init(fifo, 0, 0); | 83 | _kfifo_init(fifo, 0, 0); |
84 | return -ENOMEM; | 84 | return -ENOMEM; |
85 | } | 85 | } |
86 | 86 | ||
87 | _kfifo_init(fifo, buffer, size); | 87 | _kfifo_init(fifo, buffer, size); |
88 | 88 | ||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | EXPORT_SYMBOL(kfifo_alloc); | 91 | EXPORT_SYMBOL(kfifo_alloc); |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * kfifo_free - frees the FIFO internal buffer | 94 | * kfifo_free - frees the FIFO internal buffer |
95 | * @fifo: the fifo to be freed. | 95 | * @fifo: the fifo to be freed. |
96 | */ | 96 | */ |
97 | void kfifo_free(struct kfifo *fifo) | 97 | void kfifo_free(struct kfifo *fifo) |
98 | { | 98 | { |
99 | kfree(fifo->buffer); | 99 | kfree(fifo->buffer); |
100 | } | 100 | } |
101 | EXPORT_SYMBOL(kfifo_free); | 101 | EXPORT_SYMBOL(kfifo_free); |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * kfifo_skip - skip output data | 104 | * kfifo_skip - skip output data |
105 | * @fifo: the fifo to be used. | 105 | * @fifo: the fifo to be used. |
106 | * @len: number of bytes to skip | 106 | * @len: number of bytes to skip |
107 | */ | 107 | */ |
108 | void kfifo_skip(struct kfifo *fifo, unsigned int len) | 108 | void kfifo_skip(struct kfifo *fifo, unsigned int len) |
109 | { | 109 | { |
110 | if (len < kfifo_len(fifo)) { | 110 | if (len < kfifo_len(fifo)) { |
111 | __kfifo_add_out(fifo, len); | 111 | __kfifo_add_out(fifo, len); |
112 | return; | 112 | return; |
113 | } | 113 | } |
114 | kfifo_reset_out(fifo); | 114 | kfifo_reset_out(fifo); |
115 | } | 115 | } |
116 | EXPORT_SYMBOL(kfifo_skip); | 116 | EXPORT_SYMBOL(kfifo_skip); |
117 | 117 | ||
118 | static inline void __kfifo_in_data(struct kfifo *fifo, | 118 | static inline void __kfifo_in_data(struct kfifo *fifo, |
119 | const void *from, unsigned int len, unsigned int off) | 119 | const void *from, unsigned int len, unsigned int off) |
120 | { | 120 | { |
121 | unsigned int l; | 121 | unsigned int l; |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * Ensure that we sample the fifo->out index -before- we | 124 | * Ensure that we sample the fifo->out index -before- we |
125 | * start putting bytes into the kfifo. | 125 | * start putting bytes into the kfifo. |
126 | */ | 126 | */ |
127 | 127 | ||
128 | smp_mb(); | 128 | smp_mb(); |
129 | 129 | ||
130 | off = __kfifo_off(fifo, fifo->in + off); | 130 | off = __kfifo_off(fifo, fifo->in + off); |
131 | 131 | ||
132 | /* first put the data starting from fifo->in to buffer end */ | 132 | /* first put the data starting from fifo->in to buffer end */ |
133 | l = min(len, fifo->size - off); | 133 | l = min(len, fifo->size - off); |
134 | memcpy(fifo->buffer + off, from, l); | 134 | memcpy(fifo->buffer + off, from, l); |
135 | 135 | ||
136 | /* then put the rest (if any) at the beginning of the buffer */ | 136 | /* then put the rest (if any) at the beginning of the buffer */ |
137 | memcpy(fifo->buffer, from + l, len - l); | 137 | memcpy(fifo->buffer, from + l, len - l); |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline void __kfifo_out_data(struct kfifo *fifo, | 140 | static inline void __kfifo_out_data(struct kfifo *fifo, |
141 | void *to, unsigned int len, unsigned int off) | 141 | void *to, unsigned int len, unsigned int off) |
142 | { | 142 | { |
143 | unsigned int l; | 143 | unsigned int l; |
144 | 144 | ||
145 | /* | 145 | /* |
146 | * Ensure that we sample the fifo->in index -before- we | 146 | * Ensure that we sample the fifo->in index -before- we |
147 | * start removing bytes from the kfifo. | 147 | * start removing bytes from the kfifo. |
148 | */ | 148 | */ |
149 | 149 | ||
150 | smp_rmb(); | 150 | smp_rmb(); |
151 | 151 | ||
152 | off = __kfifo_off(fifo, fifo->out + off); | 152 | off = __kfifo_off(fifo, fifo->out + off); |
153 | 153 | ||
154 | /* first get the data from fifo->out until the end of the buffer */ | 154 | /* first get the data from fifo->out until the end of the buffer */ |
155 | l = min(len, fifo->size - off); | 155 | l = min(len, fifo->size - off); |
156 | memcpy(to, fifo->buffer + off, l); | 156 | memcpy(to, fifo->buffer + off, l); |
157 | 157 | ||
158 | /* then get the rest (if any) from the beginning of the buffer */ | 158 | /* then get the rest (if any) from the beginning of the buffer */ |
159 | memcpy(to + l, fifo->buffer, len - l); | 159 | memcpy(to + l, fifo->buffer, len - l); |
160 | } | 160 | } |
161 | 161 | ||
162 | static inline int __kfifo_from_user_data(struct kfifo *fifo, | 162 | static inline int __kfifo_from_user_data(struct kfifo *fifo, |
163 | const void __user *from, unsigned int len, unsigned int off, | 163 | const void __user *from, unsigned int len, unsigned int off, |
164 | unsigned *lenout) | 164 | unsigned *lenout) |
165 | { | 165 | { |
166 | unsigned int l; | 166 | unsigned int l; |
167 | int ret; | 167 | int ret; |
168 | 168 | ||
169 | /* | 169 | /* |
170 | * Ensure that we sample the fifo->out index -before- we | 170 | * Ensure that we sample the fifo->out index -before- we |
171 | * start putting bytes into the kfifo. | 171 | * start putting bytes into the kfifo. |
172 | */ | 172 | */ |
173 | 173 | ||
174 | smp_mb(); | 174 | smp_mb(); |
175 | 175 | ||
176 | off = __kfifo_off(fifo, fifo->in + off); | 176 | off = __kfifo_off(fifo, fifo->in + off); |
177 | 177 | ||
178 | /* first put the data starting from fifo->in to buffer end */ | 178 | /* first put the data starting from fifo->in to buffer end */ |
179 | l = min(len, fifo->size - off); | 179 | l = min(len, fifo->size - off); |
180 | ret = copy_from_user(fifo->buffer + off, from, l); | 180 | ret = copy_from_user(fifo->buffer + off, from, l); |
181 | if (unlikely(ret)) { | 181 | if (unlikely(ret)) { |
182 | *lenout = ret; | 182 | *lenout = ret; |
183 | return -EFAULT; | 183 | return -EFAULT; |
184 | } | 184 | } |
185 | *lenout = l; | 185 | *lenout = l; |
186 | 186 | ||
187 | /* then put the rest (if any) at the beginning of the buffer */ | 187 | /* then put the rest (if any) at the beginning of the buffer */ |
188 | ret = copy_from_user(fifo->buffer, from + l, len - l); | 188 | ret = copy_from_user(fifo->buffer, from + l, len - l); |
189 | *lenout += ret ? ret : len - l; | 189 | *lenout += ret ? ret : len - l; |
190 | return ret ? -EFAULT : 0; | 190 | return ret ? -EFAULT : 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | static inline int __kfifo_to_user_data(struct kfifo *fifo, | 193 | static inline int __kfifo_to_user_data(struct kfifo *fifo, |
194 | void __user *to, unsigned int len, unsigned int off, unsigned *lenout) | 194 | void __user *to, unsigned int len, unsigned int off, unsigned *lenout) |
195 | { | 195 | { |
196 | unsigned int l; | 196 | unsigned int l; |
197 | int ret; | 197 | int ret; |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * Ensure that we sample the fifo->in index -before- we | 200 | * Ensure that we sample the fifo->in index -before- we |
201 | * start removing bytes from the kfifo. | 201 | * start removing bytes from the kfifo. |
202 | */ | 202 | */ |
203 | 203 | ||
204 | smp_rmb(); | 204 | smp_rmb(); |
205 | 205 | ||
206 | off = __kfifo_off(fifo, fifo->out + off); | 206 | off = __kfifo_off(fifo, fifo->out + off); |
207 | 207 | ||
208 | /* first get the data from fifo->out until the end of the buffer */ | 208 | /* first get the data from fifo->out until the end of the buffer */ |
209 | l = min(len, fifo->size - off); | 209 | l = min(len, fifo->size - off); |
210 | ret = copy_to_user(to, fifo->buffer + off, l); | 210 | ret = copy_to_user(to, fifo->buffer + off, l); |
211 | *lenout = l; | 211 | *lenout = l; |
212 | if (unlikely(ret)) { | 212 | if (unlikely(ret)) { |
213 | *lenout -= ret; | 213 | *lenout -= ret; |
214 | return -EFAULT; | 214 | return -EFAULT; |
215 | } | 215 | } |
216 | 216 | ||
217 | /* then get the rest (if any) from the beginning of the buffer */ | 217 | /* then get the rest (if any) from the beginning of the buffer */ |
218 | len -= l; | 218 | len -= l; |
219 | ret = copy_to_user(to + l, fifo->buffer, len); | 219 | ret = copy_to_user(to + l, fifo->buffer, len); |
220 | if (unlikely(ret)) { | 220 | if (unlikely(ret)) { |
221 | *lenout += len - ret; | 221 | *lenout += len - ret; |
222 | return -EFAULT; | 222 | return -EFAULT; |
223 | } | 223 | } |
224 | *lenout += len; | 224 | *lenout += len; |
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | unsigned int __kfifo_in_n(struct kfifo *fifo, | 228 | unsigned int __kfifo_in_n(struct kfifo *fifo, |
229 | const void *from, unsigned int len, unsigned int recsize) | 229 | const void *from, unsigned int len, unsigned int recsize) |
230 | { | 230 | { |
231 | if (kfifo_avail(fifo) < len + recsize) | 231 | if (kfifo_avail(fifo) < len + recsize) |
232 | return len + 1; | 232 | return len + 1; |
233 | 233 | ||
234 | __kfifo_in_data(fifo, from, len, recsize); | 234 | __kfifo_in_data(fifo, from, len, recsize); |
235 | return 0; | 235 | return 0; |
236 | } | 236 | } |
237 | EXPORT_SYMBOL(__kfifo_in_n); | 237 | EXPORT_SYMBOL(__kfifo_in_n); |
238 | 238 | ||
239 | /** | 239 | /** |
240 | * kfifo_in - puts some data into the FIFO | 240 | * kfifo_in - puts some data into the FIFO |
241 | * @fifo: the fifo to be used. | 241 | * @fifo: the fifo to be used. |
242 | * @from: the data to be added. | 242 | * @from: the data to be added. |
243 | * @len: the length of the data to be added. | 243 | * @len: the length of the data to be added. |
244 | * | 244 | * |
245 | * This function copies at most @len bytes from the @from buffer into | 245 | * This function copies at most @len bytes from the @from buffer into |
246 | * the FIFO depending on the free space, and returns the number of | 246 | * the FIFO depending on the free space, and returns the number of |
247 | * bytes copied. | 247 | * bytes copied. |
248 | * | 248 | * |
249 | * Note that with only one concurrent reader and one concurrent | 249 | * Note that with only one concurrent reader and one concurrent |
250 | * writer, you don't need extra locking to use these functions. | 250 | * writer, you don't need extra locking to use these functions. |
251 | */ | 251 | */ |
252 | unsigned int kfifo_in(struct kfifo *fifo, const void *from, | 252 | unsigned int kfifo_in(struct kfifo *fifo, const void *from, |
253 | unsigned int len) | 253 | unsigned int len) |
254 | { | 254 | { |
255 | len = min(kfifo_avail(fifo), len); | 255 | len = min(kfifo_avail(fifo), len); |
256 | 256 | ||
257 | __kfifo_in_data(fifo, from, len, 0); | 257 | __kfifo_in_data(fifo, from, len, 0); |
258 | __kfifo_add_in(fifo, len); | 258 | __kfifo_add_in(fifo, len); |
259 | return len; | 259 | return len; |
260 | } | 260 | } |
261 | EXPORT_SYMBOL(kfifo_in); | 261 | EXPORT_SYMBOL(kfifo_in); |
262 | 262 | ||
263 | unsigned int __kfifo_in_generic(struct kfifo *fifo, | 263 | unsigned int __kfifo_in_generic(struct kfifo *fifo, |
264 | const void *from, unsigned int len, unsigned int recsize) | 264 | const void *from, unsigned int len, unsigned int recsize) |
265 | { | 265 | { |
266 | return __kfifo_in_rec(fifo, from, len, recsize); | 266 | return __kfifo_in_rec(fifo, from, len, recsize); |
267 | } | 267 | } |
268 | EXPORT_SYMBOL(__kfifo_in_generic); | 268 | EXPORT_SYMBOL(__kfifo_in_generic); |
269 | 269 | ||
270 | unsigned int __kfifo_out_n(struct kfifo *fifo, | 270 | unsigned int __kfifo_out_n(struct kfifo *fifo, |
271 | void *to, unsigned int len, unsigned int recsize) | 271 | void *to, unsigned int len, unsigned int recsize) |
272 | { | 272 | { |
273 | if (kfifo_len(fifo) < len + recsize) | 273 | if (kfifo_len(fifo) < len + recsize) |
274 | return len; | 274 | return len; |
275 | 275 | ||
276 | __kfifo_out_data(fifo, to, len, recsize); | 276 | __kfifo_out_data(fifo, to, len, recsize); |
277 | __kfifo_add_out(fifo, len + recsize); | 277 | __kfifo_add_out(fifo, len + recsize); |
278 | return 0; | 278 | return 0; |
279 | } | 279 | } |
280 | EXPORT_SYMBOL(__kfifo_out_n); | 280 | EXPORT_SYMBOL(__kfifo_out_n); |
281 | 281 | ||
282 | /** | 282 | /** |
283 | * kfifo_out - gets some data from the FIFO | 283 | * kfifo_out - gets some data from the FIFO |
284 | * @fifo: the fifo to be used. | 284 | * @fifo: the fifo to be used. |
285 | * @to: where the data must be copied. | 285 | * @to: where the data must be copied. |
286 | * @len: the size of the destination buffer. | 286 | * @len: the size of the destination buffer. |
287 | * | 287 | * |
288 | * This function copies at most @len bytes from the FIFO into the | 288 | * This function copies at most @len bytes from the FIFO into the |
289 | * @to buffer and returns the number of copied bytes. | 289 | * @to buffer and returns the number of copied bytes. |
290 | * | 290 | * |
291 | * Note that with only one concurrent reader and one concurrent | 291 | * Note that with only one concurrent reader and one concurrent |
292 | * writer, you don't need extra locking to use these functions. | 292 | * writer, you don't need extra locking to use these functions. |
293 | */ | 293 | */ |
294 | unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len) | 294 | unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len) |
295 | { | 295 | { |
296 | len = min(kfifo_len(fifo), len); | 296 | len = min(kfifo_len(fifo), len); |
297 | 297 | ||
298 | __kfifo_out_data(fifo, to, len, 0); | 298 | __kfifo_out_data(fifo, to, len, 0); |
299 | __kfifo_add_out(fifo, len); | 299 | __kfifo_add_out(fifo, len); |
300 | 300 | ||
301 | return len; | 301 | return len; |
302 | } | 302 | } |
303 | EXPORT_SYMBOL(kfifo_out); | 303 | EXPORT_SYMBOL(kfifo_out); |
304 | 304 | ||
305 | /** | 305 | /** |
306 | * kfifo_out_peek - copy some data from the FIFO, but do not remove it | 306 | * kfifo_out_peek - copy some data from the FIFO, but do not remove it |
307 | * @fifo: the fifo to be used. | 307 | * @fifo: the fifo to be used. |
308 | * @to: where the data must be copied. | 308 | * @to: where the data must be copied. |
309 | * @len: the size of the destination buffer. | 309 | * @len: the size of the destination buffer. |
310 | * @offset: offset into the fifo | 310 | * @offset: offset into the fifo |
311 | * | 311 | * |
312 | * This function copies at most @len bytes at @offset from the FIFO | 312 | * This function copies at most @len bytes at @offset from the FIFO |
313 | * into the @to buffer and returns the number of copied bytes. | 313 | * into the @to buffer and returns the number of copied bytes. |
314 | * The data is not removed from the FIFO. | 314 | * The data is not removed from the FIFO. |
315 | */ | 315 | */ |
316 | unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, | 316 | unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, |
317 | unsigned offset) | 317 | unsigned offset) |
318 | { | 318 | { |
319 | len = min(kfifo_len(fifo), len + offset); | 319 | len = min(kfifo_len(fifo), len + offset); |
320 | 320 | ||
321 | __kfifo_out_data(fifo, to, len, offset); | 321 | __kfifo_out_data(fifo, to, len, offset); |
322 | return len; | 322 | return len; |
323 | } | 323 | } |
324 | EXPORT_SYMBOL(kfifo_out_peek); | 324 | EXPORT_SYMBOL(kfifo_out_peek); |
325 | 325 | ||
326 | unsigned int __kfifo_out_generic(struct kfifo *fifo, | 326 | unsigned int __kfifo_out_generic(struct kfifo *fifo, |
327 | void *to, unsigned int len, unsigned int recsize, | 327 | void *to, unsigned int len, unsigned int recsize, |
328 | unsigned int *total) | 328 | unsigned int *total) |
329 | { | 329 | { |
330 | return __kfifo_out_rec(fifo, to, len, recsize, total); | 330 | return __kfifo_out_rec(fifo, to, len, recsize, total); |
331 | } | 331 | } |
332 | EXPORT_SYMBOL(__kfifo_out_generic); | 332 | EXPORT_SYMBOL(__kfifo_out_generic); |
333 | 333 | ||
334 | unsigned int __kfifo_from_user_n(struct kfifo *fifo, | 334 | unsigned int __kfifo_from_user_n(struct kfifo *fifo, |
335 | const void __user *from, unsigned int len, unsigned int recsize) | 335 | const void __user *from, unsigned int len, unsigned int recsize) |
336 | { | 336 | { |
337 | unsigned total; | 337 | unsigned total; |
338 | 338 | ||
339 | if (kfifo_avail(fifo) < len + recsize) | 339 | if (kfifo_avail(fifo) < len + recsize) |
340 | return len + 1; | 340 | return len + 1; |
341 | 341 | ||
342 | __kfifo_from_user_data(fifo, from, len, recsize, &total); | 342 | __kfifo_from_user_data(fifo, from, len, recsize, &total); |
343 | return total; | 343 | return total; |
344 | } | 344 | } |
345 | EXPORT_SYMBOL(__kfifo_from_user_n); | 345 | EXPORT_SYMBOL(__kfifo_from_user_n); |
346 | 346 | ||
347 | /** | 347 | /** |
348 | * kfifo_from_user - puts some data from user space into the FIFO | 348 | * kfifo_from_user - puts some data from user space into the FIFO |
349 | * @fifo: the fifo to be used. | 349 | * @fifo: the fifo to be used. |
350 | * @from: pointer to the data to be added. | 350 | * @from: pointer to the data to be added. |
351 | * @len: the length of the data to be added. | 351 | * @len: the length of the data to be added. |
352 | * | 352 | * |
353 | * This function copies at most @len bytes from the @from into the | 353 | * This function copies at most @len bytes from the @from into the |
354 | * FIFO depending and returns -EFAULT/0. | 354 | * FIFO depending and returns -EFAULT/0. |
355 | * | 355 | * |
356 | * Note that with only one concurrent reader and one concurrent | 356 | * Note that with only one concurrent reader and one concurrent |
357 | * writer, you don't need extra locking to use these functions. | 357 | * writer, you don't need extra locking to use these functions. |
358 | */ | 358 | */ |
359 | int kfifo_from_user(struct kfifo *fifo, | 359 | int kfifo_from_user(struct kfifo *fifo, |
360 | const void __user *from, unsigned int len, unsigned *total) | 360 | const void __user *from, unsigned int len, unsigned *total) |
361 | { | 361 | { |
362 | int ret; | 362 | int ret; |
363 | len = min(kfifo_avail(fifo), len); | 363 | len = min(kfifo_avail(fifo), len); |
364 | ret = __kfifo_from_user_data(fifo, from, len, 0, total); | 364 | ret = __kfifo_from_user_data(fifo, from, len, 0, total); |
365 | if (ret) | 365 | if (ret) |
366 | return ret; | 366 | return ret; |
367 | __kfifo_add_in(fifo, len); | 367 | __kfifo_add_in(fifo, len); |
368 | return 0; | 368 | return 0; |
369 | } | 369 | } |
370 | EXPORT_SYMBOL(kfifo_from_user); | 370 | EXPORT_SYMBOL(kfifo_from_user); |
371 | 371 | ||
372 | unsigned int __kfifo_from_user_generic(struct kfifo *fifo, | 372 | unsigned int __kfifo_from_user_generic(struct kfifo *fifo, |
373 | const void __user *from, unsigned int len, unsigned int recsize) | 373 | const void __user *from, unsigned int len, unsigned int recsize) |
374 | { | 374 | { |
375 | return __kfifo_from_user_rec(fifo, from, len, recsize); | 375 | return __kfifo_from_user_rec(fifo, from, len, recsize); |
376 | } | 376 | } |
377 | EXPORT_SYMBOL(__kfifo_from_user_generic); | 377 | EXPORT_SYMBOL(__kfifo_from_user_generic); |
378 | 378 | ||
379 | unsigned int __kfifo_to_user_n(struct kfifo *fifo, | 379 | unsigned int __kfifo_to_user_n(struct kfifo *fifo, |
380 | void __user *to, unsigned int len, unsigned int reclen, | 380 | void __user *to, unsigned int len, unsigned int reclen, |
381 | unsigned int recsize) | 381 | unsigned int recsize) |
382 | { | 382 | { |
383 | unsigned int ret, total; | 383 | unsigned int ret, total; |
384 | 384 | ||
385 | if (kfifo_len(fifo) < reclen + recsize) | 385 | if (kfifo_len(fifo) < reclen + recsize) |
386 | return len; | 386 | return len; |
387 | 387 | ||
388 | ret = __kfifo_to_user_data(fifo, to, reclen, recsize, &total); | 388 | ret = __kfifo_to_user_data(fifo, to, reclen, recsize, &total); |
389 | 389 | ||
390 | if (likely(ret == 0)) | 390 | if (likely(ret == 0)) |
391 | __kfifo_add_out(fifo, reclen + recsize); | 391 | __kfifo_add_out(fifo, reclen + recsize); |
392 | 392 | ||
393 | return total; | 393 | return total; |
394 | } | 394 | } |
395 | EXPORT_SYMBOL(__kfifo_to_user_n); | 395 | EXPORT_SYMBOL(__kfifo_to_user_n); |
396 | 396 | ||
397 | /** | 397 | /** |
398 | * kfifo_to_user - gets data from the FIFO and write it to user space | 398 | * kfifo_to_user - gets data from the FIFO and write it to user space |
399 | * @fifo: the fifo to be used. | 399 | * @fifo: the fifo to be used. |
400 | * @to: where the data must be copied. | 400 | * @to: where the data must be copied. |
401 | * @len: the size of the destination buffer. | 401 | * @len: the size of the destination buffer. |
402 | @ @lenout: pointer to output variable with copied data | 402 | @ @lenout: pointer to output variable with copied data |
403 | * | 403 | * |
404 | * This function copies at most @len bytes from the FIFO into the | 404 | * This function copies at most @len bytes from the FIFO into the |
405 | * @to buffer and 0 or -EFAULT. | 405 | * @to buffer and 0 or -EFAULT. |
406 | * | 406 | * |
407 | * Note that with only one concurrent reader and one concurrent | 407 | * Note that with only one concurrent reader and one concurrent |
408 | * writer, you don't need extra locking to use these functions. | 408 | * writer, you don't need extra locking to use these functions. |
409 | */ | 409 | */ |
410 | int kfifo_to_user(struct kfifo *fifo, | 410 | int kfifo_to_user(struct kfifo *fifo, |
411 | void __user *to, unsigned int len, unsigned *lenout) | 411 | void __user *to, unsigned int len, unsigned *lenout) |
412 | { | 412 | { |
413 | int ret; | 413 | int ret; |
414 | len = min(kfifo_len(fifo), len); | 414 | len = min(kfifo_len(fifo), len); |
415 | ret = __kfifo_to_user_data(fifo, to, len, 0, lenout); | 415 | ret = __kfifo_to_user_data(fifo, to, len, 0, lenout); |
416 | __kfifo_add_out(fifo, *lenout); | 416 | __kfifo_add_out(fifo, *lenout); |
417 | return ret; | 417 | return ret; |
418 | } | 418 | } |
419 | EXPORT_SYMBOL(kfifo_to_user); | 419 | EXPORT_SYMBOL(kfifo_to_user); |
420 | 420 | ||
421 | unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | 421 | unsigned int __kfifo_to_user_generic(struct kfifo *fifo, |
422 | void __user *to, unsigned int len, unsigned int recsize, | 422 | void __user *to, unsigned int len, unsigned int recsize, |
423 | unsigned int *total) | 423 | unsigned int *total) |
424 | { | 424 | { |
425 | return __kfifo_to_user_rec(fifo, to, len, recsize, total); | 425 | return __kfifo_to_user_rec(fifo, to, len, recsize, total); |
426 | } | 426 | } |
427 | EXPORT_SYMBOL(__kfifo_to_user_generic); | 427 | EXPORT_SYMBOL(__kfifo_to_user_generic); |
428 | 428 | ||
429 | unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize) | 429 | unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize) |
430 | { | 430 | { |
431 | if (recsize == 0) | 431 | if (recsize == 0) |
432 | return kfifo_avail(fifo); | 432 | return kfifo_avail(fifo); |
433 | 433 | ||
434 | return __kfifo_peek_n(fifo, recsize); | 434 | return __kfifo_peek_n(fifo, recsize); |
435 | } | 435 | } |
436 | EXPORT_SYMBOL(__kfifo_peek_generic); | 436 | EXPORT_SYMBOL(__kfifo_peek_generic); |
437 | 437 | ||
438 | void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize) | 438 | void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize) |
439 | { | 439 | { |
440 | __kfifo_skip_rec(fifo, recsize); | 440 | __kfifo_skip_rec(fifo, recsize); |
441 | } | 441 | } |
442 | EXPORT_SYMBOL(__kfifo_skip_generic); | 442 | EXPORT_SYMBOL(__kfifo_skip_generic); |
443 | 443 | ||
444 | 444 |