aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mlx5/mr.c
diff options
context:
space:
mode:
authorEli Cohen <eli@dev.mellanox.co.il>2013-10-23 02:53:14 -0400
committerRoland Dreier <roland@purestorage.com>2013-11-08 17:42:59 -0500
commit746b5583c1a48a837f4891adaff5e09d61b204a6 (patch)
treec939fde4e644095bcf476787aebe031f20150d0c /drivers/infiniband/hw/mlx5/mr.c
parent51ee86a4af639e4ee8953dd02ad8a766c40f46a1 (diff)
IB/mlx5: Multithreaded create MR
Use asynchronous commands to execute up to eight concurrent create MR commands. This is to fill memory caches faster so we keep consuming from there. Also, increase timeout for shrinking caches to five minutes. Signed-off-by: Eli Cohen <eli@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/mlx5/mr.c')
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c163
1 files changed, 125 insertions, 38 deletions
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 3453580b1eb2..d7f202290747 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -35,11 +35,13 @@
35#include <linux/random.h> 35#include <linux/random.h>
36#include <linux/debugfs.h> 36#include <linux/debugfs.h>
37#include <linux/export.h> 37#include <linux/export.h>
38#include <linux/delay.h>
38#include <rdma/ib_umem.h> 39#include <rdma/ib_umem.h>
39#include "mlx5_ib.h" 40#include "mlx5_ib.h"
40 41
41enum { 42enum {
42 DEF_CACHE_SIZE = 10, 43 DEF_CACHE_SIZE = 10,
44 MAX_PENDING_REG_MR = 8,
43}; 45};
44 46
45enum { 47enum {
@@ -63,6 +65,57 @@ static int order2idx(struct mlx5_ib_dev *dev, int order)
63 return order - cache->ent[0].order; 65 return order - cache->ent[0].order;
64} 66}
65 67
68static void reg_mr_callback(int status, void *context)
69{
70 struct mlx5_ib_mr *mr = context;
71 struct mlx5_ib_dev *dev = mr->dev;
72 struct mlx5_mr_cache *cache = &dev->cache;
73 int c = order2idx(dev, mr->order);
74 struct mlx5_cache_ent *ent = &cache->ent[c];
75 u8 key;
76 unsigned long delta = jiffies - mr->start;
77 unsigned long index;
78 unsigned long flags;
79
80 index = find_last_bit(&delta, 8 * sizeof(delta));
81 if (index == 64)
82 index = 0;
83
84 spin_lock_irqsave(&ent->lock, flags);
85 ent->pending--;
86 spin_unlock_irqrestore(&ent->lock, flags);
87 if (status) {
88 mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
89 kfree(mr);
90 dev->fill_delay = 1;
91 mod_timer(&dev->delay_timer, jiffies + HZ);
92 return;
93 }
94
95 if (mr->out.hdr.status) {
96 mlx5_ib_warn(dev, "failed - status %d, syndorme 0x%x\n",
97 mr->out.hdr.status,
98 be32_to_cpu(mr->out.hdr.syndrome));
99 kfree(mr);
100 dev->fill_delay = 1;
101 mod_timer(&dev->delay_timer, jiffies + HZ);
102 return;
103 }
104
105 spin_lock_irqsave(&dev->mdev.priv.mkey_lock, flags);
106 key = dev->mdev.priv.mkey_key++;
107 spin_unlock_irqrestore(&dev->mdev.priv.mkey_lock, flags);
108 mr->mmr.key = mlx5_idx_to_mkey(be32_to_cpu(mr->out.mkey) & 0xffffff) | key;
109
110 cache->last_add = jiffies;
111
112 spin_lock_irqsave(&ent->lock, flags);
113 list_add_tail(&mr->list, &ent->head);
114 ent->cur++;
115 ent->size++;
116 spin_unlock_irqrestore(&ent->lock, flags);
117}
118
66static int add_keys(struct mlx5_ib_dev *dev, int c, int num) 119static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
67{ 120{
68 struct mlx5_mr_cache *cache = &dev->cache; 121 struct mlx5_mr_cache *cache = &dev->cache;
@@ -78,36 +131,39 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
78 return -ENOMEM; 131 return -ENOMEM;
79 132
80 for (i = 0; i < num; i++) { 133 for (i = 0; i < num; i++) {
134 if (ent->pending >= MAX_PENDING_REG_MR) {
135 err = -EAGAIN;
136 break;
137 }
138
81 mr = kzalloc(sizeof(*mr), GFP_KERNEL); 139 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
82 if (!mr) { 140 if (!mr) {
83 err = -ENOMEM; 141 err = -ENOMEM;
84 goto out; 142 break;
85 } 143 }
86 mr->order = ent->order; 144 mr->order = ent->order;
87 mr->umred = 1; 145 mr->umred = 1;
146 mr->dev = dev;
88 in->seg.status = 1 << 6; 147 in->seg.status = 1 << 6;
89 in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2); 148 in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2);
90 in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); 149 in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
91 in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN; 150 in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN;
92 in->seg.log2_page_size = 12; 151 in->seg.log2_page_size = 12;
93 152
153 spin_lock_irq(&ent->lock);
154 ent->pending++;
155 spin_unlock_irq(&ent->lock);
156 mr->start = jiffies;
94 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, 157 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in,
95 sizeof(*in)); 158 sizeof(*in), reg_mr_callback,
159 mr, &mr->out);
96 if (err) { 160 if (err) {
97 mlx5_ib_warn(dev, "create mkey failed %d\n", err); 161 mlx5_ib_warn(dev, "create mkey failed %d\n", err);
98 kfree(mr); 162 kfree(mr);
99 goto out; 163 break;
100 } 164 }
101 cache->last_add = jiffies;
102
103 spin_lock(&ent->lock);
104 list_add_tail(&mr->list, &ent->head);
105 ent->cur++;
106 ent->size++;
107 spin_unlock(&ent->lock);
108 } 165 }
109 166
110out:
111 kfree(in); 167 kfree(in);
112 return err; 168 return err;
113} 169}
@@ -121,16 +177,16 @@ static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
121 int i; 177 int i;
122 178
123 for (i = 0; i < num; i++) { 179 for (i = 0; i < num; i++) {
124 spin_lock(&ent->lock); 180 spin_lock_irq(&ent->lock);
125 if (list_empty(&ent->head)) { 181 if (list_empty(&ent->head)) {
126 spin_unlock(&ent->lock); 182 spin_unlock_irq(&ent->lock);
127 return; 183 return;
128 } 184 }
129 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list); 185 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
130 list_del(&mr->list); 186 list_del(&mr->list);
131 ent->cur--; 187 ent->cur--;
132 ent->size--; 188 ent->size--;
133 spin_unlock(&ent->lock); 189 spin_unlock_irq(&ent->lock);
134 err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); 190 err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
135 if (err) 191 if (err)
136 mlx5_ib_warn(dev, "failed destroy mkey\n"); 192 mlx5_ib_warn(dev, "failed destroy mkey\n");
@@ -162,9 +218,13 @@ static ssize_t size_write(struct file *filp, const char __user *buf,
162 return -EINVAL; 218 return -EINVAL;
163 219
164 if (var > ent->size) { 220 if (var > ent->size) {
165 err = add_keys(dev, c, var - ent->size); 221 do {
166 if (err) 222 err = add_keys(dev, c, var - ent->size);
167 return err; 223 if (err && err != -EAGAIN)
224 return err;
225
226 usleep_range(3000, 5000);
227 } while (err);
168 } else if (var < ent->size) { 228 } else if (var < ent->size) {
169 remove_keys(dev, c, ent->size - var); 229 remove_keys(dev, c, ent->size - var);
170 } 230 }
@@ -280,23 +340,37 @@ static void __cache_work_func(struct mlx5_cache_ent *ent)
280 struct mlx5_ib_dev *dev = ent->dev; 340 struct mlx5_ib_dev *dev = ent->dev;
281 struct mlx5_mr_cache *cache = &dev->cache; 341 struct mlx5_mr_cache *cache = &dev->cache;
282 int i = order2idx(dev, ent->order); 342 int i = order2idx(dev, ent->order);
343 int err;
283 344
284 if (cache->stopped) 345 if (cache->stopped)
285 return; 346 return;
286 347
287 ent = &dev->cache.ent[i]; 348 ent = &dev->cache.ent[i];
288 if (ent->cur < 2 * ent->limit) { 349 if (ent->cur < 2 * ent->limit && !dev->fill_delay) {
289 add_keys(dev, i, 1); 350 err = add_keys(dev, i, 1);
290 if (ent->cur < 2 * ent->limit) 351 if (ent->cur < 2 * ent->limit) {
291 queue_work(cache->wq, &ent->work); 352 if (err == -EAGAIN) {
353 mlx5_ib_dbg(dev, "returned eagain, order %d\n",
354 i + 2);
355 queue_delayed_work(cache->wq, &ent->dwork,
356 msecs_to_jiffies(3));
357 } else if (err) {
358 mlx5_ib_warn(dev, "command failed order %d, err %d\n",
359 i + 2, err);
360 queue_delayed_work(cache->wq, &ent->dwork,
361 msecs_to_jiffies(1000));
362 } else {
363 queue_work(cache->wq, &ent->work);
364 }
365 }
292 } else if (ent->cur > 2 * ent->limit) { 366 } else if (ent->cur > 2 * ent->limit) {
293 if (!someone_adding(cache) && 367 if (!someone_adding(cache) &&
294 time_after(jiffies, cache->last_add + 60 * HZ)) { 368 time_after(jiffies, cache->last_add + 300 * HZ)) {
295 remove_keys(dev, i, 1); 369 remove_keys(dev, i, 1);
296 if (ent->cur > ent->limit) 370 if (ent->cur > ent->limit)
297 queue_work(cache->wq, &ent->work); 371 queue_work(cache->wq, &ent->work);
298 } else { 372 } else {
299 queue_delayed_work(cache->wq, &ent->dwork, 60 * HZ); 373 queue_delayed_work(cache->wq, &ent->dwork, 300 * HZ);
300 } 374 }
301 } 375 }
302} 376}
@@ -336,18 +410,18 @@ static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
336 410
337 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i); 411 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
338 412
339 spin_lock(&ent->lock); 413 spin_lock_irq(&ent->lock);
340 if (!list_empty(&ent->head)) { 414 if (!list_empty(&ent->head)) {
341 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, 415 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
342 list); 416 list);
343 list_del(&mr->list); 417 list_del(&mr->list);
344 ent->cur--; 418 ent->cur--;
345 spin_unlock(&ent->lock); 419 spin_unlock_irq(&ent->lock);
346 if (ent->cur < ent->limit) 420 if (ent->cur < ent->limit)
347 queue_work(cache->wq, &ent->work); 421 queue_work(cache->wq, &ent->work);
348 break; 422 break;
349 } 423 }
350 spin_unlock(&ent->lock); 424 spin_unlock_irq(&ent->lock);
351 425
352 queue_work(cache->wq, &ent->work); 426 queue_work(cache->wq, &ent->work);
353 427
@@ -374,12 +448,12 @@ static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
374 return; 448 return;
375 } 449 }
376 ent = &cache->ent[c]; 450 ent = &cache->ent[c];
377 spin_lock(&ent->lock); 451 spin_lock_irq(&ent->lock);
378 list_add_tail(&mr->list, &ent->head); 452 list_add_tail(&mr->list, &ent->head);
379 ent->cur++; 453 ent->cur++;
380 if (ent->cur > 2 * ent->limit) 454 if (ent->cur > 2 * ent->limit)
381 shrink = 1; 455 shrink = 1;
382 spin_unlock(&ent->lock); 456 spin_unlock_irq(&ent->lock);
383 457
384 if (shrink) 458 if (shrink)
385 queue_work(cache->wq, &ent->work); 459 queue_work(cache->wq, &ent->work);
@@ -394,16 +468,16 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
394 468
395 cancel_delayed_work(&ent->dwork); 469 cancel_delayed_work(&ent->dwork);
396 while (1) { 470 while (1) {
397 spin_lock(&ent->lock); 471 spin_lock_irq(&ent->lock);
398 if (list_empty(&ent->head)) { 472 if (list_empty(&ent->head)) {
399 spin_unlock(&ent->lock); 473 spin_unlock_irq(&ent->lock);
400 return; 474 return;
401 } 475 }
402 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list); 476 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
403 list_del(&mr->list); 477 list_del(&mr->list);
404 ent->cur--; 478 ent->cur--;
405 ent->size--; 479 ent->size--;
406 spin_unlock(&ent->lock); 480 spin_unlock_irq(&ent->lock);
407 err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); 481 err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
408 if (err) 482 if (err)
409 mlx5_ib_warn(dev, "failed destroy mkey\n"); 483 mlx5_ib_warn(dev, "failed destroy mkey\n");
@@ -464,6 +538,13 @@ static void mlx5_mr_cache_debugfs_cleanup(struct mlx5_ib_dev *dev)
464 debugfs_remove_recursive(dev->cache.root); 538 debugfs_remove_recursive(dev->cache.root);
465} 539}
466 540
541static void delay_time_func(unsigned long ctx)
542{
543 struct mlx5_ib_dev *dev = (struct mlx5_ib_dev *)ctx;
544
545 dev->fill_delay = 0;
546}
547
467int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) 548int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
468{ 549{
469 struct mlx5_mr_cache *cache = &dev->cache; 550 struct mlx5_mr_cache *cache = &dev->cache;
@@ -479,6 +560,7 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
479 return -ENOMEM; 560 return -ENOMEM;
480 } 561 }
481 562
563 setup_timer(&dev->delay_timer, delay_time_func, (unsigned long)dev);
482 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { 564 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
483 INIT_LIST_HEAD(&cache->ent[i].head); 565 INIT_LIST_HEAD(&cache->ent[i].head);
484 spin_lock_init(&cache->ent[i].lock); 566 spin_lock_init(&cache->ent[i].lock);
@@ -522,6 +604,7 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
522 clean_keys(dev, i); 604 clean_keys(dev, i);
523 605
524 destroy_workqueue(dev->cache.wq); 606 destroy_workqueue(dev->cache.wq);
607 del_timer_sync(&dev->delay_timer);
525 608
526 return 0; 609 return 0;
527} 610}
@@ -551,7 +634,8 @@ struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
551 seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); 634 seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
552 seg->start_addr = 0; 635 seg->start_addr = 0;
553 636
554 err = mlx5_core_create_mkey(mdev, &mr->mmr, in, sizeof(*in)); 637 err = mlx5_core_create_mkey(mdev, &mr->mmr, in, sizeof(*in), NULL, NULL,
638 NULL);
555 if (err) 639 if (err)
556 goto err_in; 640 goto err_in;
557 641
@@ -660,14 +744,14 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
660 int err; 744 int err;
661 int i; 745 int i;
662 746
663 for (i = 0; i < 10; i++) { 747 for (i = 0; i < 1; i++) {
664 mr = alloc_cached_mr(dev, order); 748 mr = alloc_cached_mr(dev, order);
665 if (mr) 749 if (mr)
666 break; 750 break;
667 751
668 err = add_keys(dev, order2idx(dev, order), 1); 752 err = add_keys(dev, order2idx(dev, order), 1);
669 if (err) { 753 if (err && err != -EAGAIN) {
670 mlx5_ib_warn(dev, "add_keys failed\n"); 754 mlx5_ib_warn(dev, "add_keys failed, err %d\n", err);
671 break; 755 break;
672 } 756 }
673 } 757 }
@@ -759,8 +843,10 @@ static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, u64 virt_addr,
759 in->seg.xlt_oct_size = cpu_to_be32(get_octo_len(virt_addr, length, 1 << page_shift)); 843 in->seg.xlt_oct_size = cpu_to_be32(get_octo_len(virt_addr, length, 1 << page_shift));
760 in->seg.log2_page_size = page_shift; 844 in->seg.log2_page_size = page_shift;
761 in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); 845 in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
762 in->xlat_oct_act_size = cpu_to_be32(get_octo_len(virt_addr, length, 1 << page_shift)); 846 in->xlat_oct_act_size = cpu_to_be32(get_octo_len(virt_addr, length,
763 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, inlen); 847 1 << page_shift));
848 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, inlen, NULL,
849 NULL, NULL);
764 if (err) { 850 if (err) {
765 mlx5_ib_warn(dev, "create mkey failed\n"); 851 mlx5_ib_warn(dev, "create mkey failed\n");
766 goto err_2; 852 goto err_2;
@@ -944,7 +1030,8 @@ struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd,
944 * TBD not needed - issue 197292 */ 1030 * TBD not needed - issue 197292 */
945 in->seg.log2_page_size = PAGE_SHIFT; 1031 in->seg.log2_page_size = PAGE_SHIFT;
946 1032
947 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in)); 1033 err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in), NULL,
1034 NULL, NULL);
948 kfree(in); 1035 kfree(in);
949 if (err) 1036 if (err)
950 goto err_free; 1037 goto err_free;