File: ionic_queue.h

package info (click to toggle)
rdma-core 61.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,124 kB
  • sloc: ansic: 176,798; python: 15,496; sh: 2,742; perl: 1,465; makefile: 73
file content (237 lines) | stat: -rw-r--r-- 5,707 bytes parent folder | download
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
235
236
237
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
 * Copyright (c) 2018-2025 Advanced Micro Devices, Inc.  All rights reserved.
 */

#ifndef IONIC_QUEUE_H
#define IONIC_QUEUE_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <util/mmio.h>
#include <util/udma_barrier.h>
#include <util/util.h>

#define IONIC_QID_MASK		(BIT_ULL(24) - 1)
#define IONIC_DBELL_QID_SHIFT	24
#define IONIC_DBELL_RING_ARM	BIT_ULL(16)
#define IONIC_DBELL_RING_SONLY	BIT_ULL(17)

struct ionic_pd;

/**
 * struct ionic_queue - Ring buffer used between device and driver
 * @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;
	void *ptr;
	uint16_t prod;
	uint16_t cons;
	uint16_t mask;
	uint8_t depth_log2;
	uint8_t stride_log2;
	uint64_t dbell;

	struct ionic_pd *pd;
	uint64_t pd_tag;
};

/**
 * ionic_queue_init() - Initialize user space queue
 * @q:		Uninitialized queue structure
 * @pd:		Parent domain for descriptor ring memory.
 * @pd_tag:	Identify the purpose of the ring memory.
 * @pg_shift:	Host page shift for buffer size-alignment and 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 ionic_pd *pd,
		     uint64_t pd_tag, int pg_shift, int depth, size_t stride);

/**
 * ionic_queue_destroy() - Destroy user space queue
 * @q:		Queue structure
 *
 * Return: status code
 */
void ionic_queue_destroy(struct ionic_queue *q);

/**
 * 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 uint16_t 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 uint16_t 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(uint16_t 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, uint16_t 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 uint16_t ionic_queue_next(struct ionic_queue *q, uint16_t 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_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,
					  uint32_t qid)
{
	q->dbell = ((uint64_t)qid & IONIC_QID_MASK) << IONIC_DBELL_QID_SHIFT;
}

/**
 * ionic_queue_dbell_val() - Get current doorbell update value
 * @q:		Queue structure
 */
static inline uint64_t ionic_queue_dbell_val(struct ionic_queue *q)
{
	return q->dbell | q->prod;
}

/**
 * ionic_dbell_ring() - Write the doorbell value to register
 * @dbreg:	Doorbell register
 * @val:	Doorbell value from queue
 */
static inline void ionic_dbell_ring(uint64_t *dbreg, uint64_t val)
{
	mmio_write64_le(dbreg, htole64(val));
}

#endif /* IONIC_QUEUE_H */