summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/ionic/ionic_queue.h
blob: d18020d4cad581f6f963cfedf47be3d35ed8d56f (plain)
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_ */