|
@@ -156,9 +156,8 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
|
|
|
mutex_lock(&mdev->state_lock);
|
|
|
if (priv->port_up) {
|
|
|
/* Remove old MAC and insert the new one */
|
|
|
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
|
|
- err = mlx4_register_mac(mdev->dev, priv->port,
|
|
|
- priv->mac, &priv->mac_index);
|
|
|
+ err = mlx4_replace_mac(mdev->dev, priv->port,
|
|
|
+ priv->base_qpn, priv->mac, 0);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed changing HW MAC address\n");
|
|
|
} else
|
|
@@ -214,6 +213,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
struct mlx4_en_dev *mdev = priv->mdev;
|
|
|
struct net_device *dev = priv->dev;
|
|
|
u64 mcast_addr = 0;
|
|
|
+ u8 mc_list[16] = {0};
|
|
|
int err;
|
|
|
|
|
|
mutex_lock(&mdev->state_lock);
|
|
@@ -239,8 +239,12 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
priv->flags |= MLX4_EN_FLAG_PROMISC;
|
|
|
|
|
|
/* Enable promiscouos mode */
|
|
|
- err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
|
|
- priv->base_qpn, 1);
|
|
|
+ if (!mdev->dev->caps.vep_uc_steering)
|
|
|
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
|
|
+ priv->base_qpn, 1);
|
|
|
+ else
|
|
|
+ err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed enabling "
|
|
|
"promiscous mode\n");
|
|
@@ -252,10 +256,21 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
en_err(priv, "Failed disabling "
|
|
|
"multicast filter\n");
|
|
|
|
|
|
- /* Disable port VLAN filter */
|
|
|
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
|
|
|
- if (err)
|
|
|
- en_err(priv, "Failed disabling VLAN filter\n");
|
|
|
+ /* Add the default qp number as multicast promisc */
|
|
|
+ if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
|
|
|
+ err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
+ if (err)
|
|
|
+ en_err(priv, "Failed entering multicast promisc mode\n");
|
|
|
+ priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (priv->vlgrp) {
|
|
|
+ /* Disable port VLAN filter */
|
|
|
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
|
|
|
+ if (err)
|
|
|
+ en_err(priv, "Failed disabling VLAN filter\n");
|
|
|
+ }
|
|
|
}
|
|
|
goto out;
|
|
|
}
|
|
@@ -270,11 +285,24 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
priv->flags &= ~MLX4_EN_FLAG_PROMISC;
|
|
|
|
|
|
/* Disable promiscouos mode */
|
|
|
- err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
|
|
- priv->base_qpn, 0);
|
|
|
+ if (!mdev->dev->caps.vep_uc_steering)
|
|
|
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
|
|
+ priv->base_qpn, 0);
|
|
|
+ else
|
|
|
+ err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed disabling promiscous mode\n");
|
|
|
|
|
|
+ /* Disable Multicast promisc */
|
|
|
+ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
|
|
|
+ err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
+ if (err)
|
|
|
+ en_err(priv, "Failed disabling multicast promiscous mode\n");
|
|
|
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
|
|
|
+ }
|
|
|
+
|
|
|
/* Enable port VLAN filter */
|
|
|
err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
|
|
|
if (err)
|
|
@@ -287,14 +315,38 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
0, MLX4_MCAST_DISABLE);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed disabling multicast filter\n");
|
|
|
+
|
|
|
+ /* Add the default qp number as multicast promisc */
|
|
|
+ if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
|
|
|
+ err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
+ if (err)
|
|
|
+ en_err(priv, "Failed entering multicast promisc mode\n");
|
|
|
+ priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
|
|
|
+ }
|
|
|
} else {
|
|
|
int i;
|
|
|
+ /* Disable Multicast promisc */
|
|
|
+ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
|
|
|
+ err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
|
|
|
+ priv->port);
|
|
|
+ if (err)
|
|
|
+ en_err(priv, "Failed disabling multicast promiscous mode\n");
|
|
|
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
|
|
|
+ }
|
|
|
|
|
|
err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
|
|
|
0, MLX4_MCAST_DISABLE);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed disabling multicast filter\n");
|
|
|
|
|
|
+ /* Detach our qp from all the multicast addresses */
|
|
|
+ for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
|
|
+ memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
|
|
+ mc_list[5] = priv->port;
|
|
|
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
|
|
|
+ mc_list, MLX4_PROT_ETH);
|
|
|
+ }
|
|
|
/* Flush mcast filter and init it with broadcast address */
|
|
|
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
|
|
|
1, MLX4_MCAST_CONFIG);
|
|
@@ -307,6 +359,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
|
|
mcast_addr =
|
|
|
mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN);
|
|
|
+ memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
|
|
+ mc_list[5] = priv->port;
|
|
|
+ mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
|
|
|
+ mc_list, 0, MLX4_PROT_ETH);
|
|
|
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
|
|
|
mcast_addr, 0, MLX4_MCAST_CONFIG);
|
|
|
}
|
|
@@ -314,8 +370,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
|
|
0, MLX4_MCAST_ENABLE);
|
|
|
if (err)
|
|
|
en_err(priv, "Failed enabling multicast filter\n");
|
|
|
-
|
|
|
- mlx4_en_clear_list(dev);
|
|
|
}
|
|
|
out:
|
|
|
mutex_unlock(&mdev->state_lock);
|
|
@@ -557,6 +611,7 @@ int mlx4_en_start_port(struct net_device *dev)
|
|
|
int err = 0;
|
|
|
int i;
|
|
|
int j;
|
|
|
+ u8 mc_list[16] = {0};
|
|
|
char name[32];
|
|
|
|
|
|
if (priv->port_up) {
|
|
@@ -596,10 +651,20 @@ int mlx4_en_start_port(struct net_device *dev)
|
|
|
++rx_index;
|
|
|
}
|
|
|
|
|
|
+ /* Set port mac number */
|
|
|
+ en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
|
|
|
+ err = mlx4_register_mac(mdev->dev, priv->port,
|
|
|
+ priv->mac, &priv->base_qpn, 0);
|
|
|
+ if (err) {
|
|
|
+ en_err(priv, "Failed setting port mac\n");
|
|
|
+ goto cq_err;
|
|
|
+ }
|
|
|
+ mdev->mac_removed[priv->port] = 0;
|
|
|
+
|
|
|
err = mlx4_en_config_rss_steer(priv);
|
|
|
if (err) {
|
|
|
en_err(priv, "Failed configuring rss steering\n");
|
|
|
- goto cq_err;
|
|
|
+ goto mac_err;
|
|
|
}
|
|
|
|
|
|
if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
|
|
@@ -661,24 +726,22 @@ int mlx4_en_start_port(struct net_device *dev)
|
|
|
en_err(priv, "Failed setting default qp numbers\n");
|
|
|
goto tx_err;
|
|
|
}
|
|
|
- /* Set port mac number */
|
|
|
- en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
|
|
|
- err = mlx4_register_mac(mdev->dev, priv->port,
|
|
|
- priv->mac, &priv->mac_index);
|
|
|
- if (err) {
|
|
|
- en_err(priv, "Failed setting port mac\n");
|
|
|
- goto tx_err;
|
|
|
- }
|
|
|
- mdev->mac_removed[priv->port] = 0;
|
|
|
|
|
|
/* Init port */
|
|
|
en_dbg(HW, priv, "Initializing port\n");
|
|
|
err = mlx4_INIT_PORT(mdev->dev, priv->port);
|
|
|
if (err) {
|
|
|
en_err(priv, "Failed Initializing port\n");
|
|
|
- goto mac_err;
|
|
|
+ goto tx_err;
|
|
|
}
|
|
|
|
|
|
+ /* Attach rx QP to bradcast address */
|
|
|
+ memset(&mc_list[10], 0xff, ETH_ALEN);
|
|
|
+ mc_list[5] = priv->port;
|
|
|
+ if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
|
|
|
+ 0, MLX4_PROT_ETH))
|
|
|
+ mlx4_warn(mdev, "Failed Attaching Broadcast\n");
|
|
|
+
|
|
|
/* Schedule multicast task to populate multicast list */
|
|
|
queue_work(mdev->workqueue, &priv->mcast_task);
|
|
|
|
|
@@ -686,8 +749,6 @@ int mlx4_en_start_port(struct net_device *dev)
|
|
|
netif_tx_start_all_queues(dev);
|
|
|
return 0;
|
|
|
|
|
|
-mac_err:
|
|
|
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
|
|
tx_err:
|
|
|
while (tx_index--) {
|
|
|
mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
|
|
@@ -695,6 +756,8 @@ tx_err:
|
|
|
}
|
|
|
|
|
|
mlx4_en_release_rss_steer(priv);
|
|
|
+mac_err:
|
|
|
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
|
|
|
cq_err:
|
|
|
while (rx_index--)
|
|
|
mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
|
|
@@ -710,6 +773,7 @@ void mlx4_en_stop_port(struct net_device *dev)
|
|
|
struct mlx4_en_priv *priv = netdev_priv(dev);
|
|
|
struct mlx4_en_dev *mdev = priv->mdev;
|
|
|
int i;
|
|
|
+ u8 mc_list[16] = {0};
|
|
|
|
|
|
if (!priv->port_up) {
|
|
|
en_dbg(DRV, priv, "stop port called while port already down\n");
|
|
@@ -724,8 +788,23 @@ void mlx4_en_stop_port(struct net_device *dev)
|
|
|
/* Set port as not active */
|
|
|
priv->port_up = false;
|
|
|
|
|
|
+ /* Detach All multicasts */
|
|
|
+ memset(&mc_list[10], 0xff, ETH_ALEN);
|
|
|
+ mc_list[5] = priv->port;
|
|
|
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
|
|
|
+ MLX4_PROT_ETH);
|
|
|
+ for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
|
|
+ memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
|
|
+ mc_list[5] = priv->port;
|
|
|
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
|
|
|
+ mc_list, MLX4_PROT_ETH);
|
|
|
+ }
|
|
|
+ mlx4_en_clear_list(dev);
|
|
|
+ /* Flush multicast filter */
|
|
|
+ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
|
|
|
+
|
|
|
/* Unregister Mac address for the port */
|
|
|
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
|
|
+ mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
|
|
|
mdev->mac_removed[priv->port] = 1;
|
|
|
|
|
|
/* Free TX Rings */
|