Skip to content

Commit 2c473ae

Browse files
hadarhenziondavem330
authored andcommitted
net/mlx4_core: Disallow releasing VF QPs which have steering rules
VF QPs must not be released when they have steering rules attached to them. For that end, introduce a reference count field to the QP object in the SRIOV resource tracker which is incremented/decremented when steering rules are attached/detached to it. QPs can be released by VF only when their ref count is zero. Signed-off-by: Hadar Hen Zion <[email protected]> Signed-off-by: Or Gerlitz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1e3f7b3 commit 2c473ae

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

drivers/net/ethernet/mellanox/mlx4/resource_tracker.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct res_qp {
9999
struct list_head mcg_list;
100100
spinlock_t mcg_spl;
101101
int local_qpn;
102+
atomic_t ref_count;
102103
};
103104

104105
enum res_mtt_states {
@@ -197,6 +198,7 @@ enum res_fs_rule_states {
197198

198199
struct res_fs_rule {
199200
struct res_common com;
201+
int qpn;
200202
};
201203

202204
static void *res_tracker_lookup(struct rb_root *root, u64 res_id)
@@ -447,6 +449,7 @@ static struct res_common *alloc_qp_tr(int id)
447449
ret->local_qpn = id;
448450
INIT_LIST_HEAD(&ret->mcg_list);
449451
spin_lock_init(&ret->mcg_spl);
452+
atomic_set(&ret->ref_count, 0);
450453

451454
return &ret->com;
452455
}
@@ -554,7 +557,7 @@ static struct res_common *alloc_xrcdn_tr(int id)
554557
return &ret->com;
555558
}
556559

557-
static struct res_common *alloc_fs_rule_tr(u64 id)
560+
static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
558561
{
559562
struct res_fs_rule *ret;
560563

@@ -564,7 +567,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id)
564567

565568
ret->com.res_id = id;
566569
ret->com.state = RES_FS_RULE_ALLOCATED;
567-
570+
ret->qpn = qpn;
568571
return &ret->com;
569572
}
570573

@@ -602,7 +605,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
602605
ret = alloc_xrcdn_tr(id);
603606
break;
604607
case RES_FS_RULE:
605-
ret = alloc_fs_rule_tr(id);
608+
ret = alloc_fs_rule_tr(id, extra);
606609
break;
607610
default:
608611
return NULL;
@@ -671,10 +674,14 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
671674

672675
static int remove_qp_ok(struct res_qp *res)
673676
{
674-
if (res->com.state == RES_QP_BUSY)
677+
if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||
678+
!list_empty(&res->mcg_list)) {
679+
pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",
680+
res->com.state, atomic_read(&res->ref_count));
675681
return -EBUSY;
676-
else if (res->com.state != RES_QP_RESERVED)
682+
} else if (res->com.state != RES_QP_RESERVED) {
677683
return -EPERM;
684+
}
678685

679686
return 0;
680687
}
@@ -3124,6 +3131,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
31243131
struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
31253132
int err;
31263133
int qpn;
3134+
struct res_qp *rqp;
31273135
struct mlx4_net_trans_rule_hw_ctrl *ctrl;
31283136
struct _rule_hw *rule_header;
31293137
int header_id;
@@ -3134,7 +3142,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
31343142

31353143
ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
31363144
qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
3137-
err = get_res(dev, slave, qpn, RES_QP, NULL);
3145+
err = get_res(dev, slave, qpn, RES_QP, &rqp);
31383146
if (err) {
31393147
pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
31403148
return err;
@@ -3175,14 +3183,16 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
31753183
if (err)
31763184
goto err_put;
31773185

3178-
err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0);
3186+
err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);
31793187
if (err) {
31803188
mlx4_err(dev, "Fail to add flow steering resources.\n ");
31813189
/* detach rule*/
31823190
mlx4_cmd(dev, vhcr->out_param, 0, 0,
31833191
MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
31843192
MLX4_CMD_NATIVE);
3193+
goto err_put;
31853194
}
3195+
atomic_inc(&rqp->ref_count);
31863196
err_put:
31873197
put_res(dev, slave, qpn, RES_QP);
31883198
return err;
@@ -3195,20 +3205,35 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
31953205
struct mlx4_cmd_info *cmd)
31963206
{
31973207
int err;
3208+
struct res_qp *rqp;
3209+
struct res_fs_rule *rrule;
31983210

31993211
if (dev->caps.steering_mode !=
32003212
MLX4_STEERING_MODE_DEVICE_MANAGED)
32013213
return -EOPNOTSUPP;
32023214

3215+
err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);
3216+
if (err)
3217+
return err;
3218+
/* Release the rule form busy state before removal */
3219+
put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
3220+
err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
3221+
if (err)
3222+
return err;
3223+
32033224
err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);
32043225
if (err) {
32053226
mlx4_err(dev, "Fail to remove flow steering resources.\n ");
3206-
return err;
3227+
goto out;
32073228
}
32083229

32093230
err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
32103231
MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
32113232
MLX4_CMD_NATIVE);
3233+
if (!err)
3234+
atomic_dec(&rqp->ref_count);
3235+
out:
3236+
put_res(dev, slave, rrule->qpn, RES_QP);
32123237
return err;
32133238
}
32143239

0 commit comments

Comments
 (0)