1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
#ifndef _IONIC_QUEUE_H_
#define _IONIC_QUEUE_H_
#include <linux/io.h>
#include <ionic_regs.h>
#define IONIC_MAX_DEPTH 0xffff
#define IONIC_MAX_CQ_DEPTH 0xffff
#define IONIC_CQ_RING_ARM IONIC_DBELL_RING_1
#define IONIC_CQ_RING_SOL IONIC_DBELL_RING_2
/**
* struct ionic_queue - Ring buffer used between device and driver
* @size: Size of the buffer, in bytes
* @dma: Dma address of the buffer
* @ptr: Buffer virtual address
* @prod: Driver position in the queue
* @cons: Device position in the queue
* @mask: Capacity of the queue, subtracting the hole
* This value is equal to ((1 << depth_log2) - 1)
* @depth_log2: Log base two size depth of the queue
* @stride_log2: Log base two size of an element in the queue
* @dbell: Doorbell identifying bits
*/
struct ionic_queue {
size_t size;
dma_addr_t dma;
void *ptr;
u16 prod;
u16 cons;
u16 mask;
u8 depth_log2;
u8 stride_log2;
u64 dbell;
};
/**
* ionic_queue_init() - Initialize user space queue
* @q: Uninitialized queue structure
* @dma_dev: DMA device for mapping
* @depth: Depth of the queue
* @stride: Size of each element of the queue
*
* Return: status code
*/
int ionic_queue_init(struct ionic_queue *q, struct device *dma_dev,
int depth, size_t stride);
/**
* ionic_queue_destroy() - Destroy user space queue
* @q: Queue structure
* @dma_dev: DMA device for mapping
*
* Return: status code
*/
void ionic_queue_destroy(struct ionic_queue *q, struct device *dma_dev);
/**
* ionic_queue_empty() - Test if queue is empty
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: is empty
*/
static inline bool ionic_queue_empty(struct ionic_queue *q)
{
return q->prod == q->cons;
}
/**
* ionic_queue_length() - Get the current length of the queue
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: length
*/
static inline u16 ionic_queue_length(struct ionic_queue *q)
{
return (q->prod - q->cons) & q->mask;
}
/**
* ionic_queue_length_remaining() - Get the remaining length of the queue
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: length remaining
*/
static inline u16 ionic_queue_length_remaining(struct ionic_queue *q)
{
return q->mask - ionic_queue_length(q);
}
/**
* ionic_queue_full() - Test if queue is full
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: is full
*/
static inline bool ionic_queue_full(struct ionic_queue *q)
{
return q->mask == ionic_queue_length(q);
}
/**
* ionic_color_wrap() - Flip the color if prod is wrapped
* @prod: Queue index just after advancing
* @color: Queue color just prior to advancing the index
*
* Return: color after advancing the index
*/
static inline bool ionic_color_wrap(u16 prod, bool color)
{
/* logical xor color with (prod == 0) */
return color != (prod == 0);
}
/**
* ionic_queue_at() - Get the element at the given index
* @q: Queue structure
* @idx: Index in the queue
*
* The index must be within the bounds of the queue. It is not checked here.
*
* Return: pointer to element at index
*/
static inline void *ionic_queue_at(struct ionic_queue *q, u16 idx)
{
return q->ptr + ((unsigned long)idx << q->stride_log2);
}
/**
* ionic_queue_at_prod() - Get the element at the producer index
* @q: Queue structure
*
* Return: pointer to element at producer index
*/
static inline void *ionic_queue_at_prod(struct ionic_queue *q)
{
return ionic_queue_at(q, q->prod);
}
/**
* ionic_queue_at_cons() - Get the element at the consumer index
* @q: Queue structure
*
* Return: pointer to element at consumer index
*/
static inline void *ionic_queue_at_cons(struct ionic_queue *q)
{
return ionic_queue_at(q, q->cons);
}
/**
* ionic_queue_next() - Compute the next index
* @q: Queue structure
* @idx: Index
*
* Return: next index after idx
*/
static inline u16 ionic_queue_next(struct ionic_queue *q, u16 idx)
{
return (idx + 1) & q->mask;
}
/**
* ionic_queue_produce() - Increase the producer index
* @q: Queue structure
*
* Caller must ensure that the queue is not full. It is not checked here.
*/
static inline void ionic_queue_produce(struct ionic_queue *q)
{
q->prod = ionic_queue_next(q, q->prod);
}
/**
* ionic_queue_consume() - Increase the consumer index
* @q: Queue structure
*
* Caller must ensure that the queue is not empty. It is not checked here.
*
* This is only valid for to-device queues.
*/
static inline void ionic_queue_consume(struct ionic_queue *q)
{
q->cons = ionic_queue_next(q, q->cons);
}
/**
* ionic_queue_consume_entries() - Increase the consumer index by entries
* @q: Queue structure
* @entries: Number of entries to increment
*
* Caller must ensure that the queue is not empty. It is not checked here.
*
* This is only valid for to-device queues.
*/
static inline void ionic_queue_consume_entries(struct ionic_queue *q,
u16 entries)
{
q->cons = (q->cons + entries) & q->mask;
}
/**
* ionic_queue_dbell_init() - Initialize doorbell bits for queue id
* @q: Queue structure
* @qid: Queue identifying number
*/
static inline void ionic_queue_dbell_init(struct ionic_queue *q, u32 qid)
{
q->dbell = IONIC_DBELL_QID(qid);
}
/**
* ionic_queue_dbell_val() - Get current doorbell update value
* @q: Queue structure
*
* Return: current doorbell update value
*/
static inline u64 ionic_queue_dbell_val(struct ionic_queue *q)
{
return q->dbell | q->prod;
}
#endif /* _IONIC_QUEUE_H_ */
|