18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef RXE_QUEUE_H 88c2ecf20Sopenharmony_ci#define RXE_QUEUE_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* implements a simple circular buffer that can optionally be 118c2ecf20Sopenharmony_ci * shared between user space and the kernel and can be resized 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci * the requested element size is rounded up to a power of 2 148c2ecf20Sopenharmony_ci * and the number of elements in the buffer is also rounded 158c2ecf20Sopenharmony_ci * up to a power of 2. Since the queue is empty when the 168c2ecf20Sopenharmony_ci * producer and consumer indices match the maximum capacity 178c2ecf20Sopenharmony_ci * of the queue is one less than the number of element slots 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* this data structure is shared between user space and kernel 218c2ecf20Sopenharmony_ci * space for those cases where the queue is shared. It contains 228c2ecf20Sopenharmony_ci * the producer and consumer indices. Is also contains a copy 238c2ecf20Sopenharmony_ci * of the queue size parameters for user space to use but the 248c2ecf20Sopenharmony_ci * kernel must use the parameters in the rxe_queue struct 258c2ecf20Sopenharmony_ci * this MUST MATCH the corresponding librxe struct 268c2ecf20Sopenharmony_ci * for performance reasons arrange to have producer and consumer 278c2ecf20Sopenharmony_ci * pointers in separate cache lines 288c2ecf20Sopenharmony_ci * the kernel should always mask the indices to avoid accessing 298c2ecf20Sopenharmony_ci * memory outside of the data area 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_cistruct rxe_queue_buf { 328c2ecf20Sopenharmony_ci __u32 log2_elem_size; 338c2ecf20Sopenharmony_ci __u32 index_mask; 348c2ecf20Sopenharmony_ci __u32 pad_1[30]; 358c2ecf20Sopenharmony_ci __u32 producer_index; 368c2ecf20Sopenharmony_ci __u32 pad_2[31]; 378c2ecf20Sopenharmony_ci __u32 consumer_index; 388c2ecf20Sopenharmony_ci __u32 pad_3[31]; 398c2ecf20Sopenharmony_ci __u8 data[]; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct rxe_queue { 438c2ecf20Sopenharmony_ci struct rxe_dev *rxe; 448c2ecf20Sopenharmony_ci struct rxe_queue_buf *buf; 458c2ecf20Sopenharmony_ci struct rxe_mmap_info *ip; 468c2ecf20Sopenharmony_ci size_t buf_size; 478c2ecf20Sopenharmony_ci size_t elem_size; 488c2ecf20Sopenharmony_ci unsigned int log2_elem_size; 498c2ecf20Sopenharmony_ci unsigned int index_mask; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint do_mmap_info(struct rxe_dev *rxe, struct mminfo __user *outbuf, 538c2ecf20Sopenharmony_ci struct ib_udata *udata, struct rxe_queue_buf *buf, 548c2ecf20Sopenharmony_ci size_t buf_size, struct rxe_mmap_info **ip_p); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_civoid rxe_queue_reset(struct rxe_queue *q); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, 598c2ecf20Sopenharmony_ci int *num_elem, 608c2ecf20Sopenharmony_ci unsigned int elem_size); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciint rxe_queue_resize(struct rxe_queue *q, unsigned int *num_elem_p, 638c2ecf20Sopenharmony_ci unsigned int elem_size, struct ib_udata *udata, 648c2ecf20Sopenharmony_ci struct mminfo __user *outbuf, 658c2ecf20Sopenharmony_ci /* Protect producers while resizing queue */ 668c2ecf20Sopenharmony_ci spinlock_t *producer_lock, 678c2ecf20Sopenharmony_ci /* Protect consumers while resizing queue */ 688c2ecf20Sopenharmony_ci spinlock_t *consumer_lock); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_civoid rxe_queue_cleanup(struct rxe_queue *queue); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline int next_index(struct rxe_queue *q, int index) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci return (index + 1) & q->buf->index_mask; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic inline int queue_empty(struct rxe_queue *q) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci return ((q->buf->producer_index - q->buf->consumer_index) 808c2ecf20Sopenharmony_ci & q->index_mask) == 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline int queue_full(struct rxe_queue *q) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci return ((q->buf->producer_index + 1 - q->buf->consumer_index) 868c2ecf20Sopenharmony_ci & q->index_mask) == 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline void advance_producer(struct rxe_queue *q) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci q->buf->producer_index = (q->buf->producer_index + 1) 928c2ecf20Sopenharmony_ci & q->index_mask; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic inline void advance_consumer(struct rxe_queue *q) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci q->buf->consumer_index = (q->buf->consumer_index + 1) 988c2ecf20Sopenharmony_ci & q->index_mask; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic inline void *producer_addr(struct rxe_queue *q) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci return q->buf->data + ((q->buf->producer_index & q->index_mask) 1048c2ecf20Sopenharmony_ci << q->log2_elem_size); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic inline void *consumer_addr(struct rxe_queue *q) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci return q->buf->data + ((q->buf->consumer_index & q->index_mask) 1108c2ecf20Sopenharmony_ci << q->log2_elem_size); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic inline unsigned int producer_index(struct rxe_queue *q) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci return q->buf->producer_index; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic inline unsigned int consumer_index(struct rxe_queue *q) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return q->buf->consumer_index; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline void *addr_from_index(struct rxe_queue *q, unsigned int index) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return q->buf->data + ((index & q->index_mask) 1268c2ecf20Sopenharmony_ci << q->buf->log2_elem_size); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic inline unsigned int index_from_addr(const struct rxe_queue *q, 1308c2ecf20Sopenharmony_ci const void *addr) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci return (((u8 *)addr - q->buf->data) >> q->log2_elem_size) 1338c2ecf20Sopenharmony_ci & q->index_mask; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline unsigned int queue_count(const struct rxe_queue *q) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci return (q->buf->producer_index - q->buf->consumer_index) 1398c2ecf20Sopenharmony_ci & q->index_mask; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic inline void *queue_head(struct rxe_queue *q) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return queue_empty(q) ? NULL : consumer_addr(q); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#endif /* RXE_QUEUE_H */ 148