aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtemy Kovalyov <artemyko@mellanox.com>2017-01-18 09:58:10 -0500
committerDoug Ledford <dledford@redhat.com>2017-02-14 11:41:18 -0500
commit49780d42dfc9ec0f4090c32ca59688449da1a1cd (patch)
tree17e4d73dc7665786268c4ad3afefa91b85ea7504
parent94990b498969b420949a04294618f9509466b896 (diff)
IB/mlx5: Expose MR cache for mlx5_ib
Allow other parts of mlx5_ib to use MR cache mechanism. * Add new functions mlx5_mr_cache_alloc and mlx5_mr_cache_free * Traditional MTT MKey buckets are limited by MAX_UMR_CACHE_ENTRY Additinal buckets may be added above. Signed-off-by: Artemy Kovalyov <artemyko@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h9
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c99
-rw-r--r--include/linux/mlx5/driver.h3
3 files changed, 82 insertions, 29 deletions
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 13bef19649f2..efc44de3c7d7 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -541,6 +541,10 @@ struct mlx5_cache_ent {
541 struct dentry *dir; 541 struct dentry *dir;
542 char name[4]; 542 char name[4];
543 u32 order; 543 u32 order;
544 u32 xlt;
545 u32 access_mode;
546 u32 page;
547
544 u32 size; 548 u32 size;
545 u32 cur; 549 u32 cur;
546 u32 miss; 550 u32 miss;
@@ -555,6 +559,7 @@ struct mlx5_cache_ent {
555 struct work_struct work; 559 struct work_struct work;
556 struct delayed_work dwork; 560 struct delayed_work dwork;
557 int pending; 561 int pending;
562 struct completion compl;
558}; 563};
559 564
560struct mlx5_mr_cache { 565struct mlx5_mr_cache {
@@ -837,7 +842,9 @@ void mlx5_ib_copy_pas(u64 *old, u64 *new, int step, int num);
837int mlx5_ib_get_cqe_size(struct mlx5_ib_dev *dev, struct ib_cq *ibcq); 842int mlx5_ib_get_cqe_size(struct mlx5_ib_dev *dev, struct ib_cq *ibcq);
838int mlx5_mr_cache_init(struct mlx5_ib_dev *dev); 843int mlx5_mr_cache_init(struct mlx5_ib_dev *dev);
839int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev); 844int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev);
840int mlx5_mr_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift); 845
846struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev, int entry);
847void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
841int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask, 848int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
842 struct ib_mr_status *mr_status); 849 struct ib_mr_status *mr_status);
843struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd, 850struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 8cf2a67f9fb0..8f5b94d483e4 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -49,6 +49,7 @@ enum {
49 49
50static int clean_mr(struct mlx5_ib_mr *mr); 50static int clean_mr(struct mlx5_ib_mr *mr);
51static int use_umr(struct mlx5_ib_dev *dev, int order); 51static int use_umr(struct mlx5_ib_dev *dev, int order);
52static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
52 53
53static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) 54static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
54{ 55{
@@ -149,6 +150,9 @@ static void reg_mr_callback(int status, void *context)
149 if (err) 150 if (err)
150 pr_err("Error inserting to mkey tree. 0x%x\n", -err); 151 pr_err("Error inserting to mkey tree. 0x%x\n", -err);
151 write_unlock_irqrestore(&table->lock, flags); 152 write_unlock_irqrestore(&table->lock, flags);
153
154 if (!completion_done(&ent->compl))
155 complete(&ent->compl);
152} 156}
153 157
154static int add_keys(struct mlx5_ib_dev *dev, int c, int num) 158static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
@@ -157,7 +161,6 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
157 struct mlx5_cache_ent *ent = &cache->ent[c]; 161 struct mlx5_cache_ent *ent = &cache->ent[c];
158 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in); 162 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
159 struct mlx5_ib_mr *mr; 163 struct mlx5_ib_mr *mr;
160 int npages = 1 << ent->order;
161 void *mkc; 164 void *mkc;
162 u32 *in; 165 u32 *in;
163 int err = 0; 166 int err = 0;
@@ -185,11 +188,11 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
185 188
186 MLX5_SET(mkc, mkc, free, 1); 189 MLX5_SET(mkc, mkc, free, 1);
187 MLX5_SET(mkc, mkc, umr_en, 1); 190 MLX5_SET(mkc, mkc, umr_en, 1);
188 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT); 191 MLX5_SET(mkc, mkc, access_mode, ent->access_mode);
189 192
190 MLX5_SET(mkc, mkc, qpn, 0xffffff); 193 MLX5_SET(mkc, mkc, qpn, 0xffffff);
191 MLX5_SET(mkc, mkc, translations_octword_size, (npages + 1) / 2); 194 MLX5_SET(mkc, mkc, translations_octword_size, ent->xlt);
192 MLX5_SET(mkc, mkc, log_page_size, 12); 195 MLX5_SET(mkc, mkc, log_page_size, ent->page);
193 196
194 spin_lock_irq(&ent->lock); 197 spin_lock_irq(&ent->lock);
195 ent->pending++; 198 ent->pending++;
@@ -447,6 +450,42 @@ static void cache_work_func(struct work_struct *work)
447 __cache_work_func(ent); 450 __cache_work_func(ent);
448} 451}
449 452
453struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev, int entry)
454{
455 struct mlx5_mr_cache *cache = &dev->cache;
456 struct mlx5_cache_ent *ent;
457 struct mlx5_ib_mr *mr;
458 int err;
459
460 if (entry < 0 || entry >= MAX_MR_CACHE_ENTRIES) {
461 mlx5_ib_err(dev, "cache entry %d is out of range\n", entry);
462 return NULL;
463 }
464
465 ent = &cache->ent[entry];
466 while (1) {
467 spin_lock_irq(&ent->lock);
468 if (list_empty(&ent->head)) {
469 spin_unlock_irq(&ent->lock);
470
471 err = add_keys(dev, entry, 1);
472 if (err)
473 return ERR_PTR(err);
474
475 wait_for_completion(&ent->compl);
476 } else {
477 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
478 list);
479 list_del(&mr->list);
480 ent->cur--;
481 spin_unlock_irq(&ent->lock);
482 if (ent->cur < ent->limit)
483 queue_work(cache->wq, &ent->work);
484 return mr;
485 }
486 }
487}
488
450static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order) 489static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
451{ 490{
452 struct mlx5_mr_cache *cache = &dev->cache; 491 struct mlx5_mr_cache *cache = &dev->cache;
@@ -456,12 +495,12 @@ static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
456 int i; 495 int i;
457 496
458 c = order2idx(dev, order); 497 c = order2idx(dev, order);
459 if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) { 498 if (c < 0 || c > MAX_UMR_CACHE_ENTRY) {
460 mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c); 499 mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
461 return NULL; 500 return NULL;
462 } 501 }
463 502
464 for (i = c; i < MAX_MR_CACHE_ENTRIES; i++) { 503 for (i = c; i < MAX_UMR_CACHE_ENTRY; i++) {
465 ent = &cache->ent[i]; 504 ent = &cache->ent[i];
466 505
467 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i); 506 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
@@ -488,7 +527,7 @@ static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
488 return mr; 527 return mr;
489} 528}
490 529
491static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) 530void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
492{ 531{
493 struct mlx5_mr_cache *cache = &dev->cache; 532 struct mlx5_mr_cache *cache = &dev->cache;
494 struct mlx5_cache_ent *ent; 533 struct mlx5_cache_ent *ent;
@@ -500,6 +539,10 @@ static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
500 mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c); 539 mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c);
501 return; 540 return;
502 } 541 }
542
543 if (unreg_umr(dev, mr))
544 return;
545
503 ent = &cache->ent[c]; 546 ent = &cache->ent[c];
504 spin_lock_irq(&ent->lock); 547 spin_lock_irq(&ent->lock);
505 list_add_tail(&mr->list, &ent->head); 548 list_add_tail(&mr->list, &ent->head);
@@ -602,7 +645,6 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
602{ 645{
603 struct mlx5_mr_cache *cache = &dev->cache; 646 struct mlx5_mr_cache *cache = &dev->cache;
604 struct mlx5_cache_ent *ent; 647 struct mlx5_cache_ent *ent;
605 int limit;
606 int err; 648 int err;
607 int i; 649 int i;
608 650
@@ -615,26 +657,33 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
615 657
616 setup_timer(&dev->delay_timer, delay_time_func, (unsigned long)dev); 658 setup_timer(&dev->delay_timer, delay_time_func, (unsigned long)dev);
617 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { 659 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
618 INIT_LIST_HEAD(&cache->ent[i].head);
619 spin_lock_init(&cache->ent[i].lock);
620
621 ent = &cache->ent[i]; 660 ent = &cache->ent[i];
622 INIT_LIST_HEAD(&ent->head); 661 INIT_LIST_HEAD(&ent->head);
623 spin_lock_init(&ent->lock); 662 spin_lock_init(&ent->lock);
624 ent->order = i + 2; 663 ent->order = i + 2;
625 ent->dev = dev; 664 ent->dev = dev;
665 ent->limit = 0;
626 666
627 if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) && 667 init_completion(&ent->compl);
628 mlx5_core_is_pf(dev->mdev) &&
629 use_umr(dev, ent->order))
630 limit = dev->mdev->profile->mr_cache[i].limit;
631 else
632 limit = 0;
633
634 INIT_WORK(&ent->work, cache_work_func); 668 INIT_WORK(&ent->work, cache_work_func);
635 INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func); 669 INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func);
636 ent->limit = limit;
637 queue_work(cache->wq, &ent->work); 670 queue_work(cache->wq, &ent->work);
671
672 if (i > MAX_UMR_CACHE_ENTRY)
673 continue;
674
675 if (!use_umr(dev, ent->order))
676 continue;
677
678 ent->page = PAGE_SHIFT;
679 ent->xlt = (1 << ent->order) * sizeof(struct mlx5_mtt) /
680 MLX5_IB_UMR_OCTOWORD;
681 ent->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
682 if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
683 mlx5_core_is_pf(dev->mdev))
684 ent->limit = dev->mdev->profile->mr_cache[i].limit;
685 else
686 ent->limit = 0;
638 } 687 }
639 688
640 err = mlx5_mr_cache_debugfs_init(dev); 689 err = mlx5_mr_cache_debugfs_init(dev);
@@ -758,7 +807,7 @@ static int get_octo_len(u64 addr, u64 len, int page_size)
758static int use_umr(struct mlx5_ib_dev *dev, int order) 807static int use_umr(struct mlx5_ib_dev *dev, int order)
759{ 808{
760 if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) 809 if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
761 return order < MAX_MR_CACHE_ENTRIES + 2; 810 return order <= MAX_UMR_CACHE_ENTRY + 2;
762 return order <= MLX5_MAX_UMR_SHIFT; 811 return order <= MLX5_MAX_UMR_SHIFT;
763} 812}
764 813
@@ -871,7 +920,7 @@ static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
871 MLX5_IB_UPD_XLT_ENABLE); 920 MLX5_IB_UPD_XLT_ENABLE);
872 921
873 if (err) { 922 if (err) {
874 free_cached_mr(dev, mr); 923 mlx5_mr_cache_free(dev, mr);
875 return ERR_PTR(err); 924 return ERR_PTR(err);
876 } 925 }
877 926
@@ -1091,6 +1140,7 @@ static struct mlx5_ib_mr *reg_create(struct ib_mr *ibmr, struct ib_pd *pd,
1091 goto err_2; 1140 goto err_2;
1092 } 1141 }
1093 mr->mmkey.type = MLX5_MKEY_MR; 1142 mr->mmkey.type = MLX5_MKEY_MR;
1143 mr->desc_size = sizeof(struct mlx5_mtt);
1094 mr->umem = umem; 1144 mr->umem = umem;
1095 mr->dev = dev; 1145 mr->dev = dev;
1096 mr->live = 1; 1146 mr->live = 1;
@@ -1398,12 +1448,7 @@ static int clean_mr(struct mlx5_ib_mr *mr)
1398 return err; 1448 return err;
1399 } 1449 }
1400 } else { 1450 } else {
1401 err = unreg_umr(dev, mr); 1451 mlx5_mr_cache_free(dev, mr);
1402 if (err) {
1403 mlx5_ib_warn(dev, "failed unregister\n");
1404 return err;
1405 }
1406 free_cached_mr(dev, mr);
1407 } 1452 }
1408 1453
1409 if (!umred) 1454 if (!umred)
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index b8d69aeb1784..2534b8a0fd7b 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1052,7 +1052,8 @@ enum {
1052}; 1052};
1053 1053
1054enum { 1054enum {
1055 MAX_MR_CACHE_ENTRIES = 21, 1055 MAX_UMR_CACHE_ENTRY = 20,
1056 MAX_MR_CACHE_ENTRIES
1056}; 1057};
1057 1058
1058enum { 1059enum {