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

Commit 4874080d authored by Jack Morgenstein's avatar Jack Morgenstein Committed by David S. Miller
Browse files

net/mlx4_core: Resource tracker for reg/unreg vlans



Add resource tracker support for reg/unreg vlans calls done by VFs.

Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2009d005
Loading
Loading
Loading
Loading
+121 −6
Original line number Diff line number Diff line
@@ -55,6 +55,14 @@ struct mac_res {
	u8 port;
};

struct vlan_res {
	struct list_head list;
	u16 vlan;
	int ref_count;
	int vlan_index;
	u8 port;
};

struct res_common {
	struct list_head	list;
	struct rb_node		node;
@@ -266,6 +274,7 @@ static const char *ResourceType(enum mlx4_resource rt)
	case RES_MPT: return "RES_MPT";
	case RES_MTT: return "RES_MTT";
	case RES_MAC: return  "RES_MAC";
	case RES_VLAN: return  "RES_VLAN";
	case RES_EQ: return "RES_EQ";
	case RES_COUNTER: return "RES_COUNTER";
	case RES_FS_RULE: return "RES_FS_RULE";
@@ -274,6 +283,7 @@ static const char *ResourceType(enum mlx4_resource rt)
	};
}

static void rem_slave_vlans(struct mlx4_dev *dev, int slave);
int mlx4_init_resource_tracker(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -309,11 +319,18 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev,
	int i;

	if (priv->mfunc.master.res_tracker.slave_list) {
		if (type != RES_TR_FREE_STRUCTS_ONLY)
			for (i = 0 ; i < dev->num_slaves; i++)
		if (type != RES_TR_FREE_STRUCTS_ONLY) {
			for (i = 0; i < dev->num_slaves; i++) {
				if (type == RES_TR_FREE_ALL ||
				    dev->caps.function != i)
					mlx4_delete_all_resources_for_slave(dev, i);
			}
			/* free master's vlans */
			i = dev->caps.function;
			mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
			rem_slave_vlans(dev, i);
			mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
		}

		if (type != RES_TR_FREE_SLAVES_ONLY) {
			kfree(priv->mfunc.master.res_tracker.slave_list);
@@ -1469,10 +1486,94 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
	return err;
}

static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,
			     int port, int vlan_index)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
	struct list_head *vlan_list =
		&tracker->slave_list[slave].res_list[RES_VLAN];
	struct vlan_res *res, *tmp;

	list_for_each_entry_safe(res, tmp, vlan_list, list) {
		if (res->vlan == vlan && res->port == (u8) port) {
			/* vlan found. update ref count */
			++res->ref_count;
			return 0;
		}
	}

	res = kzalloc(sizeof(*res), GFP_KERNEL);
	if (!res)
		return -ENOMEM;
	res->vlan = vlan;
	res->port = (u8) port;
	res->vlan_index = vlan_index;
	res->ref_count = 1;
	list_add_tail(&res->list,
		      &tracker->slave_list[slave].res_list[RES_VLAN]);
	return 0;
}


static void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan,
				int port)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
	struct list_head *vlan_list =
		&tracker->slave_list[slave].res_list[RES_VLAN];
	struct vlan_res *res, *tmp;

	list_for_each_entry_safe(res, tmp, vlan_list, list) {
		if (res->vlan == vlan && res->port == (u8) port) {
			if (!--res->ref_count) {
				list_del(&res->list);
				kfree(res);
			}
			break;
		}
	}
}

static void rem_slave_vlans(struct mlx4_dev *dev, int slave)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
	struct list_head *vlan_list =
		&tracker->slave_list[slave].res_list[RES_VLAN];
	struct vlan_res *res, *tmp;
	int i;

	list_for_each_entry_safe(res, tmp, vlan_list, list) {
		list_del(&res->list);
		/* dereference the vlan the num times the slave referenced it */
		for (i = 0; i < res->ref_count; i++)
			__mlx4_unregister_vlan(dev, res->port, res->vlan);
		kfree(res);
	}
}

static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
			  u64 in_param, u64 *out_param, int port)
{
	return 0;
	int err;
	u16 vlan;
	int vlan_index;

	if (!port || op != RES_OP_RESERVE_AND_MAP)
		return -EINVAL;

	vlan = (u16) in_param;

	err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);
	if (!err) {
		set_param_l(out_param, (u32) vlan_index);
		err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index);
		if (err)
			__mlx4_unregister_vlan(dev, port, vlan);
	}
	return err;
}

static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
@@ -1755,7 +1856,21 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
			    u64 in_param, u64 *out_param, int port)
{
	return 0;
	int err = 0;

	switch (op) {
	case RES_OP_RESERVE_AND_MAP:
		if (!port)
			return -EINVAL;
		vlan_del_from_slave(dev, slave, in_param, port);
		__mlx4_unregister_vlan(dev, port, in_param);
		break;
	default:
		err = -EINVAL;
		break;
	}

	return err;
}

static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
@@ -3968,7 +4083,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
	struct mlx4_priv *priv = mlx4_priv(dev);

	mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
	/*VLAN*/
	rem_slave_vlans(dev, slave);
	rem_slave_macs(dev, slave);
	rem_slave_fs_rule(dev, slave);
	rem_slave_qps(dev, slave);