linux/drivers/infiniband/sw/rxe/rxe_queue.h
<<
>>
Prefs
   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 */
  58struct 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
  69struct 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
  79int 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
  87void rxe_queue_reset(struct rxe_queue *q);
  88
  89struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe,
  90                                 int *num_elem,
  91                                 unsigned int elem_size);
  92
  93int rxe_queue_resize(struct rxe_queue *q,
  94                     unsigned int *num_elem_p,
  95                     unsigned int elem_size,
  96                     struct ib_ucontext *context,
  97                     struct ib_udata *udata,
  98                     /* Protect producers while resizing queue */
  99                     spinlock_t *producer_lock,
 100                     /* Protect consumers while resizing queue */
 101                     spinlock_t *consumer_lock);
 102
 103void rxe_queue_cleanup(struct rxe_queue *queue);
 104
 105static inline int next_index(struct rxe_queue *q, int index)
 106{
 107        return (index + 1) & q->buf->index_mask;
 108}
 109
 110static inline int queue_empty(struct rxe_queue *q)
 111{
 112        return ((q->buf->producer_index - q->buf->consumer_index)
 113                        & q->index_mask) == 0;
 114}
 115
 116static inline int queue_full(struct rxe_queue *q)
 117{
 118        return ((q->buf->producer_index + 1 - q->buf->consumer_index)
 119                        & q->index_mask) == 0;
 120}
 121
 122static inline void advance_producer(struct rxe_queue *q)
 123{
 124        q->buf->producer_index = (q->buf->producer_index + 1)
 125                        & q->index_mask;
 126}
 127
 128static inline void advance_consumer(struct rxe_queue *q)
 129{
 130        q->buf->consumer_index = (q->buf->consumer_index + 1)
 131                        & q->index_mask;
 132}
 133
 134static inline void *producer_addr(struct rxe_queue *q)
 135{
 136        return q->buf->data + ((q->buf->producer_index & q->index_mask)
 137                                << q->log2_elem_size);
 138}
 139
 140static inline void *consumer_addr(struct rxe_queue *q)
 141{
 142        return q->buf->data + ((q->buf->consumer_index & q->index_mask)
 143                                << q->log2_elem_size);
 144}
 145
 146static inline unsigned int producer_index(struct rxe_queue *q)
 147{
 148        return q->buf->producer_index;
 149}
 150
 151static inline unsigned int consumer_index(struct rxe_queue *q)
 152{
 153        return q->buf->consumer_index;
 154}
 155
 156static inline void *addr_from_index(struct rxe_queue *q, unsigned int index)
 157{
 158        return q->buf->data + ((index & q->index_mask)
 159                                << q->buf->log2_elem_size);
 160}
 161
 162static inline unsigned int index_from_addr(const struct rxe_queue *q,
 163                                           const void *addr)
 164{
 165        return (((u8 *)addr - q->buf->data) >> q->log2_elem_size)
 166                & q->index_mask;
 167}
 168
 169static inline unsigned int queue_count(const struct rxe_queue *q)
 170{
 171        return (q->buf->producer_index - q->buf->consumer_index)
 172                & q->index_mask;
 173}
 174
 175static inline void *queue_head(struct rxe_queue *q)
 176{
 177        return queue_empty(q) ? NULL : consumer_addr(q);
 178}
 179
 180#endif /* RXE_QUEUE_H */
 181