Commit ba4b87ae authored by Ido Shamay's avatar Ido Shamay Committed by David S. Miller

net/mlx4_en: Add steering rules after RSS creation

Changed the receive control flow in a way that steering
rules are added only when the RSS object is already in RTR/RTS mode.
Some optimization features, which are enabled by the device firmware,
require this condition in order to be effective.
Signed-off-by: default avatarIdo Shamay <idos@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ac6ea6e8
...@@ -573,10 +573,8 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) ...@@ -573,10 +573,8 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
{ {
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_dev *dev = mdev->dev; struct mlx4_dev *dev = mdev->dev;
struct mlx4_mac_entry *entry;
int index = 0; int index = 0;
int err = 0; int err = 0;
u64 reg_id = 0;
int *qpn = &priv->base_qpn; int *qpn = &priv->base_qpn;
u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr); u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr);
...@@ -600,44 +598,11 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) ...@@ -600,44 +598,11 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
en_dbg(DRV, priv, "Reserved qp %d\n", *qpn); en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
if (err) { if (err) {
en_err(priv, "Failed to reserve qp for mac registration\n"); en_err(priv, "Failed to reserve qp for mac registration\n");
goto qp_err; mlx4_unregister_mac(dev, priv->port, mac);
} return err;
err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, &reg_id);
if (err)
goto steer_err;
err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn,
&priv->tunnel_reg_id);
if (err)
goto tunnel_err;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
err = -ENOMEM;
goto alloc_err;
} }
memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
entry->reg_id = reg_id;
hlist_add_head_rcu(&entry->hlist,
&priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
return 0; return 0;
alloc_err:
if (priv->tunnel_reg_id)
mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
tunnel_err:
mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
steer_err:
mlx4_qp_release_range(dev, *qpn, 1);
qp_err:
mlx4_unregister_mac(dev, priv->port, mac);
return err;
} }
static void mlx4_en_put_qp(struct mlx4_en_priv *priv) static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
...@@ -645,39 +610,13 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv) ...@@ -645,39 +610,13 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_dev *dev = mdev->dev; struct mlx4_dev *dev = mdev->dev;
int qpn = priv->base_qpn; int qpn = priv->base_qpn;
u64 mac;
if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) { if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
mac = mlx4_mac_to_u64(priv->dev->dev_addr); u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr);
en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
priv->dev->dev_addr); priv->dev->dev_addr);
mlx4_unregister_mac(dev, priv->port, mac); mlx4_unregister_mac(dev, priv->port, mac);
} else { } else {
struct mlx4_mac_entry *entry;
struct hlist_node *tmp;
struct hlist_head *bucket;
unsigned int i;
for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
bucket = &priv->mac_hash[i];
hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
mac = mlx4_mac_to_u64(entry->mac);
en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
entry->mac);
mlx4_en_uc_steer_release(priv, entry->mac,
qpn, entry->reg_id);
mlx4_unregister_mac(dev, priv->port, mac);
hlist_del_rcu(&entry->hlist);
kfree_rcu(entry, rcu);
}
}
if (priv->tunnel_reg_id) {
mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
priv->tunnel_reg_id = 0;
}
en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n", en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
priv->port, qpn); priv->port, qpn);
mlx4_qp_release_range(dev, qpn, 1); mlx4_qp_release_range(dev, qpn, 1);
...@@ -1283,6 +1222,75 @@ static void mlx4_en_netpoll(struct net_device *dev) ...@@ -1283,6 +1222,75 @@ static void mlx4_en_netpoll(struct net_device *dev)
} }
#endif #endif
static int mlx4_en_set_rss_steer_rules(struct mlx4_en_priv *priv)
{
u64 reg_id;
int err = 0;
int *qpn = &priv->base_qpn;
struct mlx4_mac_entry *entry;
err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, &reg_id);
if (err)
return err;
err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn,
&priv->tunnel_reg_id);
if (err)
goto tunnel_err;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
err = -ENOMEM;
goto alloc_err;
}
memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
entry->reg_id = reg_id;
hlist_add_head_rcu(&entry->hlist,
&priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
return 0;
alloc_err:
if (priv->tunnel_reg_id)
mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
tunnel_err:
mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
return err;
}
static void mlx4_en_delete_rss_steer_rules(struct mlx4_en_priv *priv)
{
u64 mac;
unsigned int i;
int qpn = priv->base_qpn;
struct hlist_head *bucket;
struct hlist_node *tmp;
struct mlx4_mac_entry *entry;
for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
bucket = &priv->mac_hash[i];
hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
mac = mlx4_mac_to_u64(entry->mac);
en_dbg(DRV, priv, "Registering MAC:%pM for deleting\n",
entry->mac);
mlx4_en_uc_steer_release(priv, entry->mac,
qpn, entry->reg_id);
mlx4_unregister_mac(priv->mdev->dev, priv->port, mac);
hlist_del_rcu(&entry->hlist);
kfree_rcu(entry, rcu);
}
}
if (priv->tunnel_reg_id) {
mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
priv->tunnel_reg_id = 0;
}
}
static void mlx4_en_tx_timeout(struct net_device *dev) static void mlx4_en_tx_timeout(struct net_device *dev)
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
...@@ -1684,6 +1692,11 @@ int mlx4_en_start_port(struct net_device *dev) ...@@ -1684,6 +1692,11 @@ int mlx4_en_start_port(struct net_device *dev)
goto tx_err; goto tx_err;
} }
/* Set Unicast and VXLAN steering rules */
if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0 &&
mlx4_en_set_rss_steer_rules(priv))
mlx4_warn(mdev, "Failed setting steering rules\n");
/* Attach rx QP to bradcast address */ /* Attach rx QP to bradcast address */
eth_broadcast_addr(&mc_list[10]); eth_broadcast_addr(&mc_list[10]);
mc_list[5] = priv->port; /* needed for B0 steering support */ mc_list[5] = priv->port; /* needed for B0 steering support */
...@@ -1831,6 +1844,9 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) ...@@ -1831,6 +1844,9 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
for (i = 0; i < priv->tx_ring_num; i++) for (i = 0; i < priv->tx_ring_num; i++)
mlx4_en_free_tx_buf(dev, priv->tx_ring[i]); mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
mlx4_en_delete_rss_steer_rules(priv);
/* Free RSS qps */ /* Free RSS qps */
mlx4_en_release_rss_steer(priv); mlx4_en_release_rss_steer(priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment