aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_mr.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@mellanox.co.il>2005-04-16 18:26:26 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:26:26 -0400
commit9095e208d84c349193fa19245cd5a8bc1a9774b8 (patch)
treecdef394c9e01b44d59125b8a4e299e4a7d984384 /drivers/infiniband/hw/mthca/mthca_mr.c
parent8df8a34de60f8e51c87e5c145679f1a896133199 (diff)
[PATCH] IB/mthca: encapsulate MTT buddy allocator
Encapsulate the buddy allocator used for MTT segments. This cleans up the code and also gets us ready to add FMR support. Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <roland@topspin.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_mr.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c160
1 files changed, 88 insertions, 72 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 5cde296b4065..6a127a7aca57 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -72,60 +72,108 @@ struct mthca_mpt_entry {
72 * through the bitmaps) 72 * through the bitmaps)
73 */ 73 */
74 74
75static u32 __mthca_alloc_mtt(struct mthca_dev *dev, int order) 75static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
76{ 76{
77 int o; 77 int o;
78 int m; 78 int m;
79 u32 seg; 79 u32 seg;
80 80
81 spin_lock(&dev->mr_table.mpt_alloc.lock); 81 spin_lock(&buddy->lock);
82 82
83 for (o = order; o <= dev->mr_table.max_mtt_order; ++o) { 83 for (o = order; o <= buddy->max_order; ++o) {
84 m = 1 << (dev->mr_table.max_mtt_order - o); 84 m = 1 << (buddy->max_order - o);
85 seg = find_first_bit(dev->mr_table.mtt_buddy[o], m); 85 seg = find_first_bit(buddy->bits[o], m);
86 if (seg < m) 86 if (seg < m)
87 goto found; 87 goto found;
88 } 88 }
89 89
90 spin_unlock(&dev->mr_table.mpt_alloc.lock); 90 spin_unlock(&buddy->lock);
91 return -1; 91 return -1;
92 92
93 found: 93 found:
94 clear_bit(seg, dev->mr_table.mtt_buddy[o]); 94 clear_bit(seg, buddy->bits[o]);
95 95
96 while (o > order) { 96 while (o > order) {
97 --o; 97 --o;
98 seg <<= 1; 98 seg <<= 1;
99 set_bit(seg ^ 1, dev->mr_table.mtt_buddy[o]); 99 set_bit(seg ^ 1, buddy->bits[o]);
100 } 100 }
101 101
102 spin_unlock(&dev->mr_table.mpt_alloc.lock); 102 spin_unlock(&buddy->lock);
103 103
104 seg <<= order; 104 seg <<= order;
105 105
106 return seg; 106 return seg;
107} 107}
108 108
109static void __mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order) 109static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
110{ 110{
111 seg >>= order; 111 seg >>= order;
112 112
113 spin_lock(&dev->mr_table.mpt_alloc.lock); 113 spin_lock(&buddy->lock);
114 114
115 while (test_bit(seg ^ 1, dev->mr_table.mtt_buddy[order])) { 115 while (test_bit(seg ^ 1, buddy->bits[order])) {
116 clear_bit(seg ^ 1, dev->mr_table.mtt_buddy[order]); 116 clear_bit(seg ^ 1, buddy->bits[order]);
117 seg >>= 1; 117 seg >>= 1;
118 ++order; 118 ++order;
119 } 119 }
120 120
121 set_bit(seg, dev->mr_table.mtt_buddy[order]); 121 set_bit(seg, buddy->bits[order]);
122 122
123 spin_unlock(&dev->mr_table.mpt_alloc.lock); 123 spin_unlock(&buddy->lock);
124} 124}
125 125
126static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order) 126static int __devinit mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
127{ 127{
128 u32 seg = __mthca_alloc_mtt(dev, order); 128 int i, s;
129
130 buddy->max_order = max_order;
131 spin_lock_init(&buddy->lock);
132
133 buddy->bits = kmalloc((buddy->max_order + 1) * sizeof (long *),
134 GFP_KERNEL);
135 if (!buddy->bits)
136 goto err_out;
137
138 memset(buddy->bits, 0, (buddy->max_order + 1) * sizeof (long *));
139
140 for (i = 0; i <= buddy->max_order; ++i) {
141 s = BITS_TO_LONGS(1 << (buddy->max_order - i));
142 buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
143 if (!buddy->bits[i])
144 goto err_out_free;
145 bitmap_zero(buddy->bits[i],
146 1 << (buddy->max_order - i));
147 }
148
149 set_bit(0, buddy->bits[buddy->max_order]);
150
151 return 0;
152
153err_out_free:
154 for (i = 0; i <= buddy->max_order; ++i)
155 kfree(buddy->bits[i]);
156
157 kfree(buddy->bits);
158
159err_out:
160 return -ENOMEM;
161}
162
163static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy)
164{
165 int i;
166
167 for (i = 0; i <= buddy->max_order; ++i)
168 kfree(buddy->bits[i]);
169
170 kfree(buddy->bits);
171}
172
173static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order,
174 struct mthca_buddy *buddy)
175{
176 u32 seg = mthca_buddy_alloc(buddy, order);
129 177
130 if (seg == -1) 178 if (seg == -1)
131 return -1; 179 return -1;
@@ -133,16 +181,17 @@ static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order)
133 if (dev->hca_type == ARBEL_NATIVE) 181 if (dev->hca_type == ARBEL_NATIVE)
134 if (mthca_table_get_range(dev, dev->mr_table.mtt_table, seg, 182 if (mthca_table_get_range(dev, dev->mr_table.mtt_table, seg,
135 seg + (1 << order) - 1)) { 183 seg + (1 << order) - 1)) {
136 __mthca_free_mtt(dev, seg, order); 184 mthca_buddy_free(buddy, seg, order);
137 seg = -1; 185 seg = -1;
138 } 186 }
139 187
140 return seg; 188 return seg;
141} 189}
142 190
143static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order) 191static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order,
192 struct mthca_buddy* buddy)
144{ 193{
145 __mthca_free_mtt(dev, seg, order); 194 mthca_buddy_free(buddy, seg, order);
146 195
147 if (dev->hca_type == ARBEL_NATIVE) 196 if (dev->hca_type == ARBEL_NATIVE)
148 mthca_table_put_range(dev, dev->mr_table.mtt_table, seg, 197 mthca_table_put_range(dev, dev->mr_table.mtt_table, seg,
@@ -268,7 +317,8 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
268 i <<= 1, ++mr->order) 317 i <<= 1, ++mr->order)
269 ; /* nothing */ 318 ; /* nothing */
270 319
271 mr->first_seg = mthca_alloc_mtt(dev, mr->order); 320 mr->first_seg = mthca_alloc_mtt(dev, mr->order,
321 &dev->mr_table.mtt_buddy);
272 if (mr->first_seg == -1) 322 if (mr->first_seg == -1)
273 goto err_out_table; 323 goto err_out_table;
274 324
@@ -361,7 +411,7 @@ err_out_mailbox_free:
361 kfree(mailbox); 411 kfree(mailbox);
362 412
363err_out_free_mtt: 413err_out_free_mtt:
364 mthca_free_mtt(dev, mr->first_seg, mr->order); 414 mthca_free_mtt(dev, mr->first_seg, mr->order, &dev->mr_table.mtt_buddy);
365 415
366err_out_table: 416err_out_table:
367 if (dev->hca_type == ARBEL_NATIVE) 417 if (dev->hca_type == ARBEL_NATIVE)
@@ -390,7 +440,7 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
390 status); 440 status);
391 441
392 if (mr->order >= 0) 442 if (mr->order >= 0)
393 mthca_free_mtt(dev, mr->first_seg, mr->order); 443 mthca_free_mtt(dev, mr->first_seg, mr->order, &dev->mr_table.mtt_buddy);
394 444
395 if (dev->hca_type == ARBEL_NATIVE) 445 if (dev->hca_type == ARBEL_NATIVE)
396 mthca_table_put(dev, dev->mr_table.mpt_table, 446 mthca_table_put(dev, dev->mr_table.mpt_table,
@@ -401,7 +451,6 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
401int __devinit mthca_init_mr_table(struct mthca_dev *dev) 451int __devinit mthca_init_mr_table(struct mthca_dev *dev)
402{ 452{
403 int err; 453 int err;
404 int i, s;
405 454
406 err = mthca_alloc_init(&dev->mr_table.mpt_alloc, 455 err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
407 dev->limits.num_mpts, 456 dev->limits.num_mpts,
@@ -409,53 +458,24 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
409 if (err) 458 if (err)
410 return err; 459 return err;
411 460
412 err = -ENOMEM; 461 err = mthca_buddy_init(&dev->mr_table.mtt_buddy,
413 462 fls(dev->limits.num_mtt_segs - 1));
414 for (i = 1, dev->mr_table.max_mtt_order = 0; 463 if (err)
415 i < dev->limits.num_mtt_segs; 464 goto err_mtt_buddy;
416 i <<= 1, ++dev->mr_table.max_mtt_order) 465
417 ; /* nothing */ 466 if (dev->limits.reserved_mtts) {
418 467 if (mthca_alloc_mtt(dev, fls(dev->limits.reserved_mtts - 1),
419 dev->mr_table.mtt_buddy = kmalloc((dev->mr_table.max_mtt_order + 1) * 468 &dev->mr_table.mtt_buddy) == -1) {
420 sizeof (long *), 469 mthca_warn(dev, "MTT table of order %d is too small.\n",
421 GFP_KERNEL); 470 dev->mr_table.mtt_buddy.max_order);
422 if (!dev->mr_table.mtt_buddy) 471 err = -ENOMEM;
423 goto err_out; 472 goto err_mtt_buddy;
424 473 }
425 for (i = 0; i <= dev->mr_table.max_mtt_order; ++i)
426 dev->mr_table.mtt_buddy[i] = NULL;
427
428 for (i = 0; i <= dev->mr_table.max_mtt_order; ++i) {
429 s = BITS_TO_LONGS(1 << (dev->mr_table.max_mtt_order - i));
430 dev->mr_table.mtt_buddy[i] = kmalloc(s * sizeof (long),
431 GFP_KERNEL);
432 if (!dev->mr_table.mtt_buddy[i])
433 goto err_out_free;
434 bitmap_zero(dev->mr_table.mtt_buddy[i],
435 1 << (dev->mr_table.max_mtt_order - i));
436 }
437
438 set_bit(0, dev->mr_table.mtt_buddy[dev->mr_table.max_mtt_order]);
439
440 for (i = 0; i < dev->mr_table.max_mtt_order; ++i)
441 if (1 << i >= dev->limits.reserved_mtts)
442 break;
443
444 if (i == dev->mr_table.max_mtt_order) {
445 mthca_err(dev, "MTT table of order %d is "
446 "too small.\n", i);
447 goto err_out_free;
448 } 474 }
449 475
450 (void) mthca_alloc_mtt(dev, i);
451
452 return 0; 476 return 0;
453 477
454 err_out_free: 478err_mtt_buddy:
455 for (i = 0; i <= dev->mr_table.max_mtt_order; ++i)
456 kfree(dev->mr_table.mtt_buddy[i]);
457
458 err_out:
459 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc); 479 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc);
460 480
461 return err; 481 return err;
@@ -463,11 +483,7 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
463 483
464void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev) 484void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev)
465{ 485{
466 int i;
467
468 /* XXX check if any MRs are still allocated? */ 486 /* XXX check if any MRs are still allocated? */
469 for (i = 0; i <= dev->mr_table.max_mtt_order; ++i) 487 mthca_buddy_cleanup(&dev->mr_table.mtt_buddy);
470 kfree(dev->mr_table.mtt_buddy[i]);
471 kfree(dev->mr_table.mtt_buddy);
472 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc); 488 mthca_alloc_cleanup(&dev->mr_table.mpt_alloc);
473} 489}