drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
Extension
.c
Size
3394 bytes
Lines
142
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
/* Copyright (c) 2021, Intel Corporation. */

#include <net/xdp_sock_drv.h>

#include "stmmac.h"
#include "stmmac_xdp.h"

static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
				  struct xsk_buff_pool *pool, u16 queue)
{
	struct stmmac_channel *ch = &priv->channel[queue];
	bool need_update;
	u32 frame_size;
	int err;

	if (queue >= priv->plat->rx_queues_to_use ||
	    queue >= priv->plat->tx_queues_to_use)
		return -EINVAL;

	frame_size = xsk_pool_get_rx_frame_size(pool);
	/* XDP ZC does not span multiple frame, make sure XSK pool buffer
	 * size can at least store Q-in-Q frame.
	 */
	if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2)
		return -EOPNOTSUPP;

	err = xsk_pool_dma_map(pool, priv->device, STMMAC_RX_DMA_ATTR);
	if (err) {
		netdev_err(priv->dev, "Failed to map xsk pool\n");
		return err;
	}

	need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);

	if (need_update) {
		napi_disable(&ch->rx_napi);
		napi_disable(&ch->tx_napi);
		stmmac_disable_rx_queue(priv, queue);
		stmmac_disable_tx_queue(priv, queue);
	}

	set_bit(queue, priv->af_xdp_zc_qps);

	if (need_update) {
		stmmac_enable_rx_queue(priv, queue);
		stmmac_enable_tx_queue(priv, queue);
		napi_enable(&ch->rxtx_napi);

		err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
		if (err)
			return err;
	}

	return 0;
}

static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
{
	struct stmmac_channel *ch = &priv->channel[queue];
	struct xsk_buff_pool *pool;
	bool need_update;

	if (queue >= priv->plat->rx_queues_to_use ||
	    queue >= priv->plat->tx_queues_to_use)
		return -EINVAL;

	pool = xsk_get_pool_from_qid(priv->dev, queue);
	if (!pool)
		return -EINVAL;

	need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);

	if (need_update) {
		napi_disable(&ch->rxtx_napi);
		stmmac_disable_rx_queue(priv, queue);
		stmmac_disable_tx_queue(priv, queue);
		synchronize_rcu();
	}

	xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);

	clear_bit(queue, priv->af_xdp_zc_qps);

	if (need_update) {
		stmmac_enable_rx_queue(priv, queue);
		stmmac_enable_tx_queue(priv, queue);
		napi_enable(&ch->rx_napi);
		napi_enable(&ch->tx_napi);
	}

Annotation

Implementation Notes