drivers/net/ethernet/netronome/nfp/nfp_net_xsk.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/netronome/nfp/nfp_net_xsk.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/netronome/nfp/nfp_net_xsk.c
Extension
.c
Size
4156 bytes
Lines
175
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2018 Netronome Systems, Inc */
/* Copyright (C) 2021 Corigine, Inc */

#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <net/xdp_sock_drv.h>
#include <trace/events/xdp.h>

#include "nfp_app.h"
#include "nfp_net.h"
#include "nfp_net_dp.h"
#include "nfp_net_xsk.h"

static void
nfp_net_xsk_rx_bufs_stash(struct nfp_net_rx_ring *rx_ring, unsigned int idx,
			  struct xdp_buff *xdp)
{
	unsigned int headroom;

	headroom = xsk_pool_get_headroom(rx_ring->r_vec->xsk_pool);

	rx_ring->rxds[idx].fld.reserved = 0;
	rx_ring->rxds[idx].fld.meta_len_dd = 0;

	rx_ring->xsk_rxbufs[idx].xdp = xdp;
	rx_ring->xsk_rxbufs[idx].dma_addr =
		xsk_buff_xdp_get_frame_dma(xdp) + headroom;
}

void nfp_net_xsk_rx_unstash(struct nfp_net_xsk_rx_buf *rxbuf)
{
	rxbuf->dma_addr = 0;
	rxbuf->xdp = NULL;
}

void nfp_net_xsk_rx_free(struct nfp_net_xsk_rx_buf *rxbuf)
{
	if (rxbuf->xdp)
		xsk_buff_free(rxbuf->xdp);

	nfp_net_xsk_rx_unstash(rxbuf);
}

void nfp_net_xsk_rx_bufs_free(struct nfp_net_rx_ring *rx_ring)
{
	unsigned int i;

	if (!rx_ring->cnt)
		return;

	for (i = 0; i < rx_ring->cnt - 1; i++)
		nfp_net_xsk_rx_free(&rx_ring->xsk_rxbufs[i]);
}

void nfp_net_xsk_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring)
{
	struct nfp_net_r_vector *r_vec = rx_ring->r_vec;
	struct xsk_buff_pool *pool = r_vec->xsk_pool;
	unsigned int wr_idx, wr_ptr_add = 0;
	struct xdp_buff *xdp;

	while (nfp_net_rx_space(rx_ring)) {
		wr_idx = D_IDX(rx_ring, rx_ring->wr_p);

		xdp = xsk_buff_alloc(pool);
		if (!xdp)
			break;

		nfp_net_xsk_rx_bufs_stash(rx_ring, wr_idx, xdp);

		/* DMA address is expanded to 48-bit width in freelist for NFP3800,
		 * so the *_48b macro is used accordingly, it's also OK to fill
		 * a 40-bit address since the top 8 bits are get set to 0.
		 */
		nfp_desc_set_dma_addr_48b(&rx_ring->rxds[wr_idx].fld,
					  rx_ring->xsk_rxbufs[wr_idx].dma_addr);

		rx_ring->wr_p++;
		wr_ptr_add++;
	}

	/* Ensure all records are visible before incrementing write counter. */
	wmb();
	nfp_qcp_wr_ptr_add(rx_ring->qcp_fl, wr_ptr_add);
}

void nfp_net_xsk_rx_drop(struct nfp_net_r_vector *r_vec,
			 struct nfp_net_xsk_rx_buf *xrxbuf)

Annotation

Implementation Notes