Change XDP program management functional interface to correspond to new XDP API.
Signed-off-by: Tom Herbert <t...@herbertland.com> --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 105 ++++++---------------- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 12 +-- 3 files changed, 33 insertions(+), 87 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 95ca03c..0255423 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -381,7 +381,6 @@ struct mlx5e_rq { u16 rx_headroom; struct mlx5e_rx_am am; /* Adaptive Moderation */ - struct bpf_prog *xdp_prog; /* control */ struct mlx5_wq_ctrl wq_ctrl; @@ -695,7 +694,7 @@ struct mlx5e_priv { /* priv data path fields - start */ struct mlx5e_sq **txq_to_sq_map; int channeltc_to_txq_map[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC]; - struct bpf_prog *xdp_prog; + bool xdp_enabled; /* priv data path fields - end */ unsigned long state; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 3cce628..da91cf52 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -36,6 +36,7 @@ #include <linux/mlx5/fs.h> #include <net/vxlan.h> #include <linux/bpf.h> +#include <net/xdp.h> #include "en.h" #include "en_tc.h" #include "eswitch.h" @@ -113,7 +114,7 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type) static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv) { u8 rq_type = mlx5e_check_fragmented_striding_rq_cap(priv->mdev) && - !priv->xdp_prog ? + !priv->xdp_enabled ? MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ : MLX5_WQ_TYPE_LINKED_LIST; mlx5e_set_rq_type_params(priv, rq_type); @@ -568,14 +569,12 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, rq->ix = c->ix; rq->priv = c->priv; - rq->xdp_prog = priv->xdp_prog ? bpf_prog_inc(priv->xdp_prog) : NULL; - if (IS_ERR(rq->xdp_prog)) { - err = PTR_ERR(rq->xdp_prog); - rq->xdp_prog = NULL; - goto err_rq_wq_destroy; - } - - if (rq->xdp_prog) { + if (priv->xdp_enabled) { + /* Note XDP is checked whether it is enabled for the device. If + * XDP programs are set per ring as opposed to setting program + * across the device this could be adjusted to account for + * that. + */ rq->buff.map_dir = DMA_BIDIRECTIONAL; rq->rx_headroom = XDP_PACKET_HEADROOM; } else { @@ -662,8 +661,6 @@ static int mlx5e_create_rq(struct mlx5e_channel *c, mlx5_core_destroy_mkey(mdev, &rq->umr_mkey); err_rq_wq_destroy: - if (rq->xdp_prog) - bpf_prog_put(rq->xdp_prog); mlx5_wq_destroy(&rq->wq_ctrl); return err; @@ -673,9 +670,6 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq) { int i; - if (rq->xdp_prog) - bpf_prog_put(rq->xdp_prog); - switch (rq->wq_type) { case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ: mlx5e_rq_free_mpwqe_info(rq); @@ -1547,7 +1541,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, c->netdev = priv->netdev; c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); c->num_tc = priv->params.num_tc; - c->xdp = !!priv->xdp_prog; + c->xdp = priv->xdp_enabled; if (priv->params.rx_am_enabled) rx_cq_profile = mlx5e_am_get_def_profile(priv->params.rx_cq_period_mode); @@ -3196,96 +3190,52 @@ static void mlx5e_tx_timeout(struct net_device *dev) schedule_work(&priv->tx_timeout_work); } -static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog) +static int mlx5e_xdp_init(struct net_device *netdev, bool enable) { struct mlx5e_priv *priv = netdev_priv(netdev); - struct bpf_prog *old_prog; int err = 0; - bool reset, was_opened; - int i; + bool was_opened; mutex_lock(&priv->state_lock); - if ((netdev->features & NETIF_F_LRO) && prog) { + if (priv->xdp_enabled == enable) + goto unlock; + + if ((netdev->features & NETIF_F_LRO) && enable) { netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n"); err = -EINVAL; goto unlock; } was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); - /* no need for full reset when exchanging programs */ - reset = (!priv->xdp_prog || !prog); - if (was_opened && reset) + if (was_opened) mlx5e_close_locked(netdev); - if (was_opened && !reset) { - /* num_channels is invariant here, so we can take the - * batched reference right upfront. - */ - prog = bpf_prog_add(prog, priv->params.num_channels); - if (IS_ERR(prog)) { - err = PTR_ERR(prog); - goto unlock; - } - } - /* exchange programs, extra prog reference we got from caller - * as long as we don't fail from this point onwards. - */ - old_prog = xchg(&priv->xdp_prog, prog); - if (old_prog) - bpf_prog_put(old_prog); - - if (reset) /* change RQ type according to priv->xdp_prog */ - mlx5e_set_rq_priv_params(priv); + mlx5e_set_rq_priv_params(priv); - if (was_opened && reset) + if (was_opened) mlx5e_open_locked(netdev); - if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset) - goto unlock; - - /* exchanging programs w/o reset, we update ref counts on behalf - * of the channels RQs here. - */ - for (i = 0; i < priv->params.num_channels; i++) { - struct mlx5e_channel *c = priv->channel[i]; - - clear_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state); - napi_synchronize(&c->napi); - /* prevent mlx5e_poll_rx_cq from accessing rq->xdp_prog */ - - old_prog = xchg(&c->rq.xdp_prog, prog); - - set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state); - /* napi_schedule in case we have missed anything */ - set_bit(MLX5E_CHANNEL_NAPI_SCHED, &c->flags); - napi_schedule(&c->napi); - - if (old_prog) - bpf_prog_put(old_prog); - } - unlock: mutex_unlock(&priv->state_lock); return err; } -static bool mlx5e_xdp_attached(struct net_device *dev) +static int mlx5_xdp_check_bpf(struct net_device *dev, struct bpf_prog *prog) { - struct mlx5e_priv *priv = netdev_priv(dev); - - return !!priv->xdp_prog; + return 0; } static int mlx5e_xdp(struct net_device *dev, struct netdev_xdp *xdp) { switch (xdp->command) { - case XDP_SETUP_PROG: - return mlx5e_xdp_set(dev, xdp->prog); - case XDP_QUERY_PROG: - xdp->prog_attached = mlx5e_xdp_attached(dev); - return 0; + case XDP_MODE_ON: + return mlx5e_xdp_init(dev, true); + case XDP_MODE_OFF: + return mlx5e_xdp_init(dev, false); + case XDP_CHECK_BPF_PROG: + return mlx5_xdp_check_bpf(dev, xdp->prog); default: return -EINVAL; } @@ -3706,9 +3656,6 @@ static void mlx5e_nic_init(struct mlx5_core_dev *mdev, static void mlx5e_nic_cleanup(struct mlx5e_priv *priv) { mlx5e_vxlan_cleanup(priv); - - if (priv->xdp_prog) - bpf_prog_put(priv->xdp_prog); } static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index b039b87..50ab4b9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -721,18 +721,18 @@ static inline int mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di, void *va, u16 *rx_headroom, u32 *len) { - const struct bpf_prog *prog = READ_ONCE(rq->xdp_prog); struct xdp_buff xdp; + struct xdp_hook *last_hook; u32 act; - if (!prog) + if (!xdp_hook_run_needed_check(rq->netdev, rq->cq.napi)) return false; xdp.data = va + *rx_headroom; xdp.data_end = xdp.data + *len; xdp.data_hard_start = va; - act = bpf_prog_run_xdp(prog, &xdp); + act = xdp_hook_run_ret_last(rq->cq.napi, &xdp, &last_hook); switch (act) { case XDP_PASS: *rx_headroom = xdp.data - xdp.data_hard_start; @@ -740,12 +740,12 @@ static inline int mlx5e_xdp_handle(struct mlx5e_rq *rq, return false; case XDP_TX: if (unlikely(!mlx5e_xmit_xdp_frame(rq, di, &xdp))) - trace_xdp_exception(rq->netdev, prog, act); + trace_xdp_hook_exception(rq->netdev, last_hook, act); return true; default: - bpf_warn_invalid_xdp_action(act); + xdp_warn_invalid_action(act); case XDP_ABORTED: - trace_xdp_exception(rq->netdev, prog, act); + trace_xdp_hook_exception(rq->netdev, last_hook, act); case XDP_DROP: rq->stats.xdp_drop++; mlx5e_page_release(rq, di, true); -- 2.9.3