aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
diff options
context:
space:
mode:
authorHadar Hen Zion <hadarh@mellanox.co.il>2012-07-05 00:03:41 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-07 19:23:05 -0400
commit4af1c0488da97293c09d37ca49543566406073e6 (patch)
tree5c99c9767706f049012a148df9d979ae243709c8 /drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
parentd3a5ea6e2188adeea028c410c83c90e6b6d9347c (diff)
net/mlx4_core: Change resource tracking mechanism to use red-black tree
Change the data structure used for managing the SRIOV resource tracking mechanism from radix tree to red-black tree. This is preparation step for supporting resource IDs which are 64bit long, such as network flow steering rules. Such IDs can't be used as radix-tree keys on 32bit architectures and hence the reason for the change. 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/resource_tracker.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c106
1 files changed, 75 insertions, 31 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 766b8c5a235e..80c03c802301 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -57,6 +57,7 @@ struct mac_res {
57 57
58struct res_common { 58struct res_common {
59 struct list_head list; 59 struct list_head list;
60 struct rb_node node;
60 u32 res_id; 61 u32 res_id;
61 int owner; 62 int owner;
62 int state; 63 int state;
@@ -189,6 +190,49 @@ struct res_xrcdn {
189 int port; 190 int port;
190}; 191};
191 192
193static void *res_tracker_lookup(struct rb_root *root, u64 res_id)
194{
195 struct rb_node *node = root->rb_node;
196
197 while (node) {
198 struct res_common *res = container_of(node, struct res_common,
199 node);
200
201 if (res_id < res->res_id)
202 node = node->rb_left;
203 else if (res_id > res->res_id)
204 node = node->rb_right;
205 else
206 return res;
207 }
208 return NULL;
209}
210
211static int res_tracker_insert(struct rb_root *root, struct res_common *res)
212{
213 struct rb_node **new = &(root->rb_node), *parent = NULL;
214
215 /* Figure out where to put new node */
216 while (*new) {
217 struct res_common *this = container_of(*new, struct res_common,
218 node);
219
220 parent = *new;
221 if (res->res_id < this->res_id)
222 new = &((*new)->rb_left);
223 else if (res->res_id > this->res_id)
224 new = &((*new)->rb_right);
225 else
226 return -EEXIST;
227 }
228
229 /* Add new node and rebalance tree. */
230 rb_link_node(&res->node, parent, new);
231 rb_insert_color(&res->node, root);
232
233 return 0;
234}
235
192/* For Debug uses */ 236/* For Debug uses */
193static const char *ResourceType(enum mlx4_resource rt) 237static const char *ResourceType(enum mlx4_resource rt)
194{ 238{
@@ -228,8 +272,7 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
228 mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n", 272 mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n",
229 dev->num_slaves); 273 dev->num_slaves);
230 for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) 274 for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++)
231 INIT_RADIX_TREE(&priv->mfunc.master.res_tracker.res_tree[i], 275 priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT;
232 GFP_ATOMIC|__GFP_NOWARN);
233 276
234 spin_lock_init(&priv->mfunc.master.res_tracker.lock); 277 spin_lock_init(&priv->mfunc.master.res_tracker.lock);
235 return 0 ; 278 return 0 ;
@@ -277,8 +320,8 @@ static void *find_res(struct mlx4_dev *dev, int res_id,
277{ 320{
278 struct mlx4_priv *priv = mlx4_priv(dev); 321 struct mlx4_priv *priv = mlx4_priv(dev);
279 322
280 return radix_tree_lookup(&priv->mfunc.master.res_tracker.res_tree[type], 323 return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type],
281 res_id); 324 res_id);
282} 325}
283 326
284static int get_res(struct mlx4_dev *dev, int slave, int res_id, 327static int get_res(struct mlx4_dev *dev, int slave, int res_id,
@@ -523,7 +566,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count,
523 struct mlx4_priv *priv = mlx4_priv(dev); 566 struct mlx4_priv *priv = mlx4_priv(dev);
524 struct res_common **res_arr; 567 struct res_common **res_arr;
525 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; 568 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
526 struct radix_tree_root *root = &tracker->res_tree[type]; 569 struct rb_root *root = &tracker->res_tree[type];
527 570
528 res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL); 571 res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL);
529 if (!res_arr) 572 if (!res_arr)
@@ -546,7 +589,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count,
546 err = -EEXIST; 589 err = -EEXIST;
547 goto undo; 590 goto undo;
548 } 591 }
549 err = radix_tree_insert(root, base + i, res_arr[i]); 592 err = res_tracker_insert(root, res_arr[i]);
550 if (err) 593 if (err)
551 goto undo; 594 goto undo;
552 list_add_tail(&res_arr[i]->list, 595 list_add_tail(&res_arr[i]->list,
@@ -559,7 +602,7 @@ static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count,
559 602
560undo: 603undo:
561 for (--i; i >= base; --i) 604 for (--i; i >= base; --i)
562 radix_tree_delete(&tracker->res_tree[type], i); 605 rb_erase(&res_arr[i]->node, root);
563 606
564 spin_unlock_irq(mlx4_tlock(dev)); 607 spin_unlock_irq(mlx4_tlock(dev));
565 608
@@ -695,7 +738,7 @@ static int rem_res_range(struct mlx4_dev *dev, int slave, int base, int count,
695 738
696 spin_lock_irq(mlx4_tlock(dev)); 739 spin_lock_irq(mlx4_tlock(dev));
697 for (i = base; i < base + count; ++i) { 740 for (i = base; i < base + count; ++i) {
698 r = radix_tree_lookup(&tracker->res_tree[type], i); 741 r = res_tracker_lookup(&tracker->res_tree[type], i);
699 if (!r) { 742 if (!r) {
700 err = -ENOENT; 743 err = -ENOENT;
701 goto out; 744 goto out;
@@ -710,8 +753,8 @@ static int rem_res_range(struct mlx4_dev *dev, int slave, int base, int count,
710 } 753 }
711 754
712 for (i = base; i < base + count; ++i) { 755 for (i = base; i < base + count; ++i) {
713 r = radix_tree_lookup(&tracker->res_tree[type], i); 756 r = res_tracker_lookup(&tracker->res_tree[type], i);
714 radix_tree_delete(&tracker->res_tree[type], i); 757 rb_erase(&r->node, &tracker->res_tree[type]);
715 list_del(&r->list); 758 list_del(&r->list);
716 kfree(r); 759 kfree(r);
717 } 760 }
@@ -733,7 +776,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
733 int err = 0; 776 int err = 0;
734 777
735 spin_lock_irq(mlx4_tlock(dev)); 778 spin_lock_irq(mlx4_tlock(dev));
736 r = radix_tree_lookup(&tracker->res_tree[RES_QP], qpn); 779 r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn);
737 if (!r) 780 if (!r)
738 err = -ENOENT; 781 err = -ENOENT;
739 else if (r->com.owner != slave) 782 else if (r->com.owner != slave)
@@ -797,7 +840,7 @@ static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
797 int err = 0; 840 int err = 0;
798 841
799 spin_lock_irq(mlx4_tlock(dev)); 842 spin_lock_irq(mlx4_tlock(dev));
800 r = radix_tree_lookup(&tracker->res_tree[RES_MPT], index); 843 r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index);
801 if (!r) 844 if (!r)
802 err = -ENOENT; 845 err = -ENOENT;
803 else if (r->com.owner != slave) 846 else if (r->com.owner != slave)
@@ -850,7 +893,7 @@ static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
850 int err = 0; 893 int err = 0;
851 894
852 spin_lock_irq(mlx4_tlock(dev)); 895 spin_lock_irq(mlx4_tlock(dev));
853 r = radix_tree_lookup(&tracker->res_tree[RES_EQ], index); 896 r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index);
854 if (!r) 897 if (!r)
855 err = -ENOENT; 898 err = -ENOENT;
856 else if (r->com.owner != slave) 899 else if (r->com.owner != slave)
@@ -898,7 +941,7 @@ static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn,
898 int err; 941 int err;
899 942
900 spin_lock_irq(mlx4_tlock(dev)); 943 spin_lock_irq(mlx4_tlock(dev));
901 r = radix_tree_lookup(&tracker->res_tree[RES_CQ], cqn); 944 r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn);
902 if (!r) 945 if (!r)
903 err = -ENOENT; 946 err = -ENOENT;
904 else if (r->com.owner != slave) 947 else if (r->com.owner != slave)
@@ -952,7 +995,7 @@ static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
952 int err = 0; 995 int err = 0;
953 996
954 spin_lock_irq(mlx4_tlock(dev)); 997 spin_lock_irq(mlx4_tlock(dev));
955 r = radix_tree_lookup(&tracker->res_tree[RES_SRQ], index); 998 r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index);
956 if (!r) 999 if (!r)
957 err = -ENOENT; 1000 err = -ENOENT;
958 else if (r->com.owner != slave) 1001 else if (r->com.owner != slave)
@@ -1001,7 +1044,7 @@ static void res_abort_move(struct mlx4_dev *dev, int slave,
1001 struct res_common *r; 1044 struct res_common *r;
1002 1045
1003 spin_lock_irq(mlx4_tlock(dev)); 1046 spin_lock_irq(mlx4_tlock(dev));
1004 r = radix_tree_lookup(&tracker->res_tree[type], id); 1047 r = res_tracker_lookup(&tracker->res_tree[type], id);
1005 if (r && (r->owner == slave)) 1048 if (r && (r->owner == slave))
1006 r->state = r->from_state; 1049 r->state = r->from_state;
1007 spin_unlock_irq(mlx4_tlock(dev)); 1050 spin_unlock_irq(mlx4_tlock(dev));
@@ -1015,7 +1058,7 @@ static void res_end_move(struct mlx4_dev *dev, int slave,
1015 struct res_common *r; 1058 struct res_common *r;
1016 1059
1017 spin_lock_irq(mlx4_tlock(dev)); 1060 spin_lock_irq(mlx4_tlock(dev));
1018 r = radix_tree_lookup(&tracker->res_tree[type], id); 1061 r = res_tracker_lookup(&tracker->res_tree[type], id);
1019 if (r && (r->owner == slave)) 1062 if (r && (r->owner == slave))
1020 r->state = r->to_state; 1063 r->state = r->to_state;
1021 spin_unlock_irq(mlx4_tlock(dev)); 1064 spin_unlock_irq(mlx4_tlock(dev));
@@ -2817,8 +2860,8 @@ static void rem_slave_qps(struct mlx4_dev *dev, int slave)
2817 switch (state) { 2860 switch (state) {
2818 case RES_QP_RESERVED: 2861 case RES_QP_RESERVED:
2819 spin_lock_irq(mlx4_tlock(dev)); 2862 spin_lock_irq(mlx4_tlock(dev));
2820 radix_tree_delete(&tracker->res_tree[RES_QP], 2863 rb_erase(&qp->com.node,
2821 qp->com.res_id); 2864 &tracker->res_tree[RES_QP]);
2822 list_del(&qp->com.list); 2865 list_del(&qp->com.list);
2823 spin_unlock_irq(mlx4_tlock(dev)); 2866 spin_unlock_irq(mlx4_tlock(dev));
2824 kfree(qp); 2867 kfree(qp);
@@ -2888,8 +2931,8 @@ static void rem_slave_srqs(struct mlx4_dev *dev, int slave)
2888 case RES_SRQ_ALLOCATED: 2931 case RES_SRQ_ALLOCATED:
2889 __mlx4_srq_free_icm(dev, srqn); 2932 __mlx4_srq_free_icm(dev, srqn);
2890 spin_lock_irq(mlx4_tlock(dev)); 2933 spin_lock_irq(mlx4_tlock(dev));
2891 radix_tree_delete(&tracker->res_tree[RES_SRQ], 2934 rb_erase(&srq->com.node,
2892 srqn); 2935 &tracker->res_tree[RES_SRQ]);
2893 list_del(&srq->com.list); 2936 list_del(&srq->com.list);
2894 spin_unlock_irq(mlx4_tlock(dev)); 2937 spin_unlock_irq(mlx4_tlock(dev));
2895 kfree(srq); 2938 kfree(srq);
@@ -2954,8 +2997,8 @@ static void rem_slave_cqs(struct mlx4_dev *dev, int slave)
2954 case RES_CQ_ALLOCATED: 2997 case RES_CQ_ALLOCATED:
2955 __mlx4_cq_free_icm(dev, cqn); 2998 __mlx4_cq_free_icm(dev, cqn);
2956 spin_lock_irq(mlx4_tlock(dev)); 2999 spin_lock_irq(mlx4_tlock(dev));
2957 radix_tree_delete(&tracker->res_tree[RES_CQ], 3000 rb_erase(&cq->com.node,
2958 cqn); 3001 &tracker->res_tree[RES_CQ]);
2959 list_del(&cq->com.list); 3002 list_del(&cq->com.list);
2960 spin_unlock_irq(mlx4_tlock(dev)); 3003 spin_unlock_irq(mlx4_tlock(dev));
2961 kfree(cq); 3004 kfree(cq);
@@ -3017,8 +3060,8 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave)
3017 case RES_MPT_RESERVED: 3060 case RES_MPT_RESERVED:
3018 __mlx4_mr_release(dev, mpt->key); 3061 __mlx4_mr_release(dev, mpt->key);
3019 spin_lock_irq(mlx4_tlock(dev)); 3062 spin_lock_irq(mlx4_tlock(dev));
3020 radix_tree_delete(&tracker->res_tree[RES_MPT], 3063 rb_erase(&mpt->com.node,
3021 mptn); 3064 &tracker->res_tree[RES_MPT]);
3022 list_del(&mpt->com.list); 3065 list_del(&mpt->com.list);
3023 spin_unlock_irq(mlx4_tlock(dev)); 3066 spin_unlock_irq(mlx4_tlock(dev));
3024 kfree(mpt); 3067 kfree(mpt);
@@ -3086,8 +3129,8 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave)
3086 __mlx4_free_mtt_range(dev, base, 3129 __mlx4_free_mtt_range(dev, base,
3087 mtt->order); 3130 mtt->order);
3088 spin_lock_irq(mlx4_tlock(dev)); 3131 spin_lock_irq(mlx4_tlock(dev));
3089 radix_tree_delete(&tracker->res_tree[RES_MTT], 3132 rb_erase(&mtt->com.node,
3090 base); 3133 &tracker->res_tree[RES_MTT]);
3091 list_del(&mtt->com.list); 3134 list_del(&mtt->com.list);
3092 spin_unlock_irq(mlx4_tlock(dev)); 3135 spin_unlock_irq(mlx4_tlock(dev));
3093 kfree(mtt); 3136 kfree(mtt);
@@ -3133,8 +3176,8 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
3133 switch (state) { 3176 switch (state) {
3134 case RES_EQ_RESERVED: 3177 case RES_EQ_RESERVED:
3135 spin_lock_irq(mlx4_tlock(dev)); 3178 spin_lock_irq(mlx4_tlock(dev));
3136 radix_tree_delete(&tracker->res_tree[RES_EQ], 3179 rb_erase(&eq->com.node,
3137 eqn); 3180 &tracker->res_tree[RES_EQ]);
3138 list_del(&eq->com.list); 3181 list_del(&eq->com.list);
3139 spin_unlock_irq(mlx4_tlock(dev)); 3182 spin_unlock_irq(mlx4_tlock(dev));
3140 kfree(eq); 3183 kfree(eq);
@@ -3191,7 +3234,8 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave)
3191 list_for_each_entry_safe(counter, tmp, counter_list, com.list) { 3234 list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
3192 if (counter->com.owner == slave) { 3235 if (counter->com.owner == slave) {
3193 index = counter->com.res_id; 3236 index = counter->com.res_id;
3194 radix_tree_delete(&tracker->res_tree[RES_COUNTER], index); 3237 rb_erase(&counter->com.node,
3238 &tracker->res_tree[RES_COUNTER]);
3195 list_del(&counter->com.list); 3239 list_del(&counter->com.list);
3196 kfree(counter); 3240 kfree(counter);
3197 __mlx4_counter_free(dev, index); 3241 __mlx4_counter_free(dev, index);
@@ -3220,7 +3264,7 @@ static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
3220 list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) { 3264 list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
3221 if (xrcd->com.owner == slave) { 3265 if (xrcd->com.owner == slave) {
3222 xrcdn = xrcd->com.res_id; 3266 xrcdn = xrcd->com.res_id;
3223 radix_tree_delete(&tracker->res_tree[RES_XRCD], xrcdn); 3267 rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]);
3224 list_del(&xrcd->com.list); 3268 list_del(&xrcd->com.list);
3225 kfree(xrcd); 3269 kfree(xrcd);
3226 __mlx4_xrcd_free(dev, xrcdn); 3270 __mlx4_xrcd_free(dev, xrcdn);