1
2
3
4
5
6
7#ifndef RXE_QUEUE_H
8#define RXE_QUEUE_H
9
10
11#include <uapi/rdma/rdma_user_rxe.h>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37enum queue_type {
38 QUEUE_TYPE_KERNEL,
39 QUEUE_TYPE_TO_USER,
40 QUEUE_TYPE_FROM_USER,
41};
42
43struct rxe_queue {
44 struct rxe_dev *rxe;
45 struct rxe_queue_buf *buf;
46 struct rxe_mmap_info *ip;
47 size_t buf_size;
48 size_t elem_size;
49 unsigned int log2_elem_size;
50 u32 index_mask;
51 enum queue_type type;
52
53
54
55
56
57 u32 index;
58};
59
60int do_mmap_info(struct rxe_dev *rxe, struct mminfo __user *outbuf,
61 struct ib_udata *udata, struct rxe_queue_buf *buf,
62 size_t buf_size, struct rxe_mmap_info **ip_p);
63
64void rxe_queue_reset(struct rxe_queue *q);
65
66struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, int *num_elem,
67 unsigned int elem_size, enum queue_type type);
68
69int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
70 unsigned int elem_size, struct ib_udata *udata,
71 struct mminfo __user *outbuf,
72
73 spinlock_t *producer_lock,
74
75 spinlock_t *consumer_lock);
76
77void rxe_queue_cleanup(struct rxe_queue *queue);
78
79static inline int next_index(struct rxe_queue *q, int index)
80{
81 return (index + 1) & q->buf->index_mask;
82}
83
84static inline int queue_empty(struct rxe_queue *q, enum queue_type type)
85{
86 u32 prod;
87 u32 cons;
88
89 switch (type) {
90 case QUEUE_TYPE_FROM_USER:
91
92 prod = smp_load_acquire(&q->buf->producer_index);
93 cons = q->index;
94 break;
95 case QUEUE_TYPE_TO_USER:
96 prod = q->index;
97
98 cons = smp_load_acquire(&q->buf->consumer_index);
99 break;
100 case QUEUE_TYPE_KERNEL:
101 prod = q->buf->producer_index;
102 cons = q->buf->consumer_index;
103 break;
104 }
105
106 return ((prod - cons) & q->index_mask) == 0;
107}
108
109static inline int queue_full(struct rxe_queue *q, enum queue_type type)
110{
111 u32 prod;
112 u32 cons;
113
114 switch (type) {
115 case QUEUE_TYPE_FROM_USER:
116
117 prod = smp_load_acquire(&q->buf->producer_index);
118 cons = q->index;
119 break;
120 case QUEUE_TYPE_TO_USER:
121 prod = q->index;
122
123 cons = smp_load_acquire(&q->buf->consumer_index);
124 break;
125 case QUEUE_TYPE_KERNEL:
126 prod = q->buf->producer_index;
127 cons = q->buf->consumer_index;
128 break;
129 }
130
131 return ((prod + 1 - cons) & q->index_mask) == 0;
132}
133
134static inline unsigned int queue_count(const struct rxe_queue *q,
135 enum queue_type type)
136{
137 u32 prod;
138 u32 cons;
139
140 switch (type) {
141 case QUEUE_TYPE_FROM_USER:
142
143 prod = smp_load_acquire(&q->buf->producer_index);
144 cons = q->index;
145 break;
146 case QUEUE_TYPE_TO_USER:
147 prod = q->index;
148
149 cons = smp_load_acquire(&q->buf->consumer_index);
150 break;
151 case QUEUE_TYPE_KERNEL:
152 prod = q->buf->producer_index;
153 cons = q->buf->consumer_index;
154 break;
155 }
156
157 return (prod - cons) & q->index_mask;
158}
159
160static inline void advance_producer(struct rxe_queue *q, enum queue_type type)
161{
162 u32 prod;
163
164 switch (type) {
165 case QUEUE_TYPE_FROM_USER:
166 pr_warn_once("Normally kernel should not write user space index\n");
167
168 prod = smp_load_acquire(&q->buf->producer_index);
169 prod = (prod + 1) & q->index_mask;
170
171 smp_store_release(&q->buf->producer_index, prod);
172 break;
173 case QUEUE_TYPE_TO_USER:
174 prod = q->index;
175 q->index = (prod + 1) & q->index_mask;
176 q->buf->producer_index = q->index;
177 break;
178 case QUEUE_TYPE_KERNEL:
179 prod = q->buf->producer_index;
180 q->buf->producer_index = (prod + 1) & q->index_mask;
181 break;
182 }
183}
184
185static inline void advance_consumer(struct rxe_queue *q, enum queue_type type)
186{
187 u32 cons;
188
189 switch (type) {
190 case QUEUE_TYPE_FROM_USER:
191 cons = q->index;
192 q->index = (cons + 1) & q->index_mask;
193 q->buf->consumer_index = q->index;
194 break;
195 case QUEUE_TYPE_TO_USER:
196 pr_warn_once("Normally kernel should not write user space index\n");
197
198 cons = smp_load_acquire(&q->buf->consumer_index);
199 cons = (cons + 1) & q->index_mask;
200
201 smp_store_release(&q->buf->consumer_index, cons);
202 break;
203 case QUEUE_TYPE_KERNEL:
204 cons = q->buf->consumer_index;
205 q->buf->consumer_index = (cons + 1) & q->index_mask;
206 break;
207 }
208}
209
210static inline void *producer_addr(struct rxe_queue *q, enum queue_type type)
211{
212 u32 prod;
213
214 switch (type) {
215 case QUEUE_TYPE_FROM_USER:
216
217 prod = smp_load_acquire(&q->buf->producer_index);
218 prod &= q->index_mask;
219 break;
220 case QUEUE_TYPE_TO_USER:
221 prod = q->index;
222 break;
223 case QUEUE_TYPE_KERNEL:
224 prod = q->buf->producer_index;
225 break;
226 }
227
228 return q->buf->data + (prod << q->log2_elem_size);
229}
230
231static inline void *consumer_addr(struct rxe_queue *q, enum queue_type type)
232{
233 u32 cons;
234
235 switch (type) {
236 case QUEUE_TYPE_FROM_USER:
237 cons = q->index;
238 break;
239 case QUEUE_TYPE_TO_USER:
240
241 cons = smp_load_acquire(&q->buf->consumer_index);
242 cons &= q->index_mask;
243 break;
244 case QUEUE_TYPE_KERNEL:
245 cons = q->buf->consumer_index;
246 break;
247 }
248
249 return q->buf->data + (cons << q->log2_elem_size);
250}
251
252static inline unsigned int producer_index(struct rxe_queue *q,
253 enum queue_type type)
254{
255 u32 prod;
256
257 switch (type) {
258 case QUEUE_TYPE_FROM_USER:
259
260 prod = smp_load_acquire(&q->buf->producer_index);
261 prod &= q->index_mask;
262 break;
263 case QUEUE_TYPE_TO_USER:
264 prod = q->index;
265 break;
266 case QUEUE_TYPE_KERNEL:
267 prod = q->buf->producer_index;
268 break;
269 }
270
271 return prod;
272}
273
274static inline unsigned int consumer_index(struct rxe_queue *q,
275 enum queue_type type)
276{
277 u32 cons;
278
279 switch (type) {
280 case QUEUE_TYPE_FROM_USER:
281 cons = q->index;
282 break;
283 case QUEUE_TYPE_TO_USER:
284
285 cons = smp_load_acquire(&q->buf->consumer_index);
286 cons &= q->index_mask;
287 break;
288 case QUEUE_TYPE_KERNEL:
289 cons = q->buf->consumer_index;
290 break;
291 }
292
293 return cons;
294}
295
296static inline void *addr_from_index(struct rxe_queue *q,
297 unsigned int index)
298{
299 return q->buf->data + ((index & q->index_mask)
300 << q->buf->log2_elem_size);
301}
302
303static inline unsigned int index_from_addr(const struct rxe_queue *q,
304 const void *addr)
305{
306 return (((u8 *)addr - q->buf->data) >> q->log2_elem_size)
307 & q->index_mask;
308}
309
310static inline void *queue_head(struct rxe_queue *q, enum queue_type type)
311{
312 return queue_empty(q, type) ? NULL : consumer_addr(q, type);
313}
314
315#endif
316