1 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
10 /* for definition of shared struct rxe_queue_buf */
11 #include <uapi/rdma/rdma_user_rxe.h>
13 /* implements a simple circular buffer that can optionally be
14 * shared between user space and the kernel and can be resized
15 * the requested element size is rounded up to a power of 2
16 * and the number of elements in the buffer is also rounded
17 * up to a power of 2. Since the queue is empty when the
18 * producer and consumer indices match the maximum capacity
19 * of the queue is one less than the number of element slots
24 struct rxe_queue_buf *buf;
25 struct rxe_mmap_info *ip;
28 unsigned int log2_elem_size;
32 int do_mmap_info(struct rxe_dev *rxe, struct mminfo __user *outbuf,
33 struct ib_udata *udata, struct rxe_queue_buf *buf,
34 size_t buf_size, struct rxe_mmap_info **ip_p);
36 void rxe_queue_reset(struct rxe_queue *q);
38 struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe,
40 unsigned int elem_size);
42 int rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p,
43 unsigned int elem_size, struct ib_udata *udata,
44 struct mminfo __user *outbuf,
45 /* Protect producers while resizing queue */
46 spinlock_t *producer_lock,
47 /* Protect consumers while resizing queue */
48 spinlock_t *consumer_lock);
50 void rxe_queue_cleanup(struct rxe_queue *queue);
52 static inline int next_index(struct rxe_queue *q, int index)
54 return (index + 1) & q->buf->index_mask;
57 static inline int queue_empty(struct rxe_queue *q)
62 /* make sure all changes to queue complete before
65 prod = smp_load_acquire(&q->buf->producer_index);
67 cons = smp_load_acquire(&q->buf->consumer_index);
69 return ((prod - cons) & q->index_mask) == 0;
72 static inline int queue_full(struct rxe_queue *q)
77 /* make sure all changes to queue complete before
80 prod = smp_load_acquire(&q->buf->producer_index);
82 cons = smp_load_acquire(&q->buf->consumer_index);
84 return ((prod + 1 - cons) & q->index_mask) == 0;
87 static inline void advance_producer(struct rxe_queue *q)
91 prod = (q->buf->producer_index + 1) & q->index_mask;
93 /* make sure all changes to queue complete before
94 * changing producer index
96 smp_store_release(&q->buf->producer_index, prod);
99 static inline void advance_consumer(struct rxe_queue *q)
103 cons = (q->buf->consumer_index + 1) & q->index_mask;
105 /* make sure all changes to queue complete before
106 * changing consumer index
108 smp_store_release(&q->buf->consumer_index, cons);
111 static inline void *producer_addr(struct rxe_queue *q)
113 return q->buf->data + ((q->buf->producer_index & q->index_mask)
114 << q->log2_elem_size);
117 static inline void *consumer_addr(struct rxe_queue *q)
119 return q->buf->data + ((q->buf->consumer_index & q->index_mask)
120 << q->log2_elem_size);
123 static inline unsigned int producer_index(struct rxe_queue *q)
127 /* make sure all changes to queue
128 * complete before getting producer index
130 index = smp_load_acquire(&q->buf->producer_index);
131 index &= q->index_mask;
136 static inline unsigned int consumer_index(struct rxe_queue *q)
140 /* make sure all changes to queue
141 * complete before getting consumer index
143 index = smp_load_acquire(&q->buf->consumer_index);
144 index &= q->index_mask;
149 static inline void *addr_from_index(struct rxe_queue *q, unsigned int index)
151 return q->buf->data + ((index & q->index_mask)
152 << q->buf->log2_elem_size);
155 static inline unsigned int index_from_addr(const struct rxe_queue *q,
158 return (((u8 *)addr - q->buf->data) >> q->log2_elem_size)
162 static inline unsigned int queue_count(const struct rxe_queue *q)
164 return (q->buf->producer_index - q->buf->consumer_index)
168 static inline void *queue_head(struct rxe_queue *q)
170 return queue_empty(q) ? NULL : consumer_addr(q);
173 #endif /* RXE_QUEUE_H */