Skip to content

Commit bfa8ab4

Browse files
Yan Burmandavem330
authored andcommitted
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 c07cb4b "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>
1 parent e7dbeba commit bfa8ab4

2 files changed

Lines changed: 21 additions & 22 deletions

File tree

drivers/net/ethernet/mellanox/mlx4/en_netdev.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -650,28 +650,10 @@ u64 mlx4_en_mac_to_u64(u8 *addr)
650650
return mac;
651651
}
652652

653-
static int mlx4_en_set_mac(struct net_device *dev, void *addr)
653+
static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
654654
{
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-
667-
static 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;
672655
int err = 0;
673656

674-
mutex_lock(&mdev->state_lock);
675657
if (priv->port_up) {
676658
/* Remove old MAC and insert the new one */
677659
err = mlx4_en_replace_mac(priv, priv->base_qpn,
@@ -683,7 +665,26 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
683665
} else
684666
en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
685667

668+
return err;
669+
}
670+
671+
static 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);
686685
mutex_unlock(&mdev->state_lock);
686+
687+
return err;
687688
}
688689

689690
static void mlx4_en_clear_list(struct net_device *dev)
@@ -1348,7 +1349,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
13481349
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
13491350
}
13501351
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);
13521353
mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
13531354
}
13541355
mutex_unlock(&mdev->state_lock);
@@ -2078,7 +2079,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
20782079
priv->msg_enable = MLX4_EN_MSG_LEVEL;
20792080
spin_lock_init(&priv->stats_lock);
20802081
INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
2081-
INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
20822082
INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
20832083
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
20842084
INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);

drivers/net/ethernet/mellanox/mlx4/mlx4_en.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,6 @@ struct mlx4_en_priv {
509509
struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
510510
struct mlx4_qp drop_qp;
511511
struct work_struct rx_mode_task;
512-
struct work_struct mac_task;
513512
struct work_struct watchdog_task;
514513
struct work_struct linkstate_task;
515514
struct delayed_work stats_task;

0 commit comments

Comments
 (0)