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