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