Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c07cb4b0 authored by Yan Burman's avatar Yan Burman Committed by David S. Miller
Browse files

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: default avatarYan Burman <yanb@mellanox.com>
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 90bbb74a
Loading
Loading
Loading
Loading
+54 −33
Original line number Diff line number Diff line
@@ -545,13 +545,10 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
	memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
	entry->reg_id = reg_id;

	err = radix_tree_insert(&priv->mac_tree, *qpn, entry);
	if (err)
		goto insert_err;
	return 0;
	hlist_add_head_rcu(&entry->hlist,
			   &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);

insert_err:
	kfree(entry);
	return 0;

alloc_err:
	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)
{
	struct mlx4_en_dev *mdev = priv->mdev;
	struct mlx4_dev *dev = mdev->dev;
	struct mlx4_mac_entry *entry;
	int qpn = priv->base_qpn;
	u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);

@@ -577,15 +573,26 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
	mlx4_unregister_mac(dev, priv->port, mac);

	if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
		entry = radix_tree_lookup(&priv->mac_tree, qpn);
		if (entry) {
		struct mlx4_mac_entry *entry;
		struct hlist_node *n, *tmp;
		struct hlist_head *bucket;
		unsigned int mac_hash;

		mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
		bucket = &priv->mac_hash[mac_hash];
		hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
			if (ether_addr_equal_64bits(entry->mac,
						    priv->dev->dev_addr)) {
				en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n",
			       priv->port, entry->mac, qpn);
				       priv->port, priv->dev->dev_addr, qpn);
				mlx4_en_uc_steer_release(priv, entry->mac,
							 qpn, entry->reg_id);
				mlx4_qp_release_range(dev, qpn, 1);
			radix_tree_delete(&priv->mac_tree, qpn);
			kfree(entry);

				hlist_del_rcu(&entry->hlist);
				kfree_rcu(entry, rcu);
				break;
			}
		}
	}
}
@@ -595,27 +602,39 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
{
	struct mlx4_en_dev *mdev = priv->mdev;
	struct mlx4_dev *dev = mdev->dev;
	struct mlx4_mac_entry *entry;
	int err = 0;
	u64 new_mac_u64 = mlx4_en_mac_to_u64(new_mac);

	if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
		u64 prev_mac_u64;
		struct hlist_head *bucket;
		unsigned int mac_hash;
		struct mlx4_mac_entry *entry;
		struct hlist_node *n, *tmp;
		u64 prev_mac_u64 = mlx4_en_mac_to_u64(prev_mac);

		entry = radix_tree_lookup(&priv->mac_tree, qpn);
		if (!entry)
			return -EINVAL;
		prev_mac_u64 = mlx4_en_mac_to_u64(entry->mac);
		bucket = &priv->mac_hash[prev_mac[MLX4_EN_MAC_HASH_IDX]];
		hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
			if (ether_addr_equal_64bits(entry->mac, prev_mac)) {
				mlx4_en_uc_steer_release(priv, entry->mac,
							 qpn, entry->reg_id);
		mlx4_unregister_mac(dev, priv->port, prev_mac_u64);
				mlx4_unregister_mac(dev, priv->port,
						    prev_mac_u64);
				hlist_del_rcu(&entry->hlist);
				synchronize_rcu();
				memcpy(entry->mac, new_mac, ETH_ALEN);
				entry->reg_id = 0;
				mac_hash = new_mac[MLX4_EN_MAC_HASH_IDX];
				hlist_add_head_rcu(&entry->hlist,
						   &priv->mac_hash[mac_hash]);
				mlx4_register_mac(dev, priv->port, new_mac_u64);
				err = mlx4_en_uc_steer_add(priv, new_mac,
					   &qpn, &entry->reg_id);
							   &qpn,
							   &entry->reg_id);
				return err;
			}
		}
		return -EINVAL;
	}

	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,
{
	struct net_device *dev;
	struct mlx4_en_priv *priv;
	int i;
	int err;

	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,
		dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
#endif

	INIT_RADIX_TREE(&priv->mac_tree, GFP_KERNEL);
	for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
		INIT_HLIST_HEAD(&priv->mac_hash[i]);

	/* Query for default mac and max mtu */
	priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
+19 −4
Original line number Diff line number Diff line
@@ -615,11 +615,26 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
			ethh = (struct ethhdr *)(page_address(frags[0].page) +
						 frags[0].offset);

			if (is_multicast_ether_addr(ethh->h_dest)) {
				struct mlx4_mac_entry *entry;
				struct hlist_node *n;
				struct hlist_head *bucket;
				unsigned int mac_hash;

				/* Drop the packet, since HW loopback-ed it */
			if (ether_addr_equal_64bits(dev->dev_addr,
						    ethh->h_source))
				mac_hash = ethh->h_source[MLX4_EN_MAC_HASH_IDX];
				bucket = &priv->mac_hash[mac_hash];
				rcu_read_lock();
				hlist_for_each_entry_rcu(entry, n, bucket, hlist) {
					if (ether_addr_equal_64bits(entry->mac,
								    ethh->h_source)) {
						rcu_read_unlock();
						goto next;
					}
				}
				rcu_read_unlock();
			}
		}

		/*
		 * Packet is OK - process it.
+6 −1
Original line number Diff line number Diff line
@@ -442,6 +442,9 @@ enum {
	MLX4_EN_FLAG_RX_FILTER_NEEDED	= (1 << 3)
};

#define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE)
#define MLX4_EN_MAC_HASH_IDX 5

struct mlx4_en_priv {
	struct mlx4_en_dev *mdev;
	struct mlx4_en_port_profile *prof;
@@ -521,7 +524,7 @@ struct mlx4_en_priv {
	bool wol;
	struct device *ddev;
	int base_tx_qpn;
	struct radix_tree_root mac_tree;
	struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE];

#ifdef CONFIG_MLX4_EN_DCB
	struct ieee_ets ets;
@@ -542,8 +545,10 @@ enum mlx4_en_wol {
};

struct mlx4_mac_entry {
	struct hlist_node hlist;
	unsigned char mac[ETH_ALEN + 2];
	u64 reg_id;
	struct rcu_head rcu;
};

#define MLX4_EN_WOL_DO_MODIFY (1ULL << 63)