summaryrefslogtreecommitdiff
path: root/include/linux/net/intel/libie/controlq.h
blob: 175227d4eef1e50caeb0dcdf9d6a7771dad7ba8e (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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2025 Intel Corporation */

#ifndef __LIBIE_CONTROLQ_H
#define __LIBIE_CONTROLQ_H

#include <linux/dmapool.h>
#include <net/libeth/rx.h>

#include <linux/net/intel/libie/pci.h>
#include <linux/net/intel/virtchnl2.h>

/* Default mailbox control queue */
#define LIBIE_CTLQ_MBX_ID			-1
#define LIBIE_CTLQ_MAX_BUF_LEN			SZ_4K

/**
 * enum libie_ctlq_type - control queue type
 * @LIBIE_CTLQ_TYPE_TX: basic Tx control queue
 * @LIBIE_CTLQ_TYPE_RX: basic Rx control queue
 */
enum libie_ctlq_type {
	LIBIE_CTLQ_TYPE_TX = 0,
	LIBIE_CTLQ_TYPE_RX = 1,
};

/* Opcode used to send controlq message to the control plane */
#define LIBIE_CTLQ_SEND_MSG_TO_CP		0x801
#define LIBIE_CTLQ_SEND_MSG_TO_PEER		0x804

#define LIBIE_CP_TX_COPYBREAK		128

/**
 * struct libie_ctlq_ctx - contains controlq info and MMIO region info
 * @mmio_info: MMIO region info structure
 * @ctlqs: list that stores all the control queues
 * @ctlqs_lock: lock for control queue list
 */
struct libie_ctlq_ctx {
	struct libie_mmio_info	mmio_info;
	struct list_head	ctlqs;
	spinlock_t		ctlqs_lock;	/* protects the ctlqs list */
};

/**
 * struct libie_ctlq_reg - structure representing virtual addresses of the
 *			    controlq registers and masks
 * @head: controlq head register address
 * @tail: controlq tail register address
 * @len: register address to write controlq length and enable bit
 * @addr_high: register address to write the upper 32b of ring physical address
 * @addr_low: register address to write the lower 32b of ring physical address
 * @len_mask: mask to read the controlq length
 * @len_ena_mask: mask to write the controlq enable bit
 * @head_mask: mask to read the head value
 */
struct libie_ctlq_reg {
	void __iomem	*head;
	void __iomem	*tail;
	void __iomem	*len;
	void __iomem	*addr_high;
	void __iomem	*addr_low;
	u32		len_mask;
	u32		len_ena_mask;
	u32		head_mask;
};

/**
 * struct libie_cp_dma_mem - structure for DMA memory
 * @va: virtual address
 * @pa: physical address
 * @size: memory size
 * @direction: memory to device or device to memory
 */
struct libie_cp_dma_mem {
	void		*va;
	dma_addr_t	pa;
	size_t		size;
	int		direction;
};

/**
 * struct libie_ctlq_msg - control queue message data
 * @flags: refer to 'Flags sub-structure' definitions
 * @opcode: infrastructure message opcode
 * @data_len: size of the payload
 * @func_id: queue id for mailbox selection, 0 for default mailbox (Tx)
 * @hw_retval: execution status from the HW (Rx)
 * @chnl_opcode: virtchnl message opcode
 * @chnl_retval: virtchnl return value
 * @param0: indirect message raw parameter0
 * @sw_cookie: used to verify the response of the sent virtchnl message
 * @virt_flags: virtchnl capability flags
 * @addr_param: additional parameters in place of the address, given no buffer
 * @recv_mem: virtual address and size of the buffer that contains
 *	      the indirect response
 * @send_mem: physical and virtual address of the DMA buffer,
 *	      used for sending
 */
struct libie_ctlq_msg {
	u16			flags;
	u16			opcode;
	u16			data_len;
	union {
		u16		func_id;
		u16		hw_retval;
	};
	u32			chnl_opcode;
	u32			chnl_retval;
	u32			param0;
	u16			sw_cookie;
	u16			virt_flags;
	u64			addr_param;
	union {
		struct kvec		recv_mem;
		struct libie_cp_dma_mem	send_mem;
	};
};

/**
 * struct libie_ctlq_create_info - control queue create information
 * @type: control queue type (Rx or Tx)
 * @id: queue offset passed as input, -1 for default mailbox
 * @reg: registers accessed by control queue
 * @len: controlq length
 */
struct libie_ctlq_create_info {
	enum libie_ctlq_type		type;
	int				id;
	struct libie_ctlq_reg		reg;
	u16				len;
};

/**
 * struct libie_ctlq_info - control queue information
 * @list: used to add a controlq to the list of queues in libie_ctlq_ctx
 * @type: control queue type
 * @qid: queue identifier
 * @lock: control queue lock
 * @ring_mem: descriptor ring DMA memory
 * @descs: array of descriptors
 * @rx_fqes: array of controlq Rx buffers
 * @tx_msg: Tx messages sent to hardware
 * @reg: registers used by control queue
 * @dev: device that owns this control queue
 * @pp: page pool for controlq Rx buffers
 * @truesize: size to allocate per buffer
 * @next_to_clean: next descriptor to be cleaned
 * @next_to_use: next available slot to send buffer (Tx queue)
 * @next_to_post: next available slot to post buffers to (Rx queue)
 * @ring_len: length of the descriptor ring
 */
struct libie_ctlq_info {
	struct list_head		list;
	enum libie_ctlq_type		type;
	int				qid;
	spinlock_t			lock;	/* for concurrent processing */
	struct libie_cp_dma_mem	ring_mem;
	struct libie_ctlq_desc		*descs;
	union {
		struct libeth_fqe	*rx_fqes;
		struct libie_ctlq_msg	**tx_msg;
	};
	struct libie_ctlq_reg		reg;
	struct device			*dev;
	struct page_pool		*pp;
	u32				truesize;
	u32				next_to_clean;
	union {
		u32			next_to_use;
		u32			next_to_post;
	};
	u32				ring_len;
};

#define LIBIE_CTLQ_MBX_ATQ_LEN			GENMASK(9, 0)

/* libie controlq descriptor qword0 details */

/* Flags sub-structure
 * |0  |1  |2  |3  |4  |5  |6  |7  |8  |9  |10 |11 |12 |13 |14 |15 |
 * |DD |CMP|ERR|  * RSV *  |FTYPE  | *RSV* |RD |VFC|BUF|  HOST_ID  |
 */
#define LIBIE_CTLQ_DESC_FLAG_DD		BIT(0)
#define LIBIE_CTLQ_DESC_FLAG_CMP		BIT(1)
#define LIBIE_CTLQ_DESC_FLAG_ERR		BIT(2)
#define LIBIE_CTLQ_DESC_FLAG_FTYPE_VM		BIT(6)
#define LIBIE_CTLQ_DESC_FLAG_FTYPE_PF		BIT(7)
#define LIBIE_CTLQ_DESC_FLAG_FTYPE		GENMASK(7, 6)
#define LIBIE_CTLQ_DESC_FLAG_RD		BIT(10)
#define LIBIE_CTLQ_DESC_FLAG_VFC		BIT(11)
#define LIBIE_CTLQ_DESC_FLAG_BUF		BIT(12)
#define LIBIE_CTLQ_DESC_FLAG_HOST_ID		GENMASK(15, 13)

#define LIBIE_CTLQ_DESC_FLAGS			GENMASK(15, 0)
#define LIBIE_CTLQ_DESC_INFRA_OPCODE		GENMASK_ULL(31, 16)
#define LIBIE_CTLQ_DESC_DATA_LEN		GENMASK_ULL(47, 32)
#define LIBIE_CTLQ_DESC_HW_RETVAL		GENMASK_ULL(63, 48)

#define LIBIE_CTLQ_DESC_PFID_VFID		GENMASK_ULL(63, 48)

/* libie controlq descriptor qword1 details */
#define LIBIE_CTLQ_DESC_VIRTCHNL_OPCODE	GENMASK(27, 0)
#define LIBIE_CTLQ_DESC_VIRTCHNL_DESC_TYPE	GENMASK_ULL(31, 28)
#define LIBIE_CTLQ_DESC_VIRTCHNL_MSG_RET_VAL	GENMASK_ULL(63, 32)

/* libie controlq descriptor qword2 details */
#define LIBIE_CTLQ_DESC_MSG_PARAM0		GENMASK_ULL(31, 0)
#define LIBIE_CTLQ_DESC_SW_COOKIE		GENMASK_ULL(47, 32)
#define LIBIE_CTLQ_DESC_VIRTCHNL_FLAGS		GENMASK_ULL(63, 48)

/* libie controlq descriptor qword3 details */
#define LIBIE_CTLQ_DESC_DATA_ADDR_HIGH		GENMASK_ULL(31, 0)
#define LIBIE_CTLQ_DESC_DATA_ADDR_LOW		GENMASK_ULL(63, 32)

/**
 * struct libie_ctlq_desc - control queue descriptor format
 * @qword0: flags, message opcode, data length etc
 * @qword1: virtchnl opcode, descriptor type and return value
 * @qword2: indirect message parameters
 * @qword3: indirect message buffer address
 */
struct libie_ctlq_desc {
	__le64			qword0;
	__le64			qword1;
	__le64			qword2;
	__le64			qword3;
};

/**
 * struct libie_ctlq_clean_params - cleaning parameters for Tx messages
 * @rel_dma_mem: non-sleeping callback to put the DMA buffer after send
 * @rel_ctx: additional context for release callback
 * @ctlq: control queue information
 * @num_msgs: number of messages to be cleaned
 * @force: clean even if DD is not yet set, use only for final cleanup
 */
struct libie_ctlq_clean_params {
	void (*rel_dma_mem)(const void *ctx, struct libie_cp_dma_mem *dma_mem);
	const void				*rel_ctx;
	struct libie_ctlq_info			*ctlq;
	u16					num_msgs;
	bool					force;
};

/**
 * libie_ctlq_release_rx_buf - Release Rx buffer for a specific control queue
 * @rx_buf: Rx buffer to be freed
 *
 * Driver uses this function to post back the Rx buffer after the usage.
 */
static inline void libie_ctlq_release_rx_buf(struct kvec *rx_buf)
{
	netmem_ref netmem;

	if (!rx_buf->iov_base)
		return;

	netmem = virt_to_netmem(rx_buf->iov_base);
	page_pool_put_full_netmem(netmem_get_pp(netmem), netmem, false);
}

int libie_ctlq_init(struct libie_ctlq_ctx *ctx,
		    const struct libie_ctlq_create_info *qinfo, u32 numq);
void libie_ctlq_deinit(struct libie_ctlq_ctx *ctx);

struct libie_ctlq_info *libie_find_ctlq(struct libie_ctlq_ctx *ctx,
					enum libie_ctlq_type type,
					int id);

u32 libie_ctlq_send_desc_avail(const struct libie_ctlq_info *ctlq);
void libie_ctlq_send(struct libie_ctlq_info *ctlq, u32 num_q_msg);
u32 libie_ctlq_send_clean(const struct libie_ctlq_clean_params *params);
u32 libie_ctlq_recv(struct libie_ctlq_info *ctlq, struct libie_ctlq_msg *msg,
		    u32 num_q_msg);

int libie_ctlq_post_rx_buffs(struct libie_ctlq_info *ctlq);

/* Only 8 bits are available in descriptor for Xn index */
#define LIBIE_CTLQ_MAX_XN_ENTRIES		256
#define LIBIE_CTLQ_XN_COOKIE_M			GENMASK(15, 8)
#define LIBIE_CTLQ_XN_INDEX_M			GENMASK(7, 0)

/**
 * enum libie_ctlq_xn_state - Transaction state of a virtchnl message
 * @LIBIE_CTLQ_XN_IDLE: transaction is available to use
 * @LIBIE_CTLQ_XN_WAITING: waiting for transaction to complete
 * @LIBIE_CTLQ_XN_COMPLETED_SUCCESS: transaction completed with success
 * @LIBIE_CTLQ_XN_COMPLETED_FAILED: transaction completed with failure
 * @LIBIE_CTLQ_XN_ASYNC: asynchronous virtchnl message transaction type
 * @LIBIE_CTLQ_XN_SHUTDOWN: transaction cannot be used anymore
 */
enum libie_ctlq_xn_state {
	LIBIE_CTLQ_XN_IDLE = 0,
	LIBIE_CTLQ_XN_WAITING,
	LIBIE_CTLQ_XN_COMPLETED_SUCCESS,
	LIBIE_CTLQ_XN_COMPLETED_FAILED,
	LIBIE_CTLQ_XN_ASYNC,
	LIBIE_CTLQ_XN_SHUTDOWN,
};

/**
 * struct libie_ctlq_xn - structure representing a virtchnl transaction entry
 * @resp_cb: non-sleeping callback to handle the response to an async message
 * @xn_lock: lock to protect the transaction entry state
 * @cmd_completion_event: wait until reply is received or xn is terminated
 * @small_dma_mem: DMA memory for copying small send buffers from stack,
 *		   is recycled when response is received or on timeout
 * @send_dma_mem: DMA memory of send buffer
 * @recv_mem: receive buffer
 * @send_ctx: context for callback function
 * @timeout_ms: Xn transaction timeout in msecs
 * @timestamp: timestamp to record the Xn send
 * @tx_msg: control queue Tx message slot to track small DMA usage
 * @virtchnl_opcode: virtchnl command opcode used for Xn transaction
 * @state: transaction state of a virtchnl message
 * @cookie: unique message identifier, incremented every time the slot is used
 * @index: index of the transaction entry
 */
struct libie_ctlq_xn {
	void (*resp_cb)(void *ctx, struct kvec *mem, int status);
	spinlock_t			xn_lock;	/* protects state */
	struct completion		cmd_completion_event;
	struct libie_cp_dma_mem	small_dma_mem;
	struct libie_cp_dma_mem	send_dma_mem;
	struct kvec			recv_mem;
	void				*send_ctx;
	u64				timeout_ms;
	ktime_t				timestamp;
	struct libie_ctlq_msg		*tx_msg;
	u32				virtchnl_opcode;
	enum libie_ctlq_xn_state	state;
	u8				cookie;
	u8				index;
};

/**
 * struct libie_ctlq_xn_manager - structure representing the array of virtchnl
 *				   transaction entries
 * @ctx: pointer to controlq context structure
 * @free_xns_bm_lock: lock to protect the free Xn entries bit map
 * @free_xns_bm: bitmap that represents the free Xn entries
 * @ring: array of Xn entries
 * @small_buff_pool: DMA pool for small send buffers
 * @can_destroy: completion, triggered by the last released transaction
 * @shutdown: shutdown process has been started, no new transactions allowed
 */
struct libie_ctlq_xn_manager {
	struct libie_ctlq_ctx	*ctx;
	spinlock_t		free_xns_bm_lock;	/* get/check entries */
	DECLARE_BITMAP(free_xns_bm, LIBIE_CTLQ_MAX_XN_ENTRIES);
	struct libie_ctlq_xn	ring[LIBIE_CTLQ_MAX_XN_ENTRIES];
	struct dma_pool		*small_buff_pool;
	struct completion	can_destroy;
	bool			shutdown;
};

/**
 * struct libie_ctlq_xn_send_params - structure representing send Xn entry
 * @resp_cb: non-sleeping callback to handle the response to an async message
 * @rel_tx_buf: non-sleeping callback for freeing the send buffer
 * @xnm: Xn manager to process Xn entries
 * @ctlq: send control queue information
 * @ctlq_msg: control queue message information
 * @send_buf: buffer that carries outgoing message data, buffers larger than
 *	      LIBIE_CP_TX_COPYBREAK bytes will always be consumed
 * @recv_mem: receive buffer
 * @send_ctx: context for callback function
 * @timeout_ms: virtchnl transaction timeout in msecs
 * @chnl_opcode: virtchnl message opcode
 */
struct libie_ctlq_xn_send_params {
	void (*resp_cb)(void *ctx, struct kvec *mem, int status);
	void (*rel_tx_buf)(const void *buf_va);
	struct libie_ctlq_xn_manager		*xnm;
	struct libie_ctlq_info			*ctlq;
	struct libie_ctlq_msg			*ctlq_msg;
	struct kvec				send_buf;
	struct kvec				recv_mem;
	void					*send_ctx;
	u64					timeout_ms;
	u32					chnl_opcode;
};

/**
 * libie_cp_can_send_onstack - can a message be sent using a stack variable
 * @size: ctlq data buffer size
 *
 * Return: %true if the message size is small enough for caller to pass
 *	   an on-stack buffer, %false if kmalloc is needed
 */
static inline bool libie_cp_can_send_onstack(u32 size)
{
	return size <= LIBIE_CP_TX_COPYBREAK;
}

/**
 * struct libie_ctlq_xn_recv_params - request to receive xn responses
 * @ctlq_msg_handler: handler for Rx messages with no matching xn (mandatory)
 * @xnm: Xn manager to process Xn entries
 * @ctlq: control queue information
 * @budget: maximum number of messages to process
 */
struct libie_ctlq_xn_recv_params {
	void (*ctlq_msg_handler)(struct libie_ctlq_ctx *ctx,
				 struct libie_ctlq_msg *msg);
	struct libie_ctlq_xn_manager		*xnm;
	struct libie_ctlq_info			*ctlq;
	u32					budget;
};

/**
 * struct libie_ctlq_xn_init_params - xn transaction manager parameters
 * @cctlq_info: control queue information
 * @ctx: pointer to controlq context structure
 * @xnm: Xn manager to process Xn entries
 * @num_qs: number of control queues to be initialized
 */
struct libie_ctlq_xn_init_params {
	struct libie_ctlq_create_info		*cctlq_info;
	struct libie_ctlq_ctx			*ctx;
	struct libie_ctlq_xn_manager		*xnm;
	u32					num_qs;
};

int libie_ctlq_xn_init(struct libie_ctlq_xn_init_params *params);
void libie_ctlq_xn_deinit(struct libie_ctlq_xn_manager *xnm,
			  struct libie_ctlq_ctx *ctx);
void libie_ctlq_xn_shutdown(struct libie_ctlq_xn_manager *xnm);
int libie_ctlq_xn_send(struct libie_ctlq_xn_send_params *params);
u32 libie_ctlq_xn_recv(struct libie_ctlq_xn_recv_params *params);
u32 libie_ctlq_xn_send_clean(struct libie_ctlq_info *ctlq,
			     void (*rel_tx_buf)(const void *buf_va),
			     bool force);

#endif /* __LIBIE_CONTROLQ_H */