aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/en_netdev.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 72a3fe50d429..8eb24ee598e2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -545,13 +545,10 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
545 memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac)); 545 memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
546 entry->reg_id = reg_id; 546 entry->reg_id = reg_id;
547 547
548 err = radix_tree_insert(&priv->mac_tree, *qpn, entry); 548 hlist_add_head_rcu(&entry->hlist,
549 if (err) 549 &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
550 goto insert_err;
551 return 0;
552 550
553insert_err: 551 return 0;
554 kfree(entry);
555 552
556alloc_err: 553alloc_err:
557 mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id); 554 mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id);
@@ -568,7 +565,6 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
568{ 565{
569 struct mlx4_en_dev *mdev = priv->mdev; 566 struct mlx4_en_dev *mdev = priv->mdev;
570 struct mlx4_dev *dev = mdev->dev; 567 struct mlx4_dev *dev = mdev->dev;
571 struct mlx4_mac_entry *entry;
572 int qpn = priv->base_qpn; 568 int qpn = priv->base_qpn;
573 u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr); 569 u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
574 570
@@ -577,15 +573,26 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
577 mlx4_unregister_mac(dev, priv->port, mac); 573 mlx4_unregister_mac(dev, priv->port, mac);
578 574
579 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) { 575 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
580 entry = radix_tree_lookup(&priv->mac_tree, qpn); 576 struct mlx4_mac_entry *entry;
581 if (entry) { 577 struct hlist_node *n, *tmp;
582 en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n", 578 struct hlist_head *bucket;
583 priv->port, entry->mac, qpn); 579 unsigned int mac_hash;
584 mlx4_en_uc_steer_release(priv, entry->mac, 580
585 qpn, entry->reg_id); 581 mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
586 mlx4_qp_release_range(dev, qpn, 1); 582 bucket = &priv->mac_hash[mac_hash];
587 radix_tree_delete(&priv->mac_tree, qpn); 583 hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
588 kfree(entry); 584 if (ether_addr_equal_64bits(entry->mac,
585 priv->dev->dev_addr)) {
586 en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n",
587 priv->port, priv->dev->dev_addr, qpn);
588 mlx4_en_uc_steer_release(priv, entry->mac,
589 qpn, entry->reg_id);
590 mlx4_qp_release_range(dev, qpn, 1);
591
592 hlist_del_rcu(&entry->hlist);
593 kfree_rcu(entry, rcu);
594 break;
595 }
589 } 596 }
590 } 597 }
591} 598}
@@ -595,26 +602,38 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
595{ 602{
596 struct mlx4_en_dev *mdev = priv->mdev; 603 struct mlx4_en_dev *mdev = priv->mdev;
597 struct mlx4_dev *dev = mdev->dev; 604 struct mlx4_dev *dev = mdev->dev;
598 struct mlx4_mac_entry *entry;
599 int err = 0; 605 int err = 0;
600 u64 new_mac_u64 = mlx4_en_mac_to_u64(new_mac); 606 u64 new_mac_u64 = mlx4_en_mac_to_u64(new_mac);
601 607
602 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) { 608 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
603 u64 prev_mac_u64; 609 struct hlist_head *bucket;
604 610 unsigned int mac_hash;
605 entry = radix_tree_lookup(&priv->mac_tree, qpn); 611 struct mlx4_mac_entry *entry;
606 if (!entry) 612 struct hlist_node *n, *tmp;
607 return -EINVAL; 613 u64 prev_mac_u64 = mlx4_en_mac_to_u64(prev_mac);
608 prev_mac_u64 = mlx4_en_mac_to_u64(entry->mac); 614
609 mlx4_en_uc_steer_release(priv, entry->mac, 615 bucket = &priv->mac_hash[prev_mac[MLX4_EN_MAC_HASH_IDX]];
610 qpn, entry->reg_id); 616 hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
611 mlx4_unregister_mac(dev, priv->port, prev_mac_u64); 617 if (ether_addr_equal_64bits(entry->mac, prev_mac)) {
612 memcpy(entry->mac, new_mac, ETH_ALEN); 618 mlx4_en_uc_steer_release(priv, entry->mac,
613 entry->reg_id = 0; 619 qpn, entry->reg_id);
614 mlx4_register_mac(dev, priv->port, new_mac_u64); 620 mlx4_unregister_mac(dev, priv->port,
615 err = mlx4_en_uc_steer_add(priv, new_mac, 621 prev_mac_u64);
616 &qpn, &entry->reg_id); 622 hlist_del_rcu(&entry->hlist);
617 return err; 623 synchronize_rcu();
624 memcpy(entry->mac, new_mac, ETH_ALEN);
625 entry->reg_id = 0;
626 mac_hash = new_mac[MLX4_EN_MAC_HASH_IDX];
627 hlist_add_head_rcu(&entry->hlist,
628 &priv->mac_hash[mac_hash]);
629 mlx4_register_mac(dev, priv->port, new_mac_u64);
630 err = mlx4_en_uc_steer_add(priv, new_mac,
631 &qpn,
632 &entry->reg_id);
633 return err;
634 }
635 }
636 return -EINVAL;
618 } 637 }
619 638
620 return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64); 639 return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64);
@@ -1816,6 +1835,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
1816{ 1835{
1817 struct net_device *dev; 1836 struct net_device *dev;
1818 struct mlx4_en_priv *priv; 1837 struct mlx4_en_priv *priv;
1838 int i;
1819 int err; 1839 int err;
1820 1840
1821 dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv), 1841 dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
@@ -1874,7 +1894,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
1874 dev->dcbnl_ops = &mlx4_en_dcbnl_ops; 1894 dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
1875#endif 1895#endif
1876 1896
1877 INIT_RADIX_TREE(&priv->mac_tree, GFP_KERNEL); 1897 for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
1898 INIT_HLIST_HEAD(&priv->mac_hash[i]);
1878 1899
1879 /* Query for default mac and max mtu */ 1900 /* Query for default mac and max mtu */
1880 priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port]; 1901 priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];