aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/resource_tracker.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c45
1 files changed, 35 insertions, 10 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 2995687f1aee..1391b52f443a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -99,6 +99,7 @@ struct res_qp {
99 struct list_head mcg_list; 99 struct list_head mcg_list;
100 spinlock_t mcg_spl; 100 spinlock_t mcg_spl;
101 int local_qpn; 101 int local_qpn;
102 atomic_t ref_count;
102}; 103};
103 104
104enum res_mtt_states { 105enum res_mtt_states {
@@ -197,6 +198,7 @@ enum res_fs_rule_states {
197 198
198struct res_fs_rule { 199struct res_fs_rule {
199 struct res_common com; 200 struct res_common com;
201 int qpn;
200}; 202};
201 203
202static void *res_tracker_lookup(struct rb_root *root, u64 res_id) 204static void *res_tracker_lookup(struct rb_root *root, u64 res_id)
@@ -355,7 +357,7 @@ static int mpt_mask(struct mlx4_dev *dev)
355 return dev->caps.num_mpts - 1; 357 return dev->caps.num_mpts - 1;
356} 358}
357 359
358static void *find_res(struct mlx4_dev *dev, int res_id, 360static void *find_res(struct mlx4_dev *dev, u64 res_id,
359 enum mlx4_resource type) 361 enum mlx4_resource type)
360{ 362{
361 struct mlx4_priv *priv = mlx4_priv(dev); 363 struct mlx4_priv *priv = mlx4_priv(dev);
@@ -447,6 +449,7 @@ static struct res_common *alloc_qp_tr(int id)
447 ret->local_qpn = id; 449 ret->local_qpn = id;
448 INIT_LIST_HEAD(&ret->mcg_list); 450 INIT_LIST_HEAD(&ret->mcg_list);
449 spin_lock_init(&ret->mcg_spl); 451 spin_lock_init(&ret->mcg_spl);
452 atomic_set(&ret->ref_count, 0);
450 453
451 return &ret->com; 454 return &ret->com;
452} 455}
@@ -554,7 +557,7 @@ static struct res_common *alloc_xrcdn_tr(int id)
554 return &ret->com; 557 return &ret->com;
555} 558}
556 559
557static struct res_common *alloc_fs_rule_tr(u64 id) 560static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
558{ 561{
559 struct res_fs_rule *ret; 562 struct res_fs_rule *ret;
560 563
@@ -564,7 +567,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id)
564 567
565 ret->com.res_id = id; 568 ret->com.res_id = id;
566 ret->com.state = RES_FS_RULE_ALLOCATED; 569 ret->com.state = RES_FS_RULE_ALLOCATED;
567 570 ret->qpn = qpn;
568 return &ret->com; 571 return &ret->com;
569} 572}
570 573
@@ -602,7 +605,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
602 ret = alloc_xrcdn_tr(id); 605 ret = alloc_xrcdn_tr(id);
603 break; 606 break;
604 case RES_FS_RULE: 607 case RES_FS_RULE:
605 ret = alloc_fs_rule_tr(id); 608 ret = alloc_fs_rule_tr(id, extra);
606 break; 609 break;
607 default: 610 default:
608 return NULL; 611 return NULL;
@@ -671,10 +674,14 @@ undo:
671 674
672static int remove_qp_ok(struct res_qp *res) 675static int remove_qp_ok(struct res_qp *res)
673{ 676{
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));
675 return -EBUSY; 681 return -EBUSY;
676 else if (res->com.state != RES_QP_RESERVED) 682 } else if (res->com.state != RES_QP_RESERVED) {
677 return -EPERM; 683 return -EPERM;
684 }
678 685
679 return 0; 686 return 0;
680} 687}
@@ -3124,6 +3131,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3124 struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; 3131 struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
3125 int err; 3132 int err;
3126 int qpn; 3133 int qpn;
3134 struct res_qp *rqp;
3127 struct mlx4_net_trans_rule_hw_ctrl *ctrl; 3135 struct mlx4_net_trans_rule_hw_ctrl *ctrl;
3128 struct _rule_hw *rule_header; 3136 struct _rule_hw *rule_header;
3129 int header_id; 3137 int header_id;
@@ -3134,7 +3142,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3134 3142
3135 ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; 3143 ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
3136 qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; 3144 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);
3138 if (err) { 3146 if (err) {
3139 pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); 3147 pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
3140 return err; 3148 return err;
@@ -3175,14 +3183,16 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
3175 if (err) 3183 if (err)
3176 goto err_put; 3184 goto err_put;
3177 3185
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);
3179 if (err) { 3187 if (err) {
3180 mlx4_err(dev, "Fail to add flow steering resources.\n "); 3188 mlx4_err(dev, "Fail to add flow steering resources.\n ");
3181 /* detach rule*/ 3189 /* detach rule*/
3182 mlx4_cmd(dev, vhcr->out_param, 0, 0, 3190 mlx4_cmd(dev, vhcr->out_param, 0, 0,
3183 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, 3191 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
3184 MLX4_CMD_NATIVE); 3192 MLX4_CMD_NATIVE);
3193 goto err_put;
3185 } 3194 }
3195 atomic_inc(&rqp->ref_count);
3186err_put: 3196err_put:
3187 put_res(dev, slave, qpn, RES_QP); 3197 put_res(dev, slave, qpn, RES_QP);
3188 return err; 3198 return err;
@@ -3195,20 +3205,35 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
3195 struct mlx4_cmd_info *cmd) 3205 struct mlx4_cmd_info *cmd)
3196{ 3206{
3197 int err; 3207 int err;
3208 struct res_qp *rqp;
3209 struct res_fs_rule *rrule;
3198 3210
3199 if (dev->caps.steering_mode != 3211 if (dev->caps.steering_mode !=
3200 MLX4_STEERING_MODE_DEVICE_MANAGED) 3212 MLX4_STEERING_MODE_DEVICE_MANAGED)
3201 return -EOPNOTSUPP; 3213 return -EOPNOTSUPP;
3202 3214
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
3203 err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); 3224 err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);
3204 if (err) { 3225 if (err) {
3205 mlx4_err(dev, "Fail to remove flow steering resources.\n "); 3226 mlx4_err(dev, "Fail to remove flow steering resources.\n ");
3206 return err; 3227 goto out;
3207 } 3228 }
3208 3229
3209 err = mlx4_cmd(dev, vhcr->in_param, 0, 0, 3230 err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
3210 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, 3231 MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
3211 MLX4_CMD_NATIVE); 3232 MLX4_CMD_NATIVE);
3233 if (!err)
3234 atomic_dec(&rqp->ref_count);
3235out:
3236 put_res(dev, slave, rrule->qpn, RES_QP);
3212 return err; 3237 return err;
3213} 3238}
3214 3239
@@ -3806,6 +3831,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
3806 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); 3831 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
3807 /*VLAN*/ 3832 /*VLAN*/
3808 rem_slave_macs(dev, slave); 3833 rem_slave_macs(dev, slave);
3834 rem_slave_fs_rule(dev, slave);
3809 rem_slave_qps(dev, slave); 3835 rem_slave_qps(dev, slave);
3810 rem_slave_srqs(dev, slave); 3836 rem_slave_srqs(dev, slave);
3811 rem_slave_cqs(dev, slave); 3837 rem_slave_cqs(dev, slave);
@@ -3814,6 +3840,5 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
3814 rem_slave_mtts(dev, slave); 3840 rem_slave_mtts(dev, slave);
3815 rem_slave_counters(dev, slave); 3841 rem_slave_counters(dev, slave);
3816 rem_slave_xrcdns(dev, slave); 3842 rem_slave_xrcdns(dev, slave);
3817 rem_slave_fs_rule(dev, slave);
3818 mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); 3843 mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
3819} 3844}