diff options
author | Hadar Hen Zion <hadarh@mellanox.co.il> | 2012-07-05 00:03:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-07 19:23:05 -0400 |
commit | 4af1c0488da97293c09d37ca49543566406073e6 (patch) | |
tree | 5c99c9767706f049012a148df9d979ae243709c8 /drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |
parent | d3a5ea6e2188adeea028c410c83c90e6b6d9347c (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.c | 106 |
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 | ||
58 | struct res_common { | 58 | struct 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 | ||
193 | static 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 | |||
211 | static 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 */ |
193 | static const char *ResourceType(enum mlx4_resource rt) | 237 | static 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 | ||
284 | static int get_res(struct mlx4_dev *dev, int slave, int res_id, | 327 | static 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 | ||
560 | undo: | 603 | undo: |
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); |