]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net/mlx5e: Fix concurrency issues between config flow and XSK
authorMaxim Mikityanskiy <maximmi@mellanox.com>
Tue, 17 Dec 2019 16:20:44 +0000 (16:20 +0000)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 19 Dec 2019 15:20:49 +0000 (16:20 +0100)
After disabling resources necessary for XSK (the XDP program, channels,
XSK queues), use synchronize_rcu to wait until the XSK wakeup function
finishes, before freeing the resources.

Suspend XSK wakeups during switching channels. If the XDP program is
being removed, synchronize_rcu before closing the old channels to allow
XSK wakeup to complete.

Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20191217162023.16011-3-maximmi@mellanox.com
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index 2c16add0b642fb1a4d13d8f9807e337835aa157b..9c8427698238feffc4e2a2d654a12331005a7177 100644 (file)
@@ -760,7 +760,7 @@ enum {
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
        MLX5E_STATE_XDP_TX_ENABLED,
-       MLX5E_STATE_XDP_OPEN,
+       MLX5E_STATE_XDP_ACTIVE,
 };
 
 struct mlx5e_rqt {
index 36ac1e3816b9d6856960c114a6f8134d1c1b534b..d7587f40ecaecab577545f8796c6ade7da39abaa 100644 (file)
@@ -75,12 +75,18 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
 static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
 {
        set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+
+       if (priv->channels.params.xdp_prog)
+               set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
 {
+       if (priv->channels.params.xdp_prog)
+               clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
+
        clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
-       /* let other device's napi(s) see our new state */
+       /* Let other device's napi(s) and XSK wakeups see our new state. */
        synchronize_rcu();
 }
 
@@ -89,19 +95,9 @@ static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
        return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
 }
 
-static inline void mlx5e_xdp_set_open(struct mlx5e_priv *priv)
-{
-       set_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline void mlx5e_xdp_set_closed(struct mlx5e_priv *priv)
-{
-       clear_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline bool mlx5e_xdp_is_open(struct mlx5e_priv *priv)
+static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv)
 {
-       return test_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
+       return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
index 631af8dee5171d67447e5eefac4809a115bb4e3e..c28cbae4233103fda64496357525f96a2dfac98e 100644 (file)
@@ -144,6 +144,7 @@ void mlx5e_close_xsk(struct mlx5e_channel *c)
 {
        clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
        napi_synchronize(&c->napi);
+       synchronize_rcu(); /* Sync with the XSK wakeup. */
 
        mlx5e_close_rq(&c->xskrq);
        mlx5e_close_cq(&c->xskrq.cq);
index 87827477d38c48dc71d795a1a142634a1c3a5933..fe2d596cb361fa1ae03bfbfe28c2741965804f4b 100644 (file)
@@ -14,7 +14,7 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
        struct mlx5e_channel *c;
        u16 ix;
 
-       if (unlikely(!mlx5e_xdp_is_open(priv)))
+       if (unlikely(!mlx5e_xdp_is_active(priv)))
                return -ENETDOWN;
 
        if (unlikely(!mlx5e_qid_get_ch_if_in_group(params, qid, MLX5E_RQ_GROUP_XSK, &ix)))
index 4980e80a5e85ddb58fa66cda25c6280724be1ed2..4997b8a51994bc6b23f4ef5cfa0375192975711f 100644 (file)
@@ -3000,12 +3000,9 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
 int mlx5e_open_locked(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       bool is_xdp = priv->channels.params.xdp_prog;
        int err;
 
        set_bit(MLX5E_STATE_OPENED, &priv->state);
-       if (is_xdp)
-               mlx5e_xdp_set_open(priv);
 
        err = mlx5e_open_channels(priv, &priv->channels);
        if (err)
@@ -3020,8 +3017,6 @@ int mlx5e_open_locked(struct net_device *netdev)
        return 0;
 
 err_clear_state_opened_flag:
-       if (is_xdp)
-               mlx5e_xdp_set_closed(priv);
        clear_bit(MLX5E_STATE_OPENED, &priv->state);
        return err;
 }
@@ -3053,8 +3048,6 @@ int mlx5e_close_locked(struct net_device *netdev)
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
                return 0;
 
-       if (priv->channels.params.xdp_prog)
-               mlx5e_xdp_set_closed(priv);
        clear_bit(MLX5E_STATE_OPENED, &priv->state);
 
        netif_carrier_off(priv->netdev);
@@ -4371,16 +4364,6 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
        return 0;
 }
 
-static int mlx5e_xdp_update_state(struct mlx5e_priv *priv)
-{
-       if (priv->channels.params.xdp_prog)
-               mlx5e_xdp_set_open(priv);
-       else
-               mlx5e_xdp_set_closed(priv);
-
-       return 0;
-}
-
 static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4415,7 +4398,7 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
                mlx5e_set_rq_type(priv->mdev, &new_channels.params);
                old_prog = priv->channels.params.xdp_prog;
 
-               err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_xdp_update_state);
+               err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
                if (err)
                        goto unlock;
        } else {