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

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

net/mlx4_en: Cleanup MAC resources on module unload or port stop



Make sure we cleanup all MAC related resources (entries in the port MAC
table and steering rules) when stopping a port or when the driver is unloaded.

The leak was introduced by commit 07cb4b0a "net/mlx4_en: Manage hash of MAC
addresses per port".

Signed-off-by: default avatarYan Burman <yanb@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bfa8ab47
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -565,34 +565,38 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
	struct mlx4_en_dev *mdev = priv->mdev;
	struct mlx4_dev *dev = mdev->dev;
	int qpn = priv->base_qpn;
	u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
	u64 mac;

	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
		mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
		en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
		       priv->dev->dev_addr);
		mlx4_unregister_mac(dev, priv->port, mac);

	if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
	} else {
		struct mlx4_mac_entry *entry;
		struct hlist_node *tmp;
		struct hlist_head *bucket;
		unsigned int mac_hash;
		unsigned int i;

		mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
		bucket = &priv->mac_hash[mac_hash];
		for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
			bucket = &priv->mac_hash[i];
			hlist_for_each_entry_safe(entry, 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, priv->dev->dev_addr, qpn);
				mac = mlx4_en_mac_to_u64(entry->mac);
				en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
				       entry->mac);
				mlx4_en_uc_steer_release(priv, entry->mac,
							 qpn, entry->reg_id);
				mlx4_qp_release_range(dev, qpn, 1);

				mlx4_unregister_mac(dev, priv->port, mac);
				hlist_del_rcu(&entry->hlist);
				kfree_rcu(entry, rcu);
				break;
			}
		}

		en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
		       priv->port, qpn);
		mlx4_qp_release_range(dev, qpn, 1);
		priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
	}
}