1 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2 /*
3  * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4  * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
5  */
6 
7 #ifndef RXE_QUEUE_H
8 #define RXE_QUEUE_H
9 
10 /* implements a simple circular buffer that can optionally be
11  * shared between user space and the kernel and can be resized
12 
13  * the requested element size is rounded up to a power of 2
14  * and the number of elements in the buffer is also rounded
15  * up to a power of 2. Since the queue is empty when the
16  * producer and consumer indices match the maximum capacity
17  * of the queue is one less than the number of element slots
18  */
19 
20 /* this data structure is shared between user space and kernel
21  * space for those cases where the queue is shared. It contains
22  * the producer and consumer indices. Is also contains a copy
23  * of the queue size parameters for user space to use but the
24  * kernel must use the parameters in the rxe_queue struct
25  * this MUST MATCH the corresponding librxe struct
26  * for performance reasons arrange to have producer and consumer
27  * pointers in separate cache lines
28  * the kernel should always mask the indices to avoid accessing
29  * memory outside of the data area
30  */
31 struct rxe_queue_buf {
32 	__u32			log2_elem_size;
33 	__u32			index_mask;
34 	__u32			pad_1[30];
35 	__u32			producer_index;
36 	__u32			pad_2[31];
37 	__u32			consumer_index;
38 	__u32			pad_3[31];
39 	__u8			data[];
40 };
41 
42 struct rxe_queue {
43 	struct rxe_dev		*rxe;
44 	struct rxe_queue_buf	*buf;
45 	struct rxe_mmap_info	*ip;
46 	size_t			buf_size;
47 	size_t			elem_size;
48 	unsigned int		log2_elem_size;
49 	unsigned int		index_mask;
50 };
51 
52 int do_mmap_info(struct rxe_dev *rxe, struct mminfo __user *outbuf,
53 		 struct ib_udata *udata, struct rxe_queue_buf *buf,
54 		 size_t buf_size, struct rxe_mmap_info **ip_p);
55 
56 void rxe_queue_reset(struct rxe_queue *q);
57 
58 struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe,
59 				 int *num_elem,
60 				 unsigned int elem_size);
61 
62 int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
63 		     unsigned int elem_size, struct ib_udata *udata,
64 		     struct mminfo __user *outbuf,
65 		     /* Protect producers while resizing queue */
66 		     spinlock_t *producer_lock,
67 		     /* Protect consumers while resizing queue */
68 		     spinlock_t *consumer_lock);
69 
70 void rxe_queue_cleanup(struct rxe_queue *queue);
71 
72 static inline int next_index(struct rxe_queue *q, int index)
73 {
74 	return (index + 1) & q->buf->index_mask;
75 }
76 
77 static inline int queue_empty(struct rxe_queue *q)
78 {
79 	return ((q->buf->producer_index - q->buf->consumer_index)
80 			& q->index_mask) == 0;
81 }
82 
83 static inline int queue_full(struct rxe_queue *q)
84 {
85 	return ((q->buf->producer_index + 1 - q->buf->consumer_index)
86 			& q->index_mask) == 0;
87 }
88 
89 static inline void advance_producer(struct rxe_queue *q)
90 {
91 	q->buf->producer_index = (q->buf->producer_index + 1)
92 			& q->index_mask;
93 }
94 
95 static inline void advance_consumer(struct rxe_queue *q)
96 {
97 	q->buf->consumer_index = (q->buf->consumer_index + 1)
98 			& q->index_mask;
99 }
100 
101 static inline void *producer_addr(struct rxe_queue *q)
102 {
103 	return q->buf->data + ((q->buf->producer_index & q->index_mask)
104 				<< q->log2_elem_size);
105 }
106 
107 static inline void *consumer_addr(struct rxe_queue *q)
108 {
109 	return q->buf->data + ((q->buf->consumer_index & q->index_mask)
110 				<< q->log2_elem_size);
111 }
112 
113 static inline unsigned int producer_index(struct rxe_queue *q)
114 {
115 	return q->buf->producer_index;
116 }
117 
118 static inline unsigned int consumer_index(struct rxe_queue *q)
119 {
120 	return q->buf->consumer_index;
121 }
122 
123 static inline void *addr_from_index(struct rxe_queue *q, unsigned int index)
124 {
125 	return q->buf->data + ((index & q->index_mask)
126 				<< q->buf->log2_elem_size);
127 }
128 
129 static inline unsigned int index_from_addr(const struct rxe_queue *q,
130 					   const void *addr)
131 {
132 	return (((u8 *)addr - q->buf->data) >> q->log2_elem_size)
133 		& q->index_mask;
134 }
135 
136 static inline unsigned int queue_count(const struct rxe_queue *q)
137 {
138 	return (q->buf->producer_index - q->buf->consumer_index)
139 		& q->index_mask;
140 }
141 
142 static inline void *queue_head(struct rxe_queue *q)
143 {
144 	return queue_empty(q) ? NULL : consumer_addr(q);
145 }
146 
147 #endif /* RXE_QUEUE_H */
148