• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include <common/bk_include.h>
22 #include <common/bk_generic.h>
23 #include <common/bk_compiler.h>
24 #include <os/mem.h>
25 #include <os/os.h>
26 
27 typedef struct kfifo
28 {
29 	unsigned int in;
30 	unsigned int out;
31 
32 	unsigned int mask;
33 
34 	unsigned int size;
35 	unsigned char *buffer;
36 } kfifo_t, *kfifo_ptr_t;
37 
38 /**
39  * kfifo_init - allocates a new FIFO using a preallocated buffer
40  * @buffer: the preallocated buffer to be used.
41  * @size: the size of the internal buffer, this have to be a power of 2.
42  * @gfp_mask: get_free_pages mask, passed to ke_malloc()
43  * @lock: the lock to be used to protect the fifo buffer
44  *
45  * Do NOT pass the kfifo to kfifo_free() after use ! Simply free the
46  * struct kfifo with ke_free().
47  */
kfifo_init(unsigned char * buffer,unsigned int size)48 __BK_INLINE struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size)
49 {
50 	struct kfifo *fifo;
51 
52 	/* size must be a power of 2 */
53 	//BK_ASSERT(size & (size - 1));
54 
55 	fifo = os_malloc(sizeof(struct kfifo));
56 	if (!fifo)
57 		return NULLPTR;
58 
59 	fifo->buffer = buffer;
60 	fifo->size = size;
61 	fifo->in = 0;
62 	fifo->out = 0;
63 	fifo->mask = fifo->size - 1;
64 
65 	return fifo;
66 }
67 
68 /**
69  * kfifo_alloc - allocates a new FIFO and its internal buffer
70  * @size: the size of the internal buffer to be allocated.
71  * @gfp_mask: get_free_pages mask, passed to ke_malloc()
72  * @lock: the lock to be used to protect the fifo buffer
73  *
74  * The size will be rounded-up to a power of 2.
75  */
kfifo_alloc(unsigned int size)76 __BK_INLINE struct kfifo *kfifo_alloc(unsigned int size)
77 {
78 	unsigned char *buffer;
79 	struct kfifo *ret;
80 
81 	buffer = os_malloc(size);
82 	if (!buffer)
83 		return 0;
84 	os_memset(buffer, 0, size);
85 
86 	ret = kfifo_init(buffer, size);
87 
88 	if (!(ret))
89 		os_free(buffer);
90 
91 	return ret;
92 }
93 
94 /**
95  * kfifo_free - frees the FIFO
96  * @fifo: the fifo to be freed.
97  */
kfifo_free(struct kfifo * fifo)98 __BK_INLINE void kfifo_free(struct kfifo *fifo)
99 {
100 	os_free(fifo->buffer);
101 	fifo->buffer = 0;
102 
103 	os_free(fifo);
104 }
105 
106 /**
107  * __kfifo_put - puts some data into the FIFO, no locking version
108  * @fifo: the fifo to be used.
109  * @buffer: the data to be added.
110  * @len: the length of the data to be added.
111  *
112  * This function copies at most 'len' bytes from the 'buffer' into
113  * the FIFO depending on the free space, and returns the number of
114  * bytes copied.
115  *
116  * Note that with only one concurrent reader and one concurrent
117  * writer, you don't need extra locking to use these functions.
118  */
kfifo_put(struct kfifo * fifo,unsigned char * buffer,unsigned int len)119 __BK_INLINE unsigned int kfifo_put(struct kfifo *fifo,
120 			 unsigned char *buffer, unsigned int len)
121 {
122 	unsigned int l;
123     GLOBAL_INT_DECLARATION();
124 
125     GLOBAL_INT_DISABLE();
126 	len = min(len, fifo->size - fifo->in + fifo->out);
127 
128 	/* first put the data starting from fifo->in to buffer end */
129 	l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
130 	os_memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
131 
132 	/* then put the rest (if any) at the beginning of the buffer */
133 	os_memcpy(fifo->buffer, buffer + l, len - l);
134 
135 	fifo->in += len;
136     GLOBAL_INT_RESTORE();
137 
138 	return len;
139 }
140 
141 /**
142  * __kfifo_get - gets some data from the FIFO, no locking version
143  * @fifo: the fifo to be used.
144  * @buffer: where the data must be copied.
145  * @len: the size of the destination buffer.
146  *
147  * This function copies at most 'len' bytes from the FIFO into the
148  * 'buffer' and returns the number of copied bytes.
149  *
150  * Note that with only one concurrent reader and one concurrent
151  * writer, you don't need extra locking to use these functions.
152  */
kfifo_get(struct kfifo * fifo,unsigned char * buffer,unsigned int len)153 __BK_INLINE unsigned int kfifo_get(struct kfifo *fifo,
154 			 unsigned char *buffer, unsigned int len)
155 {
156 	unsigned int l;
157     GLOBAL_INT_DECLARATION();
158 
159     GLOBAL_INT_DISABLE();
160 	len = min(len, fifo->in - fifo->out);
161 
162 	/* first get the data from fifo->out until the end of the buffer */
163 	l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
164 	os_memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
165 
166 	/* then get the rest (if any) from the beginning of the buffer */
167 	os_memcpy(buffer + l, fifo->buffer, len - l);
168 
169 	fifo->out += len;
170 
171 	if (fifo->out == fifo->in) {
172 		fifo->in = 0;
173 		fifo->out = 0;
174 	}
175     GLOBAL_INT_RESTORE();
176 
177 	return len;
178 }
179 
kfifo_data_size(struct kfifo * fifo)180 __BK_INLINE unsigned int kfifo_data_size(struct kfifo *fifo)
181 {
182 	return (fifo->in - fifo->out);
183 }
184 
kfifo_unused(struct kfifo * fifo)185 __BK_INLINE unsigned int kfifo_unused(struct kfifo *fifo)
186 {
187 	return (fifo->mask + 1) - (fifo->in - fifo->out);
188 }
189 
kfifo_copy_out(struct kfifo * fifo,void * dst,unsigned int len,unsigned int off)190 __BK_INLINE void kfifo_copy_out(struct kfifo *fifo, void *dst,
191 		unsigned int len, unsigned int off)
192 {
193 	unsigned int size = fifo->mask + 1;
194 	unsigned int l;
195 
196 	off &= fifo->mask;
197 
198 	l = min(len, size - off);
199 
200 	os_memcpy(dst, (void *)(fifo->buffer + off), l);
201 	os_memcpy((void *)((unsigned int)dst + l), (void *)fifo->buffer, len - l);
202 	/*
203 	 * make sure that the data is copied before
204 	 * incrementing the fifo->out index counter
205 	 */
206 }
207 
kfifo_out_peek(struct kfifo * fifo,unsigned char * buffer,unsigned int len)208 __BK_INLINE unsigned int kfifo_out_peek(struct kfifo *fifo,
209 			 unsigned char *buffer, unsigned int len)
210 {
211 	unsigned int l;
212 
213 	l = fifo->in - fifo->out;
214 	if (len > l)
215 		len = l;
216 
217 	kfifo_copy_out(fifo, buffer, len, fifo->out);
218 
219 	return len;
220 }
221 
222 #ifdef __cplusplus
223 }
224 #endif
225