Commit ba062d52 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by David S. Miller

net/mlx4_core: Add XRC domains and counters to resource tracker

Add missing resource tracking for XRC domains and complete the tracking for HCA
network flow counters.
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 b8924951
...@@ -1306,7 +1306,7 @@ static void mlx4_cleanup_counters_table(struct mlx4_dev *dev) ...@@ -1306,7 +1306,7 @@ static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap); mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
} }
int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx) int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
...@@ -1319,13 +1319,44 @@ int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx) ...@@ -1319,13 +1319,44 @@ int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
return 0; return 0;
} }
int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
{
u64 out_param;
int err;
if (mlx4_is_mfunc(dev)) {
err = mlx4_cmd_imm(dev, 0, &out_param, RES_COUNTER,
RES_OP_RESERVE, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (!err)
*idx = get_param_l(&out_param);
return err;
}
return __mlx4_counter_alloc(dev, idx);
}
EXPORT_SYMBOL_GPL(mlx4_counter_alloc); EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
void mlx4_counter_free(struct mlx4_dev *dev, u32 idx) void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
{ {
mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx); mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
return; return;
} }
void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
{
u64 in_param;
if (mlx4_is_mfunc(dev)) {
set_param_l(&in_param, idx);
mlx4_cmd(dev, in_param, RES_COUNTER, RES_OP_RESERVE,
MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
return;
}
__mlx4_counter_free(dev, idx);
}
EXPORT_SYMBOL_GPL(mlx4_counter_free); EXPORT_SYMBOL_GPL(mlx4_counter_free);
static int mlx4_setup_hca(struct mlx4_dev *dev) static int mlx4_setup_hca(struct mlx4_dev *dev)
......
...@@ -876,6 +876,10 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); ...@@ -876,6 +876,10 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac); int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int start_index, int npages, u64 *page_list); int start_index, int npages, u64 *page_list);
int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
void mlx4_start_catas_poll(struct mlx4_dev *dev); void mlx4_start_catas_poll(struct mlx4_dev *dev);
void mlx4_stop_catas_poll(struct mlx4_dev *dev); void mlx4_stop_catas_poll(struct mlx4_dev *dev);
......
...@@ -63,7 +63,7 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) ...@@ -63,7 +63,7 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
} }
EXPORT_SYMBOL_GPL(mlx4_pd_free); EXPORT_SYMBOL_GPL(mlx4_pd_free);
int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn) int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
...@@ -73,12 +73,47 @@ int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn) ...@@ -73,12 +73,47 @@ int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
return 0; return 0;
} }
int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
{
u64 out_param;
int err;
if (mlx4_is_mfunc(dev)) {
err = mlx4_cmd_imm(dev, 0, &out_param,
RES_XRCD, RES_OP_RESERVE,
MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (err)
return err;
*xrcdn = get_param_l(&out_param);
return 0;
}
return __mlx4_xrcd_alloc(dev, xrcdn);
}
EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc); EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
{ {
mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn); mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
} }
void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
{
u64 in_param;
int err;
if (mlx4_is_mfunc(dev)) {
set_param_l(&in_param, xrcdn);
err = mlx4_cmd(dev, in_param, RES_XRCD,
RES_OP_RESERVE, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (err)
mlx4_warn(dev, "Failed to release xrcdn %d\n", xrcdn);
} else
__mlx4_xrcd_free(dev, xrcdn);
}
EXPORT_SYMBOL_GPL(mlx4_xrcd_free); EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
int mlx4_init_pd_table(struct mlx4_dev *dev) int mlx4_init_pd_table(struct mlx4_dev *dev)
......
...@@ -179,6 +179,16 @@ struct res_counter { ...@@ -179,6 +179,16 @@ struct res_counter {
int port; int port;
}; };
enum res_xrcdn_states {
RES_XRCD_BUSY = RES_ANY_BUSY,
RES_XRCD_ALLOCATED,
};
struct res_xrcdn {
struct res_common com;
int port;
};
/* For Debug uses */ /* For Debug uses */
static const char *ResourceType(enum mlx4_resource rt) static const char *ResourceType(enum mlx4_resource rt)
{ {
...@@ -191,6 +201,7 @@ static const char *ResourceType(enum mlx4_resource rt) ...@@ -191,6 +201,7 @@ static const char *ResourceType(enum mlx4_resource rt)
case RES_MAC: return "RES_MAC"; case RES_MAC: return "RES_MAC";
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_XRCD: return "RES_XRCD";
default: return "Unknown resource type !!!"; default: return "Unknown resource type !!!";
}; };
} }
...@@ -448,6 +459,20 @@ static struct res_common *alloc_counter_tr(int id) ...@@ -448,6 +459,20 @@ static struct res_common *alloc_counter_tr(int id)
return &ret->com; return &ret->com;
} }
static struct res_common *alloc_xrcdn_tr(int id)
{
struct res_xrcdn *ret;
ret = kzalloc(sizeof *ret, GFP_KERNEL);
if (!ret)
return NULL;
ret->com.res_id = id;
ret->com.state = RES_XRCD_ALLOCATED;
return &ret->com;
}
static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave, static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave,
int extra) int extra)
{ {
...@@ -478,7 +503,9 @@ static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave, ...@@ -478,7 +503,9 @@ static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave,
case RES_COUNTER: case RES_COUNTER:
ret = alloc_counter_tr(id); ret = alloc_counter_tr(id);
break; break;
case RES_XRCD:
ret = alloc_xrcdn_tr(id);
break;
default: default:
return NULL; return NULL;
} }
...@@ -601,6 +628,16 @@ static int remove_counter_ok(struct res_counter *res) ...@@ -601,6 +628,16 @@ static int remove_counter_ok(struct res_counter *res)
return 0; return 0;
} }
static int remove_xrcdn_ok(struct res_xrcdn *res)
{
if (res->com.state == RES_XRCD_BUSY)
return -EBUSY;
else if (res->com.state != RES_XRCD_ALLOCATED)
return -EPERM;
return 0;
}
static int remove_cq_ok(struct res_cq *res) static int remove_cq_ok(struct res_cq *res)
{ {
if (res->com.state == RES_CQ_BUSY) if (res->com.state == RES_CQ_BUSY)
...@@ -640,6 +677,8 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra) ...@@ -640,6 +677,8 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
return remove_eq_ok((struct res_eq *)res); return remove_eq_ok((struct res_eq *)res);
case RES_COUNTER: case RES_COUNTER:
return remove_counter_ok((struct res_counter *)res); return remove_counter_ok((struct res_counter *)res);
case RES_XRCD:
return remove_xrcdn_ok((struct res_xrcdn *)res);
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1246,6 +1285,50 @@ static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1246,6 +1285,50 @@ static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
return 0; return 0;
} }
static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param)
{
u32 index;
int err;
if (op != RES_OP_RESERVE)
return -EINVAL;
err = __mlx4_counter_alloc(dev, &index);
if (err)
return err;
err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0);
if (err)
__mlx4_counter_free(dev, index);
else
set_param_l(out_param, index);
return err;
}
static int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param)
{
u32 xrcdn;
int err;
if (op != RES_OP_RESERVE)
return -EINVAL;
err = __mlx4_xrcd_alloc(dev, &xrcdn);
if (err)
return err;
err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
if (err)
__mlx4_xrcd_free(dev, xrcdn);
else
set_param_l(out_param, xrcdn);
return err;
}
int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *inbox,
...@@ -1291,6 +1374,16 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1291,6 +1374,16 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param);
break; break;
case RES_COUNTER:
err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param);
break;
case RES_XRCD:
err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param);
break;
default: default:
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -1473,6 +1566,44 @@ static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1473,6 +1566,44 @@ static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
return 0; return 0;
} }
static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param)
{
int index;
int err;
if (op != RES_OP_RESERVE)
return -EINVAL;
index = get_param_l(&in_param);
err = rem_res_range(dev, slave, index, 1, RES_COUNTER, 0);
if (err)
return err;
__mlx4_counter_free(dev, index);
return err;
}
static int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param)
{
int xrcdn;
int err;
if (op != RES_OP_RESERVE)
return -EINVAL;
xrcdn = get_param_l(&in_param);
err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
if (err)
return err;
__mlx4_xrcd_free(dev, xrcdn);
return err;
}
int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *inbox,
...@@ -1518,6 +1649,15 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1518,6 +1649,15 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param);
break; break;
case RES_COUNTER:
err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param);
break;
case RES_XRCD:
err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param);
default: default:
break; break;
} }
...@@ -3032,6 +3172,64 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave) ...@@ -3032,6 +3172,64 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
spin_unlock_irq(mlx4_tlock(dev)); spin_unlock_irq(mlx4_tlock(dev));
} }
static void rem_slave_counters(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 *counter_list =
&tracker->slave_list[slave].res_list[RES_COUNTER];
struct res_counter *counter;
struct res_counter *tmp;
int err;
int index;
err = move_all_busy(dev, slave, RES_COUNTER);
if (err)
mlx4_warn(dev, "rem_slave_counters: Could not move all counters to "
"busy for slave %d\n", slave);
spin_lock_irq(mlx4_tlock(dev));
list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
if (counter->com.owner == slave) {
index = counter->com.res_id;
radix_tree_delete(&tracker->res_tree[RES_COUNTER], index);
list_del(&counter->com.list);
kfree(counter);
__mlx4_counter_free(dev, index);
}
}
spin_unlock_irq(mlx4_tlock(dev));
}
static void rem_slave_xrcdns(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 *xrcdn_list =
&tracker->slave_list[slave].res_list[RES_XRCD];
struct res_xrcdn *xrcd;
struct res_xrcdn *tmp;
int err;
int xrcdn;
err = move_all_busy(dev, slave, RES_XRCD);
if (err)
mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns to "
"busy for slave %d\n", slave);
spin_lock_irq(mlx4_tlock(dev));
list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
if (xrcd->com.owner == slave) {
xrcdn = xrcd->com.res_id;
radix_tree_delete(&tracker->res_tree[RES_XRCD], xrcdn);
list_del(&xrcd->com.list);
kfree(xrcd);
__mlx4_xrcd_free(dev, xrcdn);
}
}
spin_unlock_irq(mlx4_tlock(dev));
}
void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) 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);
...@@ -3045,5 +3243,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) ...@@ -3045,5 +3243,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
rem_slave_mrs(dev, slave); rem_slave_mrs(dev, slave);
rem_slave_eqs(dev, slave); rem_slave_eqs(dev, slave);
rem_slave_mtts(dev, slave); rem_slave_mtts(dev, slave);
rem_slave_counters(dev, slave);
rem_slave_xrcdns(dev, slave);
mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment