diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 132 |
2 files changed, 125 insertions, 8 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 0084967be19e..d2c436b10fbf 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -149,6 +149,7 @@ enum mlx4_resource { | |||
149 | RES_VLAN, | 149 | RES_VLAN, |
150 | RES_EQ, | 150 | RES_EQ, |
151 | RES_COUNTER, | 151 | RES_COUNTER, |
152 | RES_FS_RULE, | ||
152 | MLX4_NUM_OF_RESOURCE_TYPE | 153 | MLX4_NUM_OF_RESOURCE_TYPE |
153 | }; | 154 | }; |
154 | 155 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 5a6f3555d806..c3fa91986190 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -190,6 +190,15 @@ struct res_xrcdn { | |||
190 | int port; | 190 | int port; |
191 | }; | 191 | }; |
192 | 192 | ||
193 | enum res_fs_rule_states { | ||
194 | RES_FS_RULE_BUSY = RES_ANY_BUSY, | ||
195 | RES_FS_RULE_ALLOCATED, | ||
196 | }; | ||
197 | |||
198 | struct res_fs_rule { | ||
199 | struct res_common com; | ||
200 | }; | ||
201 | |||
193 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) | 202 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) |
194 | { | 203 | { |
195 | struct rb_node *node = root->rb_node; | 204 | struct rb_node *node = root->rb_node; |
@@ -245,6 +254,7 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
245 | case RES_MAC: return "RES_MAC"; | 254 | case RES_MAC: return "RES_MAC"; |
246 | case RES_EQ: return "RES_EQ"; | 255 | case RES_EQ: return "RES_EQ"; |
247 | case RES_COUNTER: return "RES_COUNTER"; | 256 | case RES_COUNTER: return "RES_COUNTER"; |
257 | case RES_FS_RULE: return "RES_FS_RULE"; | ||
248 | case RES_XRCD: return "RES_XRCD"; | 258 | case RES_XRCD: return "RES_XRCD"; |
249 | default: return "Unknown resource type !!!"; | 259 | default: return "Unknown resource type !!!"; |
250 | }; | 260 | }; |
@@ -516,6 +526,20 @@ static struct res_common *alloc_xrcdn_tr(int id) | |||
516 | return &ret->com; | 526 | return &ret->com; |
517 | } | 527 | } |
518 | 528 | ||
529 | static struct res_common *alloc_fs_rule_tr(u64 id) | ||
530 | { | ||
531 | struct res_fs_rule *ret; | ||
532 | |||
533 | ret = kzalloc(sizeof *ret, GFP_KERNEL); | ||
534 | if (!ret) | ||
535 | return NULL; | ||
536 | |||
537 | ret->com.res_id = id; | ||
538 | ret->com.state = RES_FS_RULE_ALLOCATED; | ||
539 | |||
540 | return &ret->com; | ||
541 | } | ||
542 | |||
519 | static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, | 543 | static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, |
520 | int extra) | 544 | int extra) |
521 | { | 545 | { |
@@ -549,6 +573,9 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, | |||
549 | case RES_XRCD: | 573 | case RES_XRCD: |
550 | ret = alloc_xrcdn_tr(id); | 574 | ret = alloc_xrcdn_tr(id); |
551 | break; | 575 | break; |
576 | case RES_FS_RULE: | ||
577 | ret = alloc_fs_rule_tr(id); | ||
578 | break; | ||
552 | default: | 579 | default: |
553 | return NULL; | 580 | return NULL; |
554 | } | 581 | } |
@@ -681,6 +708,16 @@ static int remove_xrcdn_ok(struct res_xrcdn *res) | |||
681 | return 0; | 708 | return 0; |
682 | } | 709 | } |
683 | 710 | ||
711 | static int remove_fs_rule_ok(struct res_fs_rule *res) | ||
712 | { | ||
713 | if (res->com.state == RES_FS_RULE_BUSY) | ||
714 | return -EBUSY; | ||
715 | else if (res->com.state != RES_FS_RULE_ALLOCATED) | ||
716 | return -EPERM; | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
684 | static int remove_cq_ok(struct res_cq *res) | 721 | static int remove_cq_ok(struct res_cq *res) |
685 | { | 722 | { |
686 | if (res->com.state == RES_CQ_BUSY) | 723 | if (res->com.state == RES_CQ_BUSY) |
@@ -722,6 +759,8 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra) | |||
722 | return remove_counter_ok((struct res_counter *)res); | 759 | return remove_counter_ok((struct res_counter *)res); |
723 | case RES_XRCD: | 760 | case RES_XRCD: |
724 | return remove_xrcdn_ok((struct res_xrcdn *)res); | 761 | return remove_xrcdn_ok((struct res_xrcdn *)res); |
762 | case RES_FS_RULE: | ||
763 | return remove_fs_rule_ok((struct res_fs_rule *)res); | ||
725 | default: | 764 | default: |
726 | return -EINVAL; | 765 | return -EINVAL; |
727 | } | 766 | } |
@@ -2744,14 +2783,28 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
2744 | struct mlx4_cmd_mailbox *outbox, | 2783 | struct mlx4_cmd_mailbox *outbox, |
2745 | struct mlx4_cmd_info *cmd) | 2784 | struct mlx4_cmd_info *cmd) |
2746 | { | 2785 | { |
2786 | int err; | ||
2787 | |||
2747 | if (dev->caps.steering_mode != | 2788 | if (dev->caps.steering_mode != |
2748 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 2789 | MLX4_STEERING_MODE_DEVICE_MANAGED) |
2749 | return -EOPNOTSUPP; | 2790 | return -EOPNOTSUPP; |
2750 | return mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, | 2791 | |
2751 | vhcr->in_modifier, 0, | 2792 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, |
2752 | MLX4_QP_FLOW_STEERING_ATTACH, | 2793 | vhcr->in_modifier, 0, |
2753 | MLX4_CMD_TIME_CLASS_A, | 2794 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, |
2754 | MLX4_CMD_NATIVE); | 2795 | MLX4_CMD_NATIVE); |
2796 | if (err) | ||
2797 | return err; | ||
2798 | |||
2799 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); | ||
2800 | if (err) { | ||
2801 | mlx4_err(dev, "Fail to add flow steering resources.\n "); | ||
2802 | /* detach rule*/ | ||
2803 | mlx4_cmd(dev, vhcr->out_param, 0, 0, | ||
2804 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | ||
2805 | MLX4_CMD_NATIVE); | ||
2806 | } | ||
2807 | return err; | ||
2755 | } | 2808 | } |
2756 | 2809 | ||
2757 | int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, | 2810 | int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, |
@@ -2760,12 +2813,22 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, | |||
2760 | struct mlx4_cmd_mailbox *outbox, | 2813 | struct mlx4_cmd_mailbox *outbox, |
2761 | struct mlx4_cmd_info *cmd) | 2814 | struct mlx4_cmd_info *cmd) |
2762 | { | 2815 | { |
2816 | int err; | ||
2817 | |||
2763 | if (dev->caps.steering_mode != | 2818 | if (dev->caps.steering_mode != |
2764 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 2819 | MLX4_STEERING_MODE_DEVICE_MANAGED) |
2765 | return -EOPNOTSUPP; | 2820 | return -EOPNOTSUPP; |
2766 | return mlx4_cmd(dev, vhcr->in_param, 0, 0, | 2821 | |
2767 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 2822 | err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); |
2768 | MLX4_CMD_NATIVE); | 2823 | if (err) { |
2824 | mlx4_err(dev, "Fail to remove flow steering resources.\n "); | ||
2825 | return err; | ||
2826 | } | ||
2827 | |||
2828 | err = mlx4_cmd(dev, vhcr->in_param, 0, 0, | ||
2829 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | ||
2830 | MLX4_CMD_NATIVE); | ||
2831 | return err; | ||
2769 | } | 2832 | } |
2770 | 2833 | ||
2771 | enum { | 2834 | enum { |
@@ -3177,6 +3240,58 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave) | |||
3177 | spin_unlock_irq(mlx4_tlock(dev)); | 3240 | spin_unlock_irq(mlx4_tlock(dev)); |
3178 | } | 3241 | } |
3179 | 3242 | ||
3243 | static void rem_slave_fs_rule(struct mlx4_dev *dev, int slave) | ||
3244 | { | ||
3245 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
3246 | struct mlx4_resource_tracker *tracker = | ||
3247 | &priv->mfunc.master.res_tracker; | ||
3248 | struct list_head *fs_rule_list = | ||
3249 | &tracker->slave_list[slave].res_list[RES_FS_RULE]; | ||
3250 | struct res_fs_rule *fs_rule; | ||
3251 | struct res_fs_rule *tmp; | ||
3252 | int state; | ||
3253 | u64 base; | ||
3254 | int err; | ||
3255 | |||
3256 | err = move_all_busy(dev, slave, RES_FS_RULE); | ||
3257 | if (err) | ||
3258 | mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n", | ||
3259 | slave); | ||
3260 | |||
3261 | spin_lock_irq(mlx4_tlock(dev)); | ||
3262 | list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) { | ||
3263 | spin_unlock_irq(mlx4_tlock(dev)); | ||
3264 | if (fs_rule->com.owner == slave) { | ||
3265 | base = fs_rule->com.res_id; | ||
3266 | state = fs_rule->com.from_state; | ||
3267 | while (state != 0) { | ||
3268 | switch (state) { | ||
3269 | case RES_FS_RULE_ALLOCATED: | ||
3270 | /* detach rule */ | ||
3271 | err = mlx4_cmd(dev, base, 0, 0, | ||
3272 | MLX4_QP_FLOW_STEERING_DETACH, | ||
3273 | MLX4_CMD_TIME_CLASS_A, | ||
3274 | MLX4_CMD_NATIVE); | ||
3275 | |||
3276 | spin_lock_irq(mlx4_tlock(dev)); | ||
3277 | rb_erase(&fs_rule->com.node, | ||
3278 | &tracker->res_tree[RES_FS_RULE]); | ||
3279 | list_del(&fs_rule->com.list); | ||
3280 | spin_unlock_irq(mlx4_tlock(dev)); | ||
3281 | kfree(fs_rule); | ||
3282 | state = 0; | ||
3283 | break; | ||
3284 | |||
3285 | default: | ||
3286 | state = 0; | ||
3287 | } | ||
3288 | } | ||
3289 | } | ||
3290 | spin_lock_irq(mlx4_tlock(dev)); | ||
3291 | } | ||
3292 | spin_unlock_irq(mlx4_tlock(dev)); | ||
3293 | } | ||
3294 | |||
3180 | static void rem_slave_eqs(struct mlx4_dev *dev, int slave) | 3295 | static void rem_slave_eqs(struct mlx4_dev *dev, int slave) |
3181 | { | 3296 | { |
3182 | struct mlx4_priv *priv = mlx4_priv(dev); | 3297 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -3318,5 +3433,6 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
3318 | rem_slave_mtts(dev, slave); | 3433 | rem_slave_mtts(dev, slave); |
3319 | rem_slave_counters(dev, slave); | 3434 | rem_slave_counters(dev, slave); |
3320 | rem_slave_xrcdns(dev, slave); | 3435 | rem_slave_xrcdns(dev, slave); |
3436 | rem_slave_fs_rule(dev, slave); | ||
3321 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 3437 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
3322 | } | 3438 | } |