xref: /linux/drivers/net/ethernet/intel/libeth/xsk.c (revision 5495c58c65aa3d650cccaa19dc59115b9a0069a5)
1b3ad8450SAlexander Lobakin // SPDX-License-Identifier: GPL-2.0-only
2b3ad8450SAlexander Lobakin /* Copyright (C) 2025 Intel Corporation */
3b3ad8450SAlexander Lobakin 
4b3ad8450SAlexander Lobakin #define DEFAULT_SYMBOL_NAMESPACE	"LIBETH_XDP"
5b3ad8450SAlexander Lobakin 
6b3ad8450SAlexander Lobakin #include <linux/export.h>
7b3ad8450SAlexander Lobakin 
8b3ad8450SAlexander Lobakin #include <net/libeth/xsk.h>
9b3ad8450SAlexander Lobakin 
10b3ad8450SAlexander Lobakin #include "priv.h"
11b3ad8450SAlexander Lobakin 
12b3ad8450SAlexander Lobakin /* ``XDP_TX`` bulking */
13b3ad8450SAlexander Lobakin 
14b3ad8450SAlexander Lobakin void __cold libeth_xsk_tx_return_bulk(const struct libeth_xdp_tx_frame *bq,
15b3ad8450SAlexander Lobakin 				      u32 count)
16b3ad8450SAlexander Lobakin {
17b3ad8450SAlexander Lobakin 	for (u32 i = 0; i < count; i++)
18b3ad8450SAlexander Lobakin 		libeth_xsk_buff_free_slow(bq[i].xsk);
19b3ad8450SAlexander Lobakin }
20b3ad8450SAlexander Lobakin 
2140e846d1SAlexander Lobakin /* XSk TMO */
2240e846d1SAlexander Lobakin 
2340e846d1SAlexander Lobakin const struct xsk_tx_metadata_ops libeth_xsktmo_slow = {
2440e846d1SAlexander Lobakin 	.tmo_request_checksum		= libeth_xsktmo_req_csum,
2540e846d1SAlexander Lobakin };
2640e846d1SAlexander Lobakin 
27b3ad8450SAlexander Lobakin /* Rx polling path */
28b3ad8450SAlexander Lobakin 
29b3ad8450SAlexander Lobakin /**
30b3ad8450SAlexander Lobakin  * libeth_xsk_buff_free_slow - free an XSk Rx buffer
31b3ad8450SAlexander Lobakin  * @xdp: buffer to free
32b3ad8450SAlexander Lobakin  *
33b3ad8450SAlexander Lobakin  * Slowpath version of xsk_buff_free() to be used on exceptions, cleanups etc.
34b3ad8450SAlexander Lobakin  * to avoid unwanted inlining.
35b3ad8450SAlexander Lobakin  */
36b3ad8450SAlexander Lobakin void libeth_xsk_buff_free_slow(struct libeth_xdp_buff *xdp)
37b3ad8450SAlexander Lobakin {
38b3ad8450SAlexander Lobakin 	xsk_buff_free(&xdp->base);
39b3ad8450SAlexander Lobakin }
40b3ad8450SAlexander Lobakin EXPORT_SYMBOL_GPL(libeth_xsk_buff_free_slow);
41*5495c58cSAlexander Lobakin 
42*5495c58cSAlexander Lobakin /**
43*5495c58cSAlexander Lobakin  * libeth_xsk_buff_add_frag - add frag to XSk Rx buffer
44*5495c58cSAlexander Lobakin  * @head: head buffer
45*5495c58cSAlexander Lobakin  * @xdp: frag buffer
46*5495c58cSAlexander Lobakin  *
47*5495c58cSAlexander Lobakin  * External helper used by libeth_xsk_process_buff(), do not call directly.
48*5495c58cSAlexander Lobakin  * Frees both main and frag buffers on error.
49*5495c58cSAlexander Lobakin  *
50*5495c58cSAlexander Lobakin  * Return: main buffer with attached frag on success, %NULL on error (no space
51*5495c58cSAlexander Lobakin  * for a new frag).
52*5495c58cSAlexander Lobakin  */
53*5495c58cSAlexander Lobakin struct libeth_xdp_buff *libeth_xsk_buff_add_frag(struct libeth_xdp_buff *head,
54*5495c58cSAlexander Lobakin 						 struct libeth_xdp_buff *xdp)
55*5495c58cSAlexander Lobakin {
56*5495c58cSAlexander Lobakin 	if (!xsk_buff_add_frag(&head->base, &xdp->base))
57*5495c58cSAlexander Lobakin 		goto free;
58*5495c58cSAlexander Lobakin 
59*5495c58cSAlexander Lobakin 	return head;
60*5495c58cSAlexander Lobakin 
61*5495c58cSAlexander Lobakin free:
62*5495c58cSAlexander Lobakin 	libeth_xsk_buff_free_slow(xdp);
63*5495c58cSAlexander Lobakin 	libeth_xsk_buff_free_slow(head);
64*5495c58cSAlexander Lobakin 
65*5495c58cSAlexander Lobakin 	return NULL;
66*5495c58cSAlexander Lobakin }
67*5495c58cSAlexander Lobakin EXPORT_SYMBOL_GPL(libeth_xsk_buff_add_frag);
68*5495c58cSAlexander Lobakin 
69*5495c58cSAlexander Lobakin /**
70*5495c58cSAlexander Lobakin  * libeth_xsk_buff_stats_frags - update onstack RQ stats with XSk frags info
71*5495c58cSAlexander Lobakin  * @rs: onstack stats to update
72*5495c58cSAlexander Lobakin  * @xdp: buffer to account
73*5495c58cSAlexander Lobakin  *
74*5495c58cSAlexander Lobakin  * External helper used by __libeth_xsk_run_pass(), do not call directly.
75*5495c58cSAlexander Lobakin  * Adds buffer's frags count and total len to the onstack stats.
76*5495c58cSAlexander Lobakin  */
77*5495c58cSAlexander Lobakin void libeth_xsk_buff_stats_frags(struct libeth_rq_napi_stats *rs,
78*5495c58cSAlexander Lobakin 				 const struct libeth_xdp_buff *xdp)
79*5495c58cSAlexander Lobakin {
80*5495c58cSAlexander Lobakin 	libeth_xdp_buff_stats_frags(rs, xdp);
81*5495c58cSAlexander Lobakin }
82*5495c58cSAlexander Lobakin EXPORT_SYMBOL_GPL(libeth_xsk_buff_stats_frags);
83*5495c58cSAlexander Lobakin 
84*5495c58cSAlexander Lobakin /**
85*5495c58cSAlexander Lobakin  * __libeth_xsk_run_prog_slow - process the non-``XDP_REDIRECT`` verdicts
86*5495c58cSAlexander Lobakin  * @xdp: buffer to process
87*5495c58cSAlexander Lobakin  * @bq: Tx bulk for queueing on ``XDP_TX``
88*5495c58cSAlexander Lobakin  * @act: verdict to process
89*5495c58cSAlexander Lobakin  * @ret: error code if ``XDP_REDIRECT`` failed
90*5495c58cSAlexander Lobakin  *
91*5495c58cSAlexander Lobakin  * External helper used by __libeth_xsk_run_prog(), do not call directly.
92*5495c58cSAlexander Lobakin  * ``XDP_REDIRECT`` is the most common and hottest verdict on XSk, thus
93*5495c58cSAlexander Lobakin  * it is processed inline. The rest goes here for out-of-line processing,
94*5495c58cSAlexander Lobakin  * together with redirect errors.
95*5495c58cSAlexander Lobakin  *
96*5495c58cSAlexander Lobakin  * Return: libeth_xdp XDP prog verdict.
97*5495c58cSAlexander Lobakin  */
98*5495c58cSAlexander Lobakin u32 __libeth_xsk_run_prog_slow(struct libeth_xdp_buff *xdp,
99*5495c58cSAlexander Lobakin 			       const struct libeth_xdp_tx_bulk *bq,
100*5495c58cSAlexander Lobakin 			       enum xdp_action act, int ret)
101*5495c58cSAlexander Lobakin {
102*5495c58cSAlexander Lobakin 	switch (act) {
103*5495c58cSAlexander Lobakin 	case XDP_DROP:
104*5495c58cSAlexander Lobakin 		xsk_buff_free(&xdp->base);
105*5495c58cSAlexander Lobakin 
106*5495c58cSAlexander Lobakin 		return LIBETH_XDP_DROP;
107*5495c58cSAlexander Lobakin 	case XDP_TX:
108*5495c58cSAlexander Lobakin 		return LIBETH_XDP_TX;
109*5495c58cSAlexander Lobakin 	case XDP_PASS:
110*5495c58cSAlexander Lobakin 		return LIBETH_XDP_PASS;
111*5495c58cSAlexander Lobakin 	default:
112*5495c58cSAlexander Lobakin 		break;
113*5495c58cSAlexander Lobakin 	}
114*5495c58cSAlexander Lobakin 
115*5495c58cSAlexander Lobakin 	return libeth_xdp_prog_exception(bq, xdp, act, ret);
116*5495c58cSAlexander Lobakin }
117*5495c58cSAlexander Lobakin EXPORT_SYMBOL_GPL(__libeth_xsk_run_prog_slow);
118*5495c58cSAlexander Lobakin 
119*5495c58cSAlexander Lobakin /**
120*5495c58cSAlexander Lobakin  * libeth_xsk_prog_exception - handle XDP prog exceptions on XSk
121*5495c58cSAlexander Lobakin  * @xdp: buffer to process
122*5495c58cSAlexander Lobakin  * @act: verdict returned by the prog
123*5495c58cSAlexander Lobakin  * @ret: error code if ``XDP_REDIRECT`` failed
124*5495c58cSAlexander Lobakin  *
125*5495c58cSAlexander Lobakin  * Internal. Frees the buffer and, if the queue uses XSk wakeups, stop the
126*5495c58cSAlexander Lobakin  * current NAPI poll when there are no free buffers left.
127*5495c58cSAlexander Lobakin  *
128*5495c58cSAlexander Lobakin  * Return: libeth_xdp's XDP prog verdict.
129*5495c58cSAlexander Lobakin  */
130*5495c58cSAlexander Lobakin u32 __cold libeth_xsk_prog_exception(struct libeth_xdp_buff *xdp,
131*5495c58cSAlexander Lobakin 				     enum xdp_action act, int ret)
132*5495c58cSAlexander Lobakin {
133*5495c58cSAlexander Lobakin 	const struct xdp_buff_xsk *xsk;
134*5495c58cSAlexander Lobakin 	u32 __ret = LIBETH_XDP_DROP;
135*5495c58cSAlexander Lobakin 
136*5495c58cSAlexander Lobakin 	if (act != XDP_REDIRECT)
137*5495c58cSAlexander Lobakin 		goto drop;
138*5495c58cSAlexander Lobakin 
139*5495c58cSAlexander Lobakin 	xsk = container_of(&xdp->base, typeof(*xsk), xdp);
140*5495c58cSAlexander Lobakin 	if (xsk_uses_need_wakeup(xsk->pool) && ret == -ENOBUFS)
141*5495c58cSAlexander Lobakin 		__ret = LIBETH_XDP_ABORTED;
142*5495c58cSAlexander Lobakin 
143*5495c58cSAlexander Lobakin drop:
144*5495c58cSAlexander Lobakin 	libeth_xsk_buff_free_slow(xdp);
145*5495c58cSAlexander Lobakin 
146*5495c58cSAlexander Lobakin 	return __ret;
147*5495c58cSAlexander Lobakin }
148