aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYan Burman <yanb@mellanox.com>2013-02-06 21:25:25 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-07 23:26:13 -0500
commitc07cb4b0ab78f279ea94c3b4661cad86eb02a5d9 (patch)
tree7c2eda4433a461a036410586a3ca31d27d46fb6a /drivers
parent90bbb74af68b3255bc298731f8b60d5668877306 (diff)
net/mlx4_en: Manage hash of MAC addresses per port
As a preparation step for supporting multiple unicast addresses, store MAC addresses in hash table. Remove the radix tree for MAC addresses per QP, as it's not in use. Signed-off-by: Yan Burman <yanb@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c87
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c23
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h7
3 files changed, 79 insertions, 38 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];
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 2e7f5bb94e1f..91bb8e157253 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -615,10 +615,25 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
615 ethh = (struct ethhdr *)(page_address(frags[0].page) + 615 ethh = (struct ethhdr *)(page_address(frags[0].page) +
616 frags[0].offset); 616 frags[0].offset);
617 617
618 /* Drop the packet, since HW loopback-ed it */ 618 if (is_multicast_ether_addr(ethh->h_dest)) {
619 if (ether_addr_equal_64bits(dev->dev_addr, 619 struct mlx4_mac_entry *entry;
620 ethh->h_source)) 620 struct hlist_node *n;
621 goto next; 621 struct hlist_head *bucket;
622 unsigned int mac_hash;
623
624 /* Drop the packet, since HW loopback-ed it */
625 mac_hash = ethh->h_source[MLX4_EN_MAC_HASH_IDX];
626 bucket = &priv->mac_hash[mac_hash];
627 rcu_read_lock();
628 hlist_for_each_entry_rcu(entry, n, bucket, hlist) {
629 if (ether_addr_equal_64bits(entry->mac,
630 ethh->h_source)) {
631 rcu_read_unlock();
632 goto next;
633 }
634 }
635 rcu_read_unlock();
636 }
622 } 637 }
623 638
624 /* 639 /*
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 47c9876a2449..0ff99e0b2ea3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -442,6 +442,9 @@ enum {
442 MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3) 442 MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3)
443}; 443};
444 444
445#define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE)
446#define MLX4_EN_MAC_HASH_IDX 5
447
445struct mlx4_en_priv { 448struct mlx4_en_priv {
446 struct mlx4_en_dev *mdev; 449 struct mlx4_en_dev *mdev;
447 struct mlx4_en_port_profile *prof; 450 struct mlx4_en_port_profile *prof;
@@ -521,7 +524,7 @@ struct mlx4_en_priv {
521 bool wol; 524 bool wol;
522 struct device *ddev; 525 struct device *ddev;
523 int base_tx_qpn; 526 int base_tx_qpn;
524 struct radix_tree_root mac_tree; 527 struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE];
525 528
526#ifdef CONFIG_MLX4_EN_DCB 529#ifdef CONFIG_MLX4_EN_DCB
527 struct ieee_ets ets; 530 struct ieee_ets ets;
@@ -542,8 +545,10 @@ enum mlx4_en_wol {
542}; 545};
543 546
544struct mlx4_mac_entry { 547struct mlx4_mac_entry {
548 struct hlist_node hlist;
545 unsigned char mac[ETH_ALEN + 2]; 549 unsigned char mac[ETH_ALEN + 2];
546 u64 reg_id; 550 u64 reg_id;
551 struct rcu_head rcu;
547}; 552};
548 553
549#define MLX4_EN_WOL_DO_MODIFY (1ULL << 63) 554#define MLX4_EN_WOL_DO_MODIFY (1ULL << 63)