net/mlx4_core: Resource tracker for reg/unreg vlans
Add resource tracker support for reg/unreg vlans calls done by VFs. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
2009d0059c
commit
4874080dee
@@ -55,6 +55,14 @@ struct mac_res {
|
|||||||
u8 port;
|
u8 port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vlan_res {
|
||||||
|
struct list_head list;
|
||||||
|
u16 vlan;
|
||||||
|
int ref_count;
|
||||||
|
int vlan_index;
|
||||||
|
u8 port;
|
||||||
|
};
|
||||||
|
|
||||||
struct res_common {
|
struct res_common {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
@@ -266,6 +274,7 @@ static const char *ResourceType(enum mlx4_resource rt)
|
|||||||
case RES_MPT: return "RES_MPT";
|
case RES_MPT: return "RES_MPT";
|
||||||
case RES_MTT: return "RES_MTT";
|
case RES_MTT: return "RES_MTT";
|
||||||
case RES_MAC: return "RES_MAC";
|
case RES_MAC: return "RES_MAC";
|
||||||
|
case RES_VLAN: return "RES_VLAN";
|
||||||
case RES_EQ: return "RES_EQ";
|
case RES_EQ: return "RES_EQ";
|
||||||
case RES_COUNTER: return "RES_COUNTER";
|
case RES_COUNTER: return "RES_COUNTER";
|
||||||
case RES_FS_RULE: return "RES_FS_RULE";
|
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)
|
int mlx4_init_resource_tracker(struct mlx4_dev *dev)
|
||||||
{
|
{
|
||||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
@@ -309,11 +319,18 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (priv->mfunc.master.res_tracker.slave_list) {
|
if (priv->mfunc.master.res_tracker.slave_list) {
|
||||||
if (type != RES_TR_FREE_STRUCTS_ONLY)
|
if (type != RES_TR_FREE_STRUCTS_ONLY) {
|
||||||
for (i = 0 ; i < dev->num_slaves; i++)
|
for (i = 0; i < dev->num_slaves; i++) {
|
||||||
if (type == RES_TR_FREE_ALL ||
|
if (type == RES_TR_FREE_ALL ||
|
||||||
dev->caps.function != i)
|
dev->caps.function != i)
|
||||||
mlx4_delete_all_resources_for_slave(dev, 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) {
|
if (type != RES_TR_FREE_SLAVES_ONLY) {
|
||||||
kfree(priv->mfunc.master.res_tracker.slave_list);
|
kfree(priv->mfunc.master.res_tracker.slave_list);
|
||||||
@@ -1469,12 +1486,96 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,
|
||||||
u64 in_param, u64 *out_param, int port)
|
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;
|
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)
|
||||||
|
{
|
||||||
|
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,
|
static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||||
u64 in_param, u64 *out_param)
|
u64 in_param, u64 *out_param)
|
||||||
{
|
{
|
||||||
@@ -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,
|
static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
|
||||||
u64 in_param, u64 *out_param, int port)
|
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,
|
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);
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
|
||||||
mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
|
mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
|
||||||
/*VLAN*/
|
rem_slave_vlans(dev, slave);
|
||||||
rem_slave_macs(dev, slave);
|
rem_slave_macs(dev, slave);
|
||||||
rem_slave_fs_rule(dev, slave);
|
rem_slave_fs_rule(dev, slave);
|
||||||
rem_slave_qps(dev, slave);
|
rem_slave_qps(dev, slave);
|
||||||
|
Reference in New Issue
Block a user