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 */ 31struct 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 42struct 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 52int 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 56void rxe_queue_reset(struct rxe_queue *q); 57 58struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, 59 int *num_elem, 60 unsigned int elem_size); 61 62int 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 70void rxe_queue_cleanup(struct rxe_queue *queue); 71 72static inline int next_index(struct rxe_queue *q, int index) 73{ 74 return (index + 1) & q->buf->index_mask; 75} 76 77static 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 83static 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 89static 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 95static 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 101static 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 107static 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 113static inline unsigned int producer_index(struct rxe_queue *q) 114{ 115 return q->buf->producer_index; 116} 117 118static inline unsigned int consumer_index(struct rxe_queue *q) 119{ 120 return q->buf->consumer_index; 121} 122 123static 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 129static 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 136static 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 142static 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