diff options
author | Noa Osherovich <noaos@mellanox.com> | 2014-07-08 04:25:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 22:58:45 -0400 |
commit | 2695bab2a6a18f31839c4e862eba3b450c0d2868 (patch) | |
tree | 21d8b55f81282fecf3c4c7bbe3880f508368abbd /drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |
parent | d5b8dff0073d782f3169e510fd9445f1f56994e2 (diff) |
net/mlx4_en: Fix mac_hash database inconsistency
Using a local copy of dev_addr in mlx4_en_set_mac() to prevent dev_addr
from being modified during error flow or when dev_addr is modified in
another context (which is another problem that is being discussed over
the mailing list [1]).
Also fixing bad naming of priv->prev_mac into priv->current_mac.
[1] - http://patchwork.ozlabs.org/patch/351489/
Reviewed-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Noa Osherovich <noaos@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/en_netdev.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 255950adcc6b..f384b354c88d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -760,21 +760,22 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn, | |||
760 | return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64); | 760 | return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64); |
761 | } | 761 | } |
762 | 762 | ||
763 | static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv) | 763 | static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv, |
764 | unsigned char new_mac[ETH_ALEN + 2]) | ||
764 | { | 765 | { |
765 | int err = 0; | 766 | int err = 0; |
766 | 767 | ||
767 | if (priv->port_up) { | 768 | if (priv->port_up) { |
768 | /* Remove old MAC and insert the new one */ | 769 | /* Remove old MAC and insert the new one */ |
769 | err = mlx4_en_replace_mac(priv, priv->base_qpn, | 770 | err = mlx4_en_replace_mac(priv, priv->base_qpn, |
770 | priv->dev->dev_addr, priv->prev_mac); | 771 | new_mac, priv->current_mac); |
771 | if (err) | 772 | if (err) |
772 | en_err(priv, "Failed changing HW MAC address\n"); | 773 | en_err(priv, "Failed changing HW MAC address\n"); |
773 | } else | 774 | } else |
774 | en_dbg(HW, priv, "Port is down while registering mac, exiting...\n"); | 775 | en_dbg(HW, priv, "Port is down while registering mac, exiting...\n"); |
775 | 776 | ||
776 | memcpy(priv->prev_mac, priv->dev->dev_addr, | 777 | if (!err) |
777 | sizeof(priv->prev_mac)); | 778 | memcpy(priv->current_mac, new_mac, sizeof(priv->current_mac)); |
778 | 779 | ||
779 | return err; | 780 | return err; |
780 | } | 781 | } |
@@ -784,14 +785,17 @@ static int mlx4_en_set_mac(struct net_device *dev, void *addr) | |||
784 | struct mlx4_en_priv *priv = netdev_priv(dev); | 785 | struct mlx4_en_priv *priv = netdev_priv(dev); |
785 | struct mlx4_en_dev *mdev = priv->mdev; | 786 | struct mlx4_en_dev *mdev = priv->mdev; |
786 | struct sockaddr *saddr = addr; | 787 | struct sockaddr *saddr = addr; |
788 | unsigned char new_mac[ETH_ALEN + 2]; | ||
787 | int err; | 789 | int err; |
788 | 790 | ||
789 | if (!is_valid_ether_addr(saddr->sa_data)) | 791 | if (!is_valid_ether_addr(saddr->sa_data)) |
790 | return -EADDRNOTAVAIL; | 792 | return -EADDRNOTAVAIL; |
791 | 793 | ||
792 | mutex_lock(&mdev->state_lock); | 794 | mutex_lock(&mdev->state_lock); |
793 | memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); | 795 | memcpy(new_mac, saddr->sa_data, ETH_ALEN); |
794 | err = mlx4_en_do_set_mac(priv); | 796 | err = mlx4_en_do_set_mac(priv, new_mac); |
797 | if (!err) | ||
798 | memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); | ||
795 | mutex_unlock(&mdev->state_lock); | 799 | mutex_unlock(&mdev->state_lock); |
796 | 800 | ||
797 | return err; | 801 | return err; |
@@ -1156,7 +1160,8 @@ static void mlx4_en_do_uc_filter(struct mlx4_en_priv *priv, | |||
1156 | } | 1160 | } |
1157 | 1161 | ||
1158 | /* MAC address of the port is not in uc list */ | 1162 | /* MAC address of the port is not in uc list */ |
1159 | if (ether_addr_equal_64bits(entry->mac, dev->dev_addr)) | 1163 | if (ether_addr_equal_64bits(entry->mac, |
1164 | priv->current_mac)) | ||
1160 | found = true; | 1165 | found = true; |
1161 | 1166 | ||
1162 | if (!found) { | 1167 | if (!found) { |
@@ -1466,7 +1471,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work) | |||
1466 | queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); | 1471 | queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); |
1467 | } | 1472 | } |
1468 | if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { | 1473 | if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { |
1469 | mlx4_en_do_set_mac(priv); | 1474 | mlx4_en_do_set_mac(priv, priv->current_mac); |
1470 | mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; | 1475 | mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; |
1471 | } | 1476 | } |
1472 | mutex_unlock(&mdev->state_lock); | 1477 | mutex_unlock(&mdev->state_lock); |
@@ -2524,7 +2529,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2524 | } | 2529 | } |
2525 | } | 2530 | } |
2526 | 2531 | ||
2527 | memcpy(priv->prev_mac, dev->dev_addr, sizeof(priv->prev_mac)); | 2532 | memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac)); |
2528 | 2533 | ||
2529 | priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + | 2534 | priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + |
2530 | DS_SIZE * MLX4_EN_MAX_RX_FRAGS); | 2535 | DS_SIZE * MLX4_EN_MAX_RX_FRAGS); |