linux/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2021, Intel Corporation. */
   3
   4#include <net/xdp_sock_drv.h>
   5
   6#include "stmmac.h"
   7#include "stmmac_xdp.h"
   8
   9static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
  10                                  struct xsk_buff_pool *pool, u16 queue)
  11{
  12        struct stmmac_channel *ch = &priv->channel[queue];
  13        bool need_update;
  14        u32 frame_size;
  15        int err;
  16
  17        if (queue >= priv->plat->rx_queues_to_use ||
  18            queue >= priv->plat->tx_queues_to_use)
  19                return -EINVAL;
  20
  21        frame_size = xsk_pool_get_rx_frame_size(pool);
  22        /* XDP ZC does not span multiple frame, make sure XSK pool buffer
  23         * size can at least store Q-in-Q frame.
  24         */
  25        if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2)
  26                return -EOPNOTSUPP;
  27
  28        err = xsk_pool_dma_map(pool, priv->device, STMMAC_RX_DMA_ATTR);
  29        if (err) {
  30                netdev_err(priv->dev, "Failed to map xsk pool\n");
  31                return err;
  32        }
  33
  34        need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
  35
  36        if (need_update) {
  37                napi_disable(&ch->rx_napi);
  38                napi_disable(&ch->tx_napi);
  39                stmmac_disable_rx_queue(priv, queue);
  40                stmmac_disable_tx_queue(priv, queue);
  41        }
  42
  43        set_bit(queue, priv->af_xdp_zc_qps);
  44
  45        if (need_update) {
  46                stmmac_enable_rx_queue(priv, queue);
  47                stmmac_enable_tx_queue(priv, queue);
  48                napi_enable(&ch->rxtx_napi);
  49
  50                err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
  51                if (err)
  52                        return err;
  53        }
  54
  55        return 0;
  56}
  57
  58static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
  59{
  60        struct stmmac_channel *ch = &priv->channel[queue];
  61        struct xsk_buff_pool *pool;
  62        bool need_update;
  63
  64        if (queue >= priv->plat->rx_queues_to_use ||
  65            queue >= priv->plat->tx_queues_to_use)
  66                return -EINVAL;
  67
  68        pool = xsk_get_pool_from_qid(priv->dev, queue);
  69        if (!pool)
  70                return -EINVAL;
  71
  72        need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
  73
  74        if (need_update) {
  75                napi_disable(&ch->rxtx_napi);
  76                stmmac_disable_rx_queue(priv, queue);
  77                stmmac_disable_tx_queue(priv, queue);
  78                synchronize_rcu();
  79        }
  80
  81        xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);
  82
  83        clear_bit(queue, priv->af_xdp_zc_qps);
  84
  85        if (need_update) {
  86                stmmac_enable_rx_queue(priv, queue);
  87                stmmac_enable_tx_queue(priv, queue);
  88                napi_enable(&ch->rx_napi);
  89                napi_enable(&ch->tx_napi);
  90        }
  91
  92        return 0;
  93}
  94
  95int stmmac_xdp_setup_pool(struct stmmac_priv *priv, struct xsk_buff_pool *pool,
  96                          u16 queue)
  97{
  98        return pool ? stmmac_xdp_enable_pool(priv, pool, queue) :
  99                      stmmac_xdp_disable_pool(priv, queue);
 100}
 101
 102int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
 103                        struct netlink_ext_ack *extack)
 104{
 105        struct net_device *dev = priv->dev;
 106        struct bpf_prog *old_prog;
 107        bool need_update;
 108        bool if_running;
 109
 110        if_running = netif_running(dev);
 111
 112        if (prog && dev->mtu > ETH_DATA_LEN) {
 113                /* For now, the driver doesn't support XDP functionality with
 114                 * jumbo frames so we return error.
 115                 */
 116                NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
 117                return -EOPNOTSUPP;
 118        }
 119
 120        need_update = !!priv->xdp_prog != !!prog;
 121        if (if_running && need_update)
 122                stmmac_release(dev);
 123
 124        old_prog = xchg(&priv->xdp_prog, prog);
 125        if (old_prog)
 126                bpf_prog_put(old_prog);
 127
 128        /* Disable RX SPH for XDP operation */
 129        priv->sph = priv->sph_cap && !stmmac_xdp_is_enabled(priv);
 130
 131        if (if_running && need_update)
 132                stmmac_open(dev);
 133
 134        return 0;
 135}
 136