aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox
diff options
context:
space:
mode:
authorYan Burman <yanb@mellanox.com>2013-03-06 22:46:55 -0500
committerDavid S. Miller <davem@davemloft.net>2013-03-07 15:52:04 -0500
commitbfa8ab47415a87c6c93a9e54e16f2f8cc6de79af (patch)
treed529eba9c805f34b8c27f5b40e543d2f61c3cc7d /drivers/net/ethernet/mellanox
parente7dbeba85600aa2c8daf99f8f53d9ad27e88b810 (diff)
net/mlx4_en: Fix race when setting the device MAC address
Remove unnecessary use of workqueue for the device MAC address setting flow, and fix a race when setting MAC address which was introduced by commit c07cb4b0a "net/mlx4_en: Manage hash of MAC addresses per port" The race happened when mlx4_en_replace_mac was being executed in parallel with a successive call to ndo_set_mac_address, e.g witn an A/B/A MAC setting configuration test, the third set fails. With this change we also properly report an error if set MAC fails. Signed-off-by: Yan Burman <yanb@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c42
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h1
2 files changed, 21 insertions, 22 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index bb4d8d99f36d..217e618fd712 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -650,28 +650,10 @@ u64 mlx4_en_mac_to_u64(u8 *addr)
650 return mac; 650 return mac;
651} 651}
652 652
653static int mlx4_en_set_mac(struct net_device *dev, void *addr) 653static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
654{ 654{
655 struct mlx4_en_priv *priv = netdev_priv(dev);
656 struct mlx4_en_dev *mdev = priv->mdev;
657 struct sockaddr *saddr = addr;
658
659 if (!is_valid_ether_addr(saddr->sa_data))
660 return -EADDRNOTAVAIL;
661
662 memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
663 queue_work(mdev->workqueue, &priv->mac_task);
664 return 0;
665}
666
667static void mlx4_en_do_set_mac(struct work_struct *work)
668{
669 struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
670 mac_task);
671 struct mlx4_en_dev *mdev = priv->mdev;
672 int err = 0; 655 int err = 0;
673 656
674 mutex_lock(&mdev->state_lock);
675 if (priv->port_up) { 657 if (priv->port_up) {
676 /* Remove old MAC and insert the new one */ 658 /* Remove old MAC and insert the new one */
677 err = mlx4_en_replace_mac(priv, priv->base_qpn, 659 err = mlx4_en_replace_mac(priv, priv->base_qpn,
@@ -683,7 +665,26 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
683 } else 665 } else
684 en_dbg(HW, priv, "Port is down while registering mac, exiting...\n"); 666 en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
685 667
668 return err;
669}
670
671static int mlx4_en_set_mac(struct net_device *dev, void *addr)
672{
673 struct mlx4_en_priv *priv = netdev_priv(dev);
674 struct mlx4_en_dev *mdev = priv->mdev;
675 struct sockaddr *saddr = addr;
676 int err;
677
678 if (!is_valid_ether_addr(saddr->sa_data))
679 return -EADDRNOTAVAIL;
680
681 memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
682
683 mutex_lock(&mdev->state_lock);
684 err = mlx4_en_do_set_mac(priv);
686 mutex_unlock(&mdev->state_lock); 685 mutex_unlock(&mdev->state_lock);
686
687 return err;
687} 688}
688 689
689static void mlx4_en_clear_list(struct net_device *dev) 690static void mlx4_en_clear_list(struct net_device *dev)
@@ -1348,7 +1349,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
1348 queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); 1349 queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
1349 } 1350 }
1350 if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { 1351 if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
1351 queue_work(mdev->workqueue, &priv->mac_task); 1352 mlx4_en_do_set_mac(priv);
1352 mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; 1353 mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
1353 } 1354 }
1354 mutex_unlock(&mdev->state_lock); 1355 mutex_unlock(&mdev->state_lock);
@@ -2078,7 +2079,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
2078 priv->msg_enable = MLX4_EN_MSG_LEVEL; 2079 priv->msg_enable = MLX4_EN_MSG_LEVEL;
2079 spin_lock_init(&priv->stats_lock); 2080 spin_lock_init(&priv->stats_lock);
2080 INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); 2081 INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
2081 INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
2082 INIT_WORK(&priv->watchdog_task, mlx4_en_restart); 2082 INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
2083 INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); 2083 INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
2084 INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); 2084 INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index c313d7e943a9..f710b7ce0dcb 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -509,7 +509,6 @@ struct mlx4_en_priv {
509 struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; 509 struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
510 struct mlx4_qp drop_qp; 510 struct mlx4_qp drop_qp;
511 struct work_struct rx_mode_task; 511 struct work_struct rx_mode_task;
512 struct work_struct mac_task;
513 struct work_struct watchdog_task; 512 struct work_struct watchdog_task;
514 struct work_struct linkstate_task; 513 struct work_struct linkstate_task;
515 struct delayed_work stats_task; 514 struct delayed_work stats_task;