aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4
diff options
context:
space:
mode:
authorHadar Hen Zion <hadarh@mellanox.co.il>2012-07-05 00:03:47 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-07 19:23:06 -0400
commit1b9c6b064ef4fbc6f55485a8b5aab7ce889592c2 (patch)
tree86963d262d90c025555b183ffbd68a312199656e /drivers/net/ethernet/mellanox/mlx4
parent0ff1fb654bec0cff62ddf81a8a8edec4263604a0 (diff)
net/mlx4_core: Add resource tracking for device managed flow steering rules
As with other device resources, the resource tracker is needed for supporting device managed flow steering rules under SRIOV: make sure virtual functions delete only rules created by them, and clean all rules attached by a crashed VF. Signed-off-by: Hadar Hen Zion <hadarh@mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c132
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
193enum res_fs_rule_states {
194 RES_FS_RULE_BUSY = RES_ANY_BUSY,
195 RES_FS_RULE_ALLOCATED,
196};
197
198struct res_fs_rule {
199 struct res_common com;
200};
201
193static void *res_tracker_lookup(struct rb_root *root, u64 res_id) 202static 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
529static 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
519static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, 543static 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
711static 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
684static int remove_cq_ok(struct res_cq *res) 721static 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
2757int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, 2810int 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
2771enum { 2834enum {
@@ -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
3243static 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
3180static void rem_slave_eqs(struct mlx4_dev *dev, int slave) 3295static 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}