diff options
author | Martin KaFai Lau <kafai@fb.com> | 2017-02-01 01:35:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-02-02 21:27:05 -0500 |
commit | 770f82253dbd7e6892a88018f2f6cd395f48d214 (patch) | |
tree | 177c454b09676bb54648883037b2d66c40bbdf74 | |
parent | f32b20e89e82c9ff1825fc5c5d69753ff5558ccd (diff) |
mlx4: xdp_prog becomes inactive after ethtool '-L' or '-G'
After calling mlx4_en_try_alloc_resources (e.g. by changing the
number of rx-queues with ethtool -L), the existing xdp_prog becomes
inactive.
The bug is that the xdp_prog ptr has not been carried over from
the old rx-queues to the new rx-queues
Fixes: 47a38e155037 ("net/mlx4_en: add support for fast rx drop bpf program")
Cc: Brenden Blanco <bblanco@plumgrid.com>
Cc: Saeed Mahameed <saeedm@mellanox.com>
Cc: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 |
3 files changed, 27 insertions, 7 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index d5a9372ed84d..9aa422691954 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | |||
@@ -1099,7 +1099,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, | |||
1099 | memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); | 1099 | memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); |
1100 | new_prof.tx_ring_size = tx_size; | 1100 | new_prof.tx_ring_size = tx_size; |
1101 | new_prof.rx_ring_size = rx_size; | 1101 | new_prof.rx_ring_size = rx_size; |
1102 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); | 1102 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true); |
1103 | if (err) | 1103 | if (err) |
1104 | goto out; | 1104 | goto out; |
1105 | 1105 | ||
@@ -1774,7 +1774,7 @@ static int mlx4_en_set_channels(struct net_device *dev, | |||
1774 | new_prof.tx_ring_num[TX_XDP] = xdp_count; | 1774 | new_prof.tx_ring_num[TX_XDP] = xdp_count; |
1775 | new_prof.rx_ring_num = channel->rx_count; | 1775 | new_prof.rx_ring_num = channel->rx_count; |
1776 | 1776 | ||
1777 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); | 1777 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true); |
1778 | if (err) | 1778 | if (err) |
1779 | goto out; | 1779 | goto out; |
1780 | 1780 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 3abcead208d2..3b4961a8e8e4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -2186,9 +2186,11 @@ static void mlx4_en_update_priv(struct mlx4_en_priv *dst, | |||
2186 | 2186 | ||
2187 | int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, | 2187 | int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, |
2188 | struct mlx4_en_priv *tmp, | 2188 | struct mlx4_en_priv *tmp, |
2189 | struct mlx4_en_port_profile *prof) | 2189 | struct mlx4_en_port_profile *prof, |
2190 | bool carry_xdp_prog) | ||
2190 | { | 2191 | { |
2191 | int t; | 2192 | struct bpf_prog *xdp_prog; |
2193 | int i, t; | ||
2192 | 2194 | ||
2193 | mlx4_en_copy_priv(tmp, priv, prof); | 2195 | mlx4_en_copy_priv(tmp, priv, prof); |
2194 | 2196 | ||
@@ -2202,6 +2204,23 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, | |||
2202 | } | 2204 | } |
2203 | return -ENOMEM; | 2205 | return -ENOMEM; |
2204 | } | 2206 | } |
2207 | |||
2208 | /* All rx_rings has the same xdp_prog. Pick the first one. */ | ||
2209 | xdp_prog = rcu_dereference_protected( | ||
2210 | priv->rx_ring[0]->xdp_prog, | ||
2211 | lockdep_is_held(&priv->mdev->state_lock)); | ||
2212 | |||
2213 | if (xdp_prog && carry_xdp_prog) { | ||
2214 | xdp_prog = bpf_prog_add(xdp_prog, tmp->rx_ring_num); | ||
2215 | if (IS_ERR(xdp_prog)) { | ||
2216 | mlx4_en_free_resources(tmp); | ||
2217 | return PTR_ERR(xdp_prog); | ||
2218 | } | ||
2219 | for (i = 0; i < tmp->rx_ring_num; i++) | ||
2220 | rcu_assign_pointer(tmp->rx_ring[i]->xdp_prog, | ||
2221 | xdp_prog); | ||
2222 | } | ||
2223 | |||
2205 | return 0; | 2224 | return 0; |
2206 | } | 2225 | } |
2207 | 2226 | ||
@@ -2751,7 +2770,7 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog) | |||
2751 | en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n"); | 2770 | en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n"); |
2752 | } | 2771 | } |
2753 | 2772 | ||
2754 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); | 2773 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, false); |
2755 | if (err) { | 2774 | if (err) { |
2756 | if (prog) | 2775 | if (prog) |
2757 | bpf_prog_sub(prog, priv->rx_ring_num - 1); | 2776 | bpf_prog_sub(prog, priv->rx_ring_num - 1); |
@@ -3495,7 +3514,7 @@ int mlx4_en_reset_config(struct net_device *dev, | |||
3495 | memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); | 3514 | memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile)); |
3496 | memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config)); | 3515 | memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config)); |
3497 | 3516 | ||
3498 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof); | 3517 | err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true); |
3499 | if (err) | 3518 | if (err) |
3500 | goto out; | 3519 | goto out; |
3501 | 3520 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index ba1c6cd0cc79..cec59bc264c9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -679,7 +679,8 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev, | |||
679 | 679 | ||
680 | int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, | 680 | int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, |
681 | struct mlx4_en_priv *tmp, | 681 | struct mlx4_en_priv *tmp, |
682 | struct mlx4_en_port_profile *prof); | 682 | struct mlx4_en_port_profile *prof, |
683 | bool carry_xdp_prog); | ||
683 | void mlx4_en_safe_replace_resources(struct mlx4_en_priv *priv, | 684 | void mlx4_en_safe_replace_resources(struct mlx4_en_priv *priv, |
684 | struct mlx4_en_priv *tmp); | 685 | struct mlx4_en_priv *tmp); |
685 | 686 | ||