1 /* 2 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved. 3 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #ifndef RXE_QUEUE_H 35 #define RXE_QUEUE_H 36 37 /* implements a simple circular buffer that can optionally be 38 * shared between user space and the kernel and can be resized 39 40 * the requested element size is rounded up to a power of 2 41 * and the number of elements in the buffer is also rounded 42 * up to a power of 2. Since the queue is empty when the 43 * producer and consumer indices match the maximum capacity 44 * of the queue is one less than the number of element slots 45 */ 46 47 /* this data structure is shared between user space and kernel 48 * space for those cases where the queue is shared. It contains 49 * the producer and consumer indices. Is also contains a copy 50 * of the queue size parameters for user space to use but the 51 * kernel must use the parameters in the rxe_queue struct 52 * this MUST MATCH the corresponding librxe struct 53 * for performance reasons arrange to have producer and consumer 54 * pointers in separate cache lines 55 * the kernel should always mask the indices to avoid accessing 56 * memory outside of the data area 57 */ 58 struct rxe_queue_buf { 59 __u32 log2_elem_size; 60 __u32 index_mask; 61 __u32 pad_1[30]; 62 __u32 producer_index; 63 __u32 pad_2[31]; 64 __u32 consumer_index; 65 __u32 pad_3[31]; 66 __u8 data[0]; 67 }; 68 69 struct rxe_queue { 70 struct rxe_dev *rxe; 71 struct rxe_queue_buf *buf; 72 struct rxe_mmap_info *ip; 73 size_t buf_size; 74 size_t elem_size; 75 unsigned int log2_elem_size; 76 unsigned int index_mask; 77 }; 78 79 int do_mmap_info(struct rxe_dev *rxe, 80 struct ib_udata *udata, 81 bool is_req, 82 struct ib_ucontext *context, 83 struct rxe_queue_buf *buf, 84 size_t buf_size, 85 struct rxe_mmap_info **ip_p); 86 87 struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, 88 int *num_elem, 89 unsigned int elem_size); 90 91 int rxe_queue_resize(struct rxe_queue *q, 92 unsigned int *num_elem_p, 93 unsigned int elem_size, 94 struct ib_ucontext *context, 95 struct ib_udata *udata, 96 /* Protect producers while resizing queue */ 97 spinlock_t *producer_lock, 98 /* Protect consumers while resizing queue */ 99 spinlock_t *consumer_lock); 100 101 void rxe_queue_cleanup(struct rxe_queue *queue); 102 103 static inline int next_index(struct rxe_queue *q, int index) 104 { 105 return (index + 1) & q->buf->index_mask; 106 } 107 108 static inline int queue_empty(struct rxe_queue *q) 109 { 110 return ((q->buf->producer_index - q->buf->consumer_index) 111 & q->index_mask) == 0; 112 } 113 114 static inline int queue_full(struct rxe_queue *q) 115 { 116 return ((q->buf->producer_index + 1 - q->buf->consumer_index) 117 & q->index_mask) == 0; 118 } 119 120 static inline void advance_producer(struct rxe_queue *q) 121 { 122 q->buf->producer_index = (q->buf->producer_index + 1) 123 & q->index_mask; 124 } 125 126 static inline void advance_consumer(struct rxe_queue *q) 127 { 128 q->buf->consumer_index = (q->buf->consumer_index + 1) 129 & q->index_mask; 130 } 131 132 static inline void *producer_addr(struct rxe_queue *q) 133 { 134 return q->buf->data + ((q->buf->producer_index & q->index_mask) 135 << q->log2_elem_size); 136 } 137 138 static inline void *consumer_addr(struct rxe_queue *q) 139 { 140 return q->buf->data + ((q->buf->consumer_index & q->index_mask) 141 << q->log2_elem_size); 142 } 143 144 static inline unsigned int producer_index(struct rxe_queue *q) 145 { 146 return q->buf->producer_index; 147 } 148 149 static inline unsigned int consumer_index(struct rxe_queue *q) 150 { 151 return q->buf->consumer_index; 152 } 153 154 static inline void *addr_from_index(struct rxe_queue *q, unsigned int index) 155 { 156 return q->buf->data + ((index & q->index_mask) 157 << q->buf->log2_elem_size); 158 } 159 160 static inline unsigned int index_from_addr(const struct rxe_queue *q, 161 const void *addr) 162 { 163 return (((u8 *)addr - q->buf->data) >> q->log2_elem_size) 164 & q->index_mask; 165 } 166 167 static inline unsigned int queue_count(const struct rxe_queue *q) 168 { 169 return (q->buf->producer_index - q->buf->consumer_index) 170 & q->index_mask; 171 } 172 173 static inline void *queue_head(struct rxe_queue *q) 174 { 175 return queue_empty(q) ? NULL : consumer_addr(q); 176 } 177 178 #endif /* RXE_QUEUE_H */ 179