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