| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- /* Copyright (C) 2024-2025 Intel Corporation */
- #ifndef __LIBETH_TX_H
- #define __LIBETH_TX_H
- #include <linux/skbuff.h>
- #include <net/libeth/types.h>
- /* Tx buffer completion */
- /**
- * enum libeth_sqe_type - type of &libeth_sqe to act on Tx completion
- * @LIBETH_SQE_EMPTY: unused/empty OR XDP_TX/XSk frame, no action required
- * @LIBETH_SQE_CTX: context descriptor with empty SQE, no action required
- * @LIBETH_SQE_SLAB: kmalloc-allocated buffer, unmap and kfree()
- * @LIBETH_SQE_FRAG: mapped skb frag, only unmap DMA
- * @LIBETH_SQE_SKB: &sk_buff, unmap and napi_consume_skb(), update stats
- * @__LIBETH_SQE_XDP_START: separator between skb and XDP types
- * @LIBETH_SQE_XDP_TX: &skb_shared_info, libeth_xdp_return_buff_bulk(), stats
- * @LIBETH_SQE_XDP_XMIT: &xdp_frame, unmap and xdp_return_frame_bulk(), stats
- * @LIBETH_SQE_XDP_XMIT_FRAG: &xdp_frame frag, only unmap DMA
- * @LIBETH_SQE_XSK_TX: &libeth_xdp_buff on XSk queue, xsk_buff_free(), stats
- * @LIBETH_SQE_XSK_TX_FRAG: &libeth_xdp_buff frag on XSk queue, xsk_buff_free()
- */
- enum libeth_sqe_type {
- LIBETH_SQE_EMPTY = 0U,
- LIBETH_SQE_CTX,
- LIBETH_SQE_SLAB,
- LIBETH_SQE_FRAG,
- LIBETH_SQE_SKB,
- __LIBETH_SQE_XDP_START,
- LIBETH_SQE_XDP_TX = __LIBETH_SQE_XDP_START,
- LIBETH_SQE_XDP_XMIT,
- LIBETH_SQE_XDP_XMIT_FRAG,
- LIBETH_SQE_XSK_TX,
- LIBETH_SQE_XSK_TX_FRAG,
- };
- /**
- * struct libeth_sqe - represents a Send Queue Element / Tx buffer
- * @type: type of the buffer, see the enum above
- * @rs_idx: index of the last buffer from the batch this one was sent in
- * @raw: slab buffer to free via kfree()
- * @skb: &sk_buff to consume
- * @sinfo: skb shared info of an XDP_TX frame
- * @xdpf: XDP frame from ::ndo_xdp_xmit()
- * @xsk: XSk Rx frame from XDP_TX action
- * @dma: DMA address to unmap
- * @len: length of the mapped region to unmap
- * @nr_frags: number of frags in the frame this buffer belongs to
- * @packets: number of physical packets sent for this frame
- * @bytes: number of physical bytes sent for this frame
- * @priv: driver-private scratchpad
- */
- struct libeth_sqe {
- enum libeth_sqe_type type:32;
- u32 rs_idx;
- union {
- void *raw;
- struct sk_buff *skb;
- struct skb_shared_info *sinfo;
- struct xdp_frame *xdpf;
- struct libeth_xdp_buff *xsk;
- };
- DEFINE_DMA_UNMAP_ADDR(dma);
- DEFINE_DMA_UNMAP_LEN(len);
- u32 nr_frags;
- u32 packets;
- u32 bytes;
- unsigned long priv;
- } __aligned_largest;
- /**
- * LIBETH_SQE_CHECK_PRIV - check the driver's private SQE data
- * @p: type or name of the object the driver wants to fit into &libeth_sqe
- *
- * Make sure the driver's private data fits into libeth_sqe::priv. To be used
- * right after its declaration.
- */
- #define LIBETH_SQE_CHECK_PRIV(p) \
- static_assert(sizeof(p) <= sizeof_field(struct libeth_sqe, priv))
- /**
- * struct libeth_cq_pp - completion queue poll params
- * @dev: &device to perform DMA unmapping
- * @bq: XDP frame bulk to combine return operations
- * @ss: onstack NAPI stats to fill
- * @xss: onstack XDPSQ NAPI stats to fill
- * @xdp_tx: number of XDP-not-XSk frames processed
- * @napi: whether it's called from the NAPI context
- *
- * libeth uses this structure to access objects needed for performing full
- * Tx complete operation without passing lots of arguments and change the
- * prototypes each time a new one is added.
- */
- struct libeth_cq_pp {
- struct device *dev;
- struct xdp_frame_bulk *bq;
- union {
- struct libeth_sq_napi_stats *ss;
- struct libeth_xdpsq_napi_stats *xss;
- };
- u32 xdp_tx;
- bool napi;
- };
- /**
- * libeth_tx_complete - perform Tx completion for one SQE
- * @sqe: SQE to complete
- * @cp: poll params
- *
- * Do Tx complete for all the types of buffers, incl. freeing, unmapping,
- * updating the stats etc.
- */
- static inline void libeth_tx_complete(struct libeth_sqe *sqe,
- const struct libeth_cq_pp *cp)
- {
- switch (sqe->type) {
- case LIBETH_SQE_EMPTY:
- return;
- case LIBETH_SQE_SKB:
- case LIBETH_SQE_FRAG:
- case LIBETH_SQE_SLAB:
- dma_unmap_page(cp->dev, dma_unmap_addr(sqe, dma),
- dma_unmap_len(sqe, len), DMA_TO_DEVICE);
- break;
- default:
- break;
- }
- switch (sqe->type) {
- case LIBETH_SQE_SKB:
- cp->ss->packets += sqe->packets;
- cp->ss->bytes += sqe->bytes;
- napi_consume_skb(sqe->skb, cp->napi);
- break;
- case LIBETH_SQE_SLAB:
- kfree(sqe->raw);
- break;
- default:
- break;
- }
- sqe->type = LIBETH_SQE_EMPTY;
- }
- void libeth_tx_complete_any(struct libeth_sqe *sqe, struct libeth_cq_pp *cp);
- #endif /* __LIBETH_TX_H */
|