blob: f4ecc10cbbba53a90ef015dc86490e97f8573c08 [file] [log] [blame]
Eli Cohene126ba92013-07-07 17:25:49 +03001/*
Saeed Mahameed6cf0a152015-04-02 17:07:30 +03002 * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
Eli Cohene126ba92013-07-07 17:25:49 +03003 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33
34#include <linux/kref.h>
35#include <linux/random.h>
36#include <linux/debugfs.h>
37#include <linux/export.h>
Eli Cohen746b5582013-10-23 09:53:14 +030038#include <linux/delay.h>
Eli Cohene126ba92013-07-07 17:25:49 +030039#include <rdma/ib_umem.h>
Haggai Eranb4cfe442014-12-11 17:04:26 +020040#include <rdma/ib_umem_odp.h>
Haggai Eran968e78d2014-12-11 17:04:11 +020041#include <rdma/ib_verbs.h>
Eli Cohene126ba92013-07-07 17:25:49 +030042#include "mlx5_ib.h"
43
44enum {
Eli Cohen746b5582013-10-23 09:53:14 +030045 MAX_PENDING_REG_MR = 8,
Eli Cohene126ba92013-07-07 17:25:49 +030046};
47
Haggai Eran832a6b02014-12-11 17:04:22 +020048#define MLX5_UMR_ALIGN 2048
Eli Cohenfe45f822013-09-11 16:35:35 +030049
Haggai Eran6aec21f2014-12-11 17:04:23 +020050static int clean_mr(struct mlx5_ib_mr *mr);
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +020051static int use_umr(struct mlx5_ib_dev *dev, int order);
Haggai Eran6aec21f2014-12-11 17:04:23 +020052
Haggai Eranb4cfe442014-12-11 17:04:26 +020053static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
54{
Matan Baraka606b0f2016-02-29 18:05:28 +020055 int err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
Haggai Eranb4cfe442014-12-11 17:04:26 +020056
57#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
58 /* Wait until all page fault handlers using the mr complete. */
59 synchronize_srcu(&dev->mr_srcu);
60#endif
61
62 return err;
63}
64
Eli Cohene126ba92013-07-07 17:25:49 +030065static int order2idx(struct mlx5_ib_dev *dev, int order)
66{
67 struct mlx5_mr_cache *cache = &dev->cache;
68
69 if (order < cache->ent[0].order)
70 return 0;
71 else
72 return order - cache->ent[0].order;
73}
74
Noa Osherovich56e11d62016-02-29 16:46:51 +020075static bool use_umr_mtt_update(struct mlx5_ib_mr *mr, u64 start, u64 length)
76{
77 return ((u64)1 << mr->order) * MLX5_ADAPTER_PAGE_SIZE >=
78 length + (start & (MLX5_ADAPTER_PAGE_SIZE - 1));
79}
80
Noa Osherovich395a8e42016-02-29 16:46:50 +020081#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
82static void update_odp_mr(struct mlx5_ib_mr *mr)
83{
84 if (mr->umem->odp_data) {
85 /*
86 * This barrier prevents the compiler from moving the
87 * setting of umem->odp_data->private to point to our
88 * MR, before reg_umr finished, to ensure that the MR
89 * initialization have finished before starting to
90 * handle invalidations.
91 */
92 smp_wmb();
93 mr->umem->odp_data->private = mr;
94 /*
95 * Make sure we will see the new
96 * umem->odp_data->private value in the invalidation
97 * routines, before we can get page faults on the
98 * MR. Page faults can happen once we put the MR in
99 * the tree, below this line. Without the barrier,
100 * there can be a fault handling and an invalidation
101 * before umem->odp_data->private == mr is visible to
102 * the invalidation handler.
103 */
104 smp_wmb();
105 }
106}
107#endif
108
Eli Cohen746b5582013-10-23 09:53:14 +0300109static void reg_mr_callback(int status, void *context)
110{
111 struct mlx5_ib_mr *mr = context;
112 struct mlx5_ib_dev *dev = mr->dev;
113 struct mlx5_mr_cache *cache = &dev->cache;
114 int c = order2idx(dev, mr->order);
115 struct mlx5_cache_ent *ent = &cache->ent[c];
116 u8 key;
Eli Cohen746b5582013-10-23 09:53:14 +0300117 unsigned long flags;
Matan Baraka606b0f2016-02-29 18:05:28 +0200118 struct mlx5_mkey_table *table = &dev->mdev->priv.mkey_table;
Haggai Eran86059332014-05-22 14:50:09 +0300119 int err;
Eli Cohen746b5582013-10-23 09:53:14 +0300120
Eli Cohen746b5582013-10-23 09:53:14 +0300121 spin_lock_irqsave(&ent->lock, flags);
122 ent->pending--;
123 spin_unlock_irqrestore(&ent->lock, flags);
124 if (status) {
125 mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
126 kfree(mr);
127 dev->fill_delay = 1;
128 mod_timer(&dev->delay_timer, jiffies + HZ);
129 return;
130 }
131
Jack Morgenstein9603b612014-07-28 23:30:22 +0300132 spin_lock_irqsave(&dev->mdev->priv.mkey_lock, flags);
133 key = dev->mdev->priv.mkey_key++;
134 spin_unlock_irqrestore(&dev->mdev->priv.mkey_lock, flags);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300135 mr->mmkey.key = mlx5_idx_to_mkey(MLX5_GET(create_mkey_out, mr->out, mkey_index)) | key;
Eli Cohen746b5582013-10-23 09:53:14 +0300136
137 cache->last_add = jiffies;
138
139 spin_lock_irqsave(&ent->lock, flags);
140 list_add_tail(&mr->list, &ent->head);
141 ent->cur++;
142 ent->size++;
143 spin_unlock_irqrestore(&ent->lock, flags);
Haggai Eran86059332014-05-22 14:50:09 +0300144
145 write_lock_irqsave(&table->lock, flags);
Matan Baraka606b0f2016-02-29 18:05:28 +0200146 err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->mmkey.key),
147 &mr->mmkey);
Haggai Eran86059332014-05-22 14:50:09 +0300148 if (err)
Matan Baraka606b0f2016-02-29 18:05:28 +0200149 pr_err("Error inserting to mkey tree. 0x%x\n", -err);
Haggai Eran86059332014-05-22 14:50:09 +0300150 write_unlock_irqrestore(&table->lock, flags);
Eli Cohen746b5582013-10-23 09:53:14 +0300151}
152
Eli Cohene126ba92013-07-07 17:25:49 +0300153static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
154{
Eli Cohene126ba92013-07-07 17:25:49 +0300155 struct mlx5_mr_cache *cache = &dev->cache;
156 struct mlx5_cache_ent *ent = &cache->ent[c];
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300157 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Eli Cohene126ba92013-07-07 17:25:49 +0300158 struct mlx5_ib_mr *mr;
159 int npages = 1 << ent->order;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300160 void *mkc;
161 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300162 int err = 0;
163 int i;
164
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300165 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300166 if (!in)
167 return -ENOMEM;
168
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300169 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300170 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300171 if (ent->pending >= MAX_PENDING_REG_MR) {
172 err = -EAGAIN;
173 break;
174 }
175
Eli Cohene126ba92013-07-07 17:25:49 +0300176 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
177 if (!mr) {
178 err = -ENOMEM;
Eli Cohen746b5582013-10-23 09:53:14 +0300179 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300180 }
181 mr->order = ent->order;
182 mr->umred = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300183 mr->dev = dev;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300184
185 MLX5_SET(mkc, mkc, free, 1);
186 MLX5_SET(mkc, mkc, umr_en, 1);
187 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
188
189 MLX5_SET(mkc, mkc, qpn, 0xffffff);
190 MLX5_SET(mkc, mkc, translations_octword_size, (npages + 1) / 2);
191 MLX5_SET(mkc, mkc, log_page_size, 12);
Eli Cohene126ba92013-07-07 17:25:49 +0300192
Eli Cohen746b5582013-10-23 09:53:14 +0300193 spin_lock_irq(&ent->lock);
194 ent->pending++;
195 spin_unlock_irq(&ent->lock);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300196 err = mlx5_core_create_mkey_cb(dev->mdev, &mr->mmkey,
197 in, inlen,
198 mr->out, sizeof(mr->out),
199 reg_mr_callback, mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300200 if (err) {
Eli Cohend14e7112014-12-02 12:26:19 +0200201 spin_lock_irq(&ent->lock);
202 ent->pending--;
203 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300204 mlx5_ib_warn(dev, "create mkey failed %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300205 kfree(mr);
Eli Cohen746b5582013-10-23 09:53:14 +0300206 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300207 }
Eli Cohene126ba92013-07-07 17:25:49 +0300208 }
209
Eli Cohene126ba92013-07-07 17:25:49 +0300210 kfree(in);
211 return err;
212}
213
214static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
215{
Eli Cohene126ba92013-07-07 17:25:49 +0300216 struct mlx5_mr_cache *cache = &dev->cache;
217 struct mlx5_cache_ent *ent = &cache->ent[c];
218 struct mlx5_ib_mr *mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300219 int err;
220 int i;
221
222 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300223 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300224 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300225 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300226 return;
227 }
228 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
229 list_del(&mr->list);
230 ent->cur--;
231 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300232 spin_unlock_irq(&ent->lock);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200233 err = destroy_mkey(dev, mr);
Eli Cohen203099f2013-09-11 16:35:26 +0300234 if (err)
Eli Cohene126ba92013-07-07 17:25:49 +0300235 mlx5_ib_warn(dev, "failed destroy mkey\n");
Eli Cohen203099f2013-09-11 16:35:26 +0300236 else
Eli Cohene126ba92013-07-07 17:25:49 +0300237 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300238 }
239}
240
241static ssize_t size_write(struct file *filp, const char __user *buf,
242 size_t count, loff_t *pos)
243{
244 struct mlx5_cache_ent *ent = filp->private_data;
245 struct mlx5_ib_dev *dev = ent->dev;
246 char lbuf[20];
247 u32 var;
248 int err;
249 int c;
250
251 if (copy_from_user(lbuf, buf, sizeof(lbuf)))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300252 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300253
254 c = order2idx(dev, ent->order);
255 lbuf[sizeof(lbuf) - 1] = 0;
256
257 if (sscanf(lbuf, "%u", &var) != 1)
258 return -EINVAL;
259
260 if (var < ent->limit)
261 return -EINVAL;
262
263 if (var > ent->size) {
Eli Cohen746b5582013-10-23 09:53:14 +0300264 do {
265 err = add_keys(dev, c, var - ent->size);
266 if (err && err != -EAGAIN)
267 return err;
268
269 usleep_range(3000, 5000);
270 } while (err);
Eli Cohene126ba92013-07-07 17:25:49 +0300271 } else if (var < ent->size) {
272 remove_keys(dev, c, ent->size - var);
273 }
274
275 return count;
276}
277
278static ssize_t size_read(struct file *filp, char __user *buf, size_t count,
279 loff_t *pos)
280{
281 struct mlx5_cache_ent *ent = filp->private_data;
282 char lbuf[20];
283 int err;
284
285 if (*pos)
286 return 0;
287
288 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->size);
289 if (err < 0)
290 return err;
291
292 if (copy_to_user(buf, lbuf, err))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300293 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300294
295 *pos += err;
296
297 return err;
298}
299
300static const struct file_operations size_fops = {
301 .owner = THIS_MODULE,
302 .open = simple_open,
303 .write = size_write,
304 .read = size_read,
305};
306
307static ssize_t limit_write(struct file *filp, const char __user *buf,
308 size_t count, loff_t *pos)
309{
310 struct mlx5_cache_ent *ent = filp->private_data;
311 struct mlx5_ib_dev *dev = ent->dev;
312 char lbuf[20];
313 u32 var;
314 int err;
315 int c;
316
317 if (copy_from_user(lbuf, buf, sizeof(lbuf)))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300318 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300319
320 c = order2idx(dev, ent->order);
321 lbuf[sizeof(lbuf) - 1] = 0;
322
323 if (sscanf(lbuf, "%u", &var) != 1)
324 return -EINVAL;
325
326 if (var > ent->size)
327 return -EINVAL;
328
329 ent->limit = var;
330
331 if (ent->cur < ent->limit) {
332 err = add_keys(dev, c, 2 * ent->limit - ent->cur);
333 if (err)
334 return err;
335 }
336
337 return count;
338}
339
340static ssize_t limit_read(struct file *filp, char __user *buf, size_t count,
341 loff_t *pos)
342{
343 struct mlx5_cache_ent *ent = filp->private_data;
344 char lbuf[20];
345 int err;
346
347 if (*pos)
348 return 0;
349
350 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->limit);
351 if (err < 0)
352 return err;
353
354 if (copy_to_user(buf, lbuf, err))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300355 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300356
357 *pos += err;
358
359 return err;
360}
361
362static const struct file_operations limit_fops = {
363 .owner = THIS_MODULE,
364 .open = simple_open,
365 .write = limit_write,
366 .read = limit_read,
367};
368
369static int someone_adding(struct mlx5_mr_cache *cache)
370{
371 int i;
372
373 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
374 if (cache->ent[i].cur < cache->ent[i].limit)
375 return 1;
376 }
377
378 return 0;
379}
380
381static void __cache_work_func(struct mlx5_cache_ent *ent)
382{
383 struct mlx5_ib_dev *dev = ent->dev;
384 struct mlx5_mr_cache *cache = &dev->cache;
385 int i = order2idx(dev, ent->order);
Eli Cohen746b5582013-10-23 09:53:14 +0300386 int err;
Eli Cohene126ba92013-07-07 17:25:49 +0300387
388 if (cache->stopped)
389 return;
390
391 ent = &dev->cache.ent[i];
Eli Cohen746b5582013-10-23 09:53:14 +0300392 if (ent->cur < 2 * ent->limit && !dev->fill_delay) {
393 err = add_keys(dev, i, 1);
394 if (ent->cur < 2 * ent->limit) {
395 if (err == -EAGAIN) {
396 mlx5_ib_dbg(dev, "returned eagain, order %d\n",
397 i + 2);
398 queue_delayed_work(cache->wq, &ent->dwork,
399 msecs_to_jiffies(3));
400 } else if (err) {
401 mlx5_ib_warn(dev, "command failed order %d, err %d\n",
402 i + 2, err);
403 queue_delayed_work(cache->wq, &ent->dwork,
404 msecs_to_jiffies(1000));
405 } else {
406 queue_work(cache->wq, &ent->work);
407 }
408 }
Eli Cohene126ba92013-07-07 17:25:49 +0300409 } else if (ent->cur > 2 * ent->limit) {
Leon Romanovskyab5cdc32015-10-21 09:21:17 +0300410 /*
411 * The remove_keys() logic is performed as garbage collection
412 * task. Such task is intended to be run when no other active
413 * processes are running.
414 *
415 * The need_resched() will return TRUE if there are user tasks
416 * to be activated in near future.
417 *
418 * In such case, we don't execute remove_keys() and postpone
419 * the garbage collection work to try to run in next cycle,
420 * in order to free CPU resources to other tasks.
421 */
422 if (!need_resched() && !someone_adding(cache) &&
Eli Cohen746b5582013-10-23 09:53:14 +0300423 time_after(jiffies, cache->last_add + 300 * HZ)) {
Eli Cohene126ba92013-07-07 17:25:49 +0300424 remove_keys(dev, i, 1);
425 if (ent->cur > ent->limit)
426 queue_work(cache->wq, &ent->work);
427 } else {
Eli Cohen746b5582013-10-23 09:53:14 +0300428 queue_delayed_work(cache->wq, &ent->dwork, 300 * HZ);
Eli Cohene126ba92013-07-07 17:25:49 +0300429 }
430 }
431}
432
433static void delayed_cache_work_func(struct work_struct *work)
434{
435 struct mlx5_cache_ent *ent;
436
437 ent = container_of(work, struct mlx5_cache_ent, dwork.work);
438 __cache_work_func(ent);
439}
440
441static void cache_work_func(struct work_struct *work)
442{
443 struct mlx5_cache_ent *ent;
444
445 ent = container_of(work, struct mlx5_cache_ent, work);
446 __cache_work_func(ent);
447}
448
449static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
450{
451 struct mlx5_mr_cache *cache = &dev->cache;
452 struct mlx5_ib_mr *mr = NULL;
453 struct mlx5_cache_ent *ent;
454 int c;
455 int i;
456
457 c = order2idx(dev, order);
458 if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
459 mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
460 return NULL;
461 }
462
463 for (i = c; i < MAX_MR_CACHE_ENTRIES; i++) {
464 ent = &cache->ent[i];
465
466 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
467
Eli Cohen746b5582013-10-23 09:53:14 +0300468 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300469 if (!list_empty(&ent->head)) {
470 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
471 list);
472 list_del(&mr->list);
473 ent->cur--;
Eli Cohen746b5582013-10-23 09:53:14 +0300474 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300475 if (ent->cur < ent->limit)
476 queue_work(cache->wq, &ent->work);
477 break;
478 }
Eli Cohen746b5582013-10-23 09:53:14 +0300479 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300480
481 queue_work(cache->wq, &ent->work);
Eli Cohene126ba92013-07-07 17:25:49 +0300482 }
483
484 if (!mr)
485 cache->ent[c].miss++;
486
487 return mr;
488}
489
490static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
491{
492 struct mlx5_mr_cache *cache = &dev->cache;
493 struct mlx5_cache_ent *ent;
494 int shrink = 0;
495 int c;
496
497 c = order2idx(dev, mr->order);
498 if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
499 mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c);
500 return;
501 }
502 ent = &cache->ent[c];
Eli Cohen746b5582013-10-23 09:53:14 +0300503 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300504 list_add_tail(&mr->list, &ent->head);
505 ent->cur++;
506 if (ent->cur > 2 * ent->limit)
507 shrink = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300508 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300509
510 if (shrink)
511 queue_work(cache->wq, &ent->work);
512}
513
514static void clean_keys(struct mlx5_ib_dev *dev, int c)
515{
Eli Cohene126ba92013-07-07 17:25:49 +0300516 struct mlx5_mr_cache *cache = &dev->cache;
517 struct mlx5_cache_ent *ent = &cache->ent[c];
518 struct mlx5_ib_mr *mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300519 int err;
520
Moshe Lazer3c461912013-09-11 16:35:23 +0300521 cancel_delayed_work(&ent->dwork);
Eli Cohene126ba92013-07-07 17:25:49 +0300522 while (1) {
Eli Cohen746b5582013-10-23 09:53:14 +0300523 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300524 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300525 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300526 return;
527 }
528 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
529 list_del(&mr->list);
530 ent->cur--;
531 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300532 spin_unlock_irq(&ent->lock);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200533 err = destroy_mkey(dev, mr);
Eli Cohen203099f2013-09-11 16:35:26 +0300534 if (err)
Eli Cohene126ba92013-07-07 17:25:49 +0300535 mlx5_ib_warn(dev, "failed destroy mkey\n");
Eli Cohen203099f2013-09-11 16:35:26 +0300536 else
Eli Cohene126ba92013-07-07 17:25:49 +0300537 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300538 }
539}
540
541static int mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev)
542{
543 struct mlx5_mr_cache *cache = &dev->cache;
544 struct mlx5_cache_ent *ent;
545 int i;
546
547 if (!mlx5_debugfs_root)
548 return 0;
549
Jack Morgenstein9603b612014-07-28 23:30:22 +0300550 cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
Eli Cohene126ba92013-07-07 17:25:49 +0300551 if (!cache->root)
552 return -ENOMEM;
553
554 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
555 ent = &cache->ent[i];
556 sprintf(ent->name, "%d", ent->order);
557 ent->dir = debugfs_create_dir(ent->name, cache->root);
558 if (!ent->dir)
559 return -ENOMEM;
560
561 ent->fsize = debugfs_create_file("size", 0600, ent->dir, ent,
562 &size_fops);
563 if (!ent->fsize)
564 return -ENOMEM;
565
566 ent->flimit = debugfs_create_file("limit", 0600, ent->dir, ent,
567 &limit_fops);
568 if (!ent->flimit)
569 return -ENOMEM;
570
571 ent->fcur = debugfs_create_u32("cur", 0400, ent->dir,
572 &ent->cur);
573 if (!ent->fcur)
574 return -ENOMEM;
575
576 ent->fmiss = debugfs_create_u32("miss", 0600, ent->dir,
577 &ent->miss);
578 if (!ent->fmiss)
579 return -ENOMEM;
580 }
581
582 return 0;
583}
584
585static void mlx5_mr_cache_debugfs_cleanup(struct mlx5_ib_dev *dev)
586{
587 if (!mlx5_debugfs_root)
588 return;
589
590 debugfs_remove_recursive(dev->cache.root);
591}
592
Eli Cohen746b5582013-10-23 09:53:14 +0300593static void delay_time_func(unsigned long ctx)
594{
595 struct mlx5_ib_dev *dev = (struct mlx5_ib_dev *)ctx;
596
597 dev->fill_delay = 0;
598}
599
Eli Cohene126ba92013-07-07 17:25:49 +0300600int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
601{
602 struct mlx5_mr_cache *cache = &dev->cache;
603 struct mlx5_cache_ent *ent;
604 int limit;
Eli Cohene126ba92013-07-07 17:25:49 +0300605 int err;
606 int i;
607
Moshe Lazer6bc1a652016-10-27 16:36:42 +0300608 mutex_init(&dev->slow_path_mutex);
Bhaktipriya Shridhar3c856c82016-08-15 23:41:18 +0530609 cache->wq = alloc_ordered_workqueue("mkey_cache", WQ_MEM_RECLAIM);
Eli Cohene126ba92013-07-07 17:25:49 +0300610 if (!cache->wq) {
611 mlx5_ib_warn(dev, "failed to create work queue\n");
612 return -ENOMEM;
613 }
614
Eli Cohen746b5582013-10-23 09:53:14 +0300615 setup_timer(&dev->delay_timer, delay_time_func, (unsigned long)dev);
Eli Cohene126ba92013-07-07 17:25:49 +0300616 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
617 INIT_LIST_HEAD(&cache->ent[i].head);
618 spin_lock_init(&cache->ent[i].lock);
619
620 ent = &cache->ent[i];
621 INIT_LIST_HEAD(&ent->head);
622 spin_lock_init(&ent->lock);
623 ent->order = i + 2;
624 ent->dev = dev;
625
Eli Cohenafd02cd2016-11-27 15:18:21 +0200626 if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200627 mlx5_core_is_pf(dev->mdev) &&
628 use_umr(dev, ent->order))
Jack Morgenstein9603b612014-07-28 23:30:22 +0300629 limit = dev->mdev->profile->mr_cache[i].limit;
Eli Cohen2d036fa2013-10-24 12:01:00 +0300630 else
Eli Cohene126ba92013-07-07 17:25:49 +0300631 limit = 0;
Eli Cohen2d036fa2013-10-24 12:01:00 +0300632
Eli Cohene126ba92013-07-07 17:25:49 +0300633 INIT_WORK(&ent->work, cache_work_func);
634 INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func);
635 ent->limit = limit;
636 queue_work(cache->wq, &ent->work);
637 }
638
639 err = mlx5_mr_cache_debugfs_init(dev);
640 if (err)
641 mlx5_ib_warn(dev, "cache debugfs failure\n");
642
643 return 0;
644}
645
Eli Cohenacbda522016-10-27 16:36:43 +0300646static void wait_for_async_commands(struct mlx5_ib_dev *dev)
647{
648 struct mlx5_mr_cache *cache = &dev->cache;
649 struct mlx5_cache_ent *ent;
650 int total = 0;
651 int i;
652 int j;
653
654 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
655 ent = &cache->ent[i];
656 for (j = 0 ; j < 1000; j++) {
657 if (!ent->pending)
658 break;
659 msleep(50);
660 }
661 }
662 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
663 ent = &cache->ent[i];
664 total += ent->pending;
665 }
666
667 if (total)
668 mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total);
669 else
670 mlx5_ib_warn(dev, "done with all pending requests\n");
671}
672
Eli Cohene126ba92013-07-07 17:25:49 +0300673int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
674{
675 int i;
676
677 dev->cache.stopped = 1;
Moshe Lazer3c461912013-09-11 16:35:23 +0300678 flush_workqueue(dev->cache.wq);
Eli Cohene126ba92013-07-07 17:25:49 +0300679
680 mlx5_mr_cache_debugfs_cleanup(dev);
681
682 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
683 clean_keys(dev, i);
684
Moshe Lazer3c461912013-09-11 16:35:23 +0300685 destroy_workqueue(dev->cache.wq);
Eli Cohenacbda522016-10-27 16:36:43 +0300686 wait_for_async_commands(dev);
Eli Cohen746b5582013-10-23 09:53:14 +0300687 del_timer_sync(&dev->delay_timer);
Moshe Lazer3c461912013-09-11 16:35:23 +0300688
Eli Cohene126ba92013-07-07 17:25:49 +0300689 return 0;
690}
691
692struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
693{
694 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300695 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Jack Morgenstein9603b612014-07-28 23:30:22 +0300696 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +0300697 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300698 void *mkc;
699 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300700 int err;
701
702 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
703 if (!mr)
704 return ERR_PTR(-ENOMEM);
705
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300706 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300707 if (!in) {
708 err = -ENOMEM;
709 goto err_free;
710 }
711
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300712 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300713
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300714 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_PA);
715 MLX5_SET(mkc, mkc, a, !!(acc & IB_ACCESS_REMOTE_ATOMIC));
716 MLX5_SET(mkc, mkc, rw, !!(acc & IB_ACCESS_REMOTE_WRITE));
717 MLX5_SET(mkc, mkc, rr, !!(acc & IB_ACCESS_REMOTE_READ));
718 MLX5_SET(mkc, mkc, lw, !!(acc & IB_ACCESS_LOCAL_WRITE));
719 MLX5_SET(mkc, mkc, lr, 1);
720
721 MLX5_SET(mkc, mkc, length64, 1);
722 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
723 MLX5_SET(mkc, mkc, qpn, 0xffffff);
724 MLX5_SET64(mkc, mkc, start_addr, 0);
725
726 err = mlx5_core_create_mkey(mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +0300727 if (err)
728 goto err_in;
729
730 kfree(in);
Matan Baraka606b0f2016-02-29 18:05:28 +0200731 mr->ibmr.lkey = mr->mmkey.key;
732 mr->ibmr.rkey = mr->mmkey.key;
Eli Cohene126ba92013-07-07 17:25:49 +0300733 mr->umem = NULL;
734
735 return &mr->ibmr;
736
737err_in:
738 kfree(in);
739
740err_free:
741 kfree(mr);
742
743 return ERR_PTR(err);
744}
745
746static int get_octo_len(u64 addr, u64 len, int page_size)
747{
748 u64 offset;
749 int npages;
750
751 offset = addr & (page_size - 1);
752 npages = ALIGN(len + offset, page_size) >> ilog2(page_size);
753 return (npages + 1) / 2;
754}
755
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200756static int use_umr(struct mlx5_ib_dev *dev, int order)
Eli Cohene126ba92013-07-07 17:25:49 +0300757{
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200758 if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
759 return order < MAX_MR_CACHE_ENTRIES + 2;
Haggai Erancc149f752014-12-11 17:04:21 +0200760 return order <= MLX5_MAX_UMR_SHIFT;
Eli Cohene126ba92013-07-07 17:25:49 +0300761}
762
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200763static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
764 int access_flags, struct ib_umem **umem,
765 int *npages, int *page_shift, int *ncont,
766 int *order)
Noa Osherovich395a8e42016-02-29 16:46:50 +0200767{
768 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200769 int err;
770
771 *umem = ib_umem_get(pd->uobject->context, start, length,
772 access_flags, 0);
773 err = PTR_ERR_OR_ZERO(*umem);
774 if (err < 0) {
Noa Osherovich395a8e42016-02-29 16:46:50 +0200775 mlx5_ib_err(dev, "umem get failed (%ld)\n", PTR_ERR(umem));
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200776 return err;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200777 }
778
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200779 mlx5_ib_cont_pages(*umem, start, MLX5_MKEY_PAGE_SHIFT_MASK, npages,
Majd Dibbiny762f8992016-10-27 16:36:47 +0300780 page_shift, ncont, order);
Noa Osherovich395a8e42016-02-29 16:46:50 +0200781 if (!*npages) {
782 mlx5_ib_warn(dev, "avoid zero region\n");
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200783 ib_umem_release(*umem);
784 return -EINVAL;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200785 }
786
787 mlx5_ib_dbg(dev, "npages %d, ncont %d, order %d, page_shift %d\n",
788 *npages, *ncont, *order, *page_shift);
789
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200790 return 0;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200791}
792
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100793static void mlx5_ib_umr_done(struct ib_cq *cq, struct ib_wc *wc)
Eli Cohene126ba92013-07-07 17:25:49 +0300794{
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100795 struct mlx5_ib_umr_context *context =
796 container_of(wc->wr_cqe, struct mlx5_ib_umr_context, cqe);
Eli Cohene126ba92013-07-07 17:25:49 +0300797
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100798 context->status = wc->status;
799 complete(&context->done);
800}
Eli Cohene126ba92013-07-07 17:25:49 +0300801
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100802static inline void mlx5_ib_init_umr_context(struct mlx5_ib_umr_context *context)
803{
804 context->cqe.done = mlx5_ib_umr_done;
805 context->status = -1;
806 init_completion(&context->done);
Eli Cohene126ba92013-07-07 17:25:49 +0300807}
808
Binoy Jayand5ea2df2017-01-02 11:37:40 +0200809static int mlx5_ib_post_send_wait(struct mlx5_ib_dev *dev,
810 struct mlx5_umr_wr *umrwr)
811{
812 struct umr_common *umrc = &dev->umrc;
813 struct ib_send_wr *bad;
814 int err;
815 struct mlx5_ib_umr_context umr_context;
816
817 mlx5_ib_init_umr_context(&umr_context);
818 umrwr->wr.wr_cqe = &umr_context.cqe;
819
820 down(&umrc->sem);
821 err = ib_post_send(umrc->qp, &umrwr->wr, &bad);
822 if (err) {
823 mlx5_ib_warn(dev, "UMR post send failed, err %d\n", err);
824 } else {
825 wait_for_completion(&umr_context.done);
826 if (umr_context.status != IB_WC_SUCCESS) {
827 mlx5_ib_warn(dev, "reg umr failed (%u)\n",
828 umr_context.status);
829 err = -EFAULT;
830 }
831 }
832 up(&umrc->sem);
833 return err;
834}
835
Eli Cohene126ba92013-07-07 17:25:49 +0300836static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
837 u64 virt_addr, u64 len, int npages,
838 int page_shift, int order, int access_flags)
839{
840 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +0300841 struct mlx5_ib_mr *mr;
Haggai Eran096f7e72014-05-22 14:50:08 +0300842 int err = 0;
Eli Cohene126ba92013-07-07 17:25:49 +0300843 int i;
844
Eli Cohen746b5582013-10-23 09:53:14 +0300845 for (i = 0; i < 1; i++) {
Eli Cohene126ba92013-07-07 17:25:49 +0300846 mr = alloc_cached_mr(dev, order);
847 if (mr)
848 break;
849
850 err = add_keys(dev, order2idx(dev, order), 1);
Eli Cohen746b5582013-10-23 09:53:14 +0300851 if (err && err != -EAGAIN) {
852 mlx5_ib_warn(dev, "add_keys failed, err %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300853 break;
854 }
855 }
856
857 if (!mr)
858 return ERR_PTR(-EAGAIN);
859
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200860 mr->ibmr.pd = pd;
861 mr->umem = umem;
862 mr->access_flags = access_flags;
863 mr->desc_size = sizeof(struct mlx5_mtt);
Matan Baraka606b0f2016-02-29 18:05:28 +0200864 mr->mmkey.iova = virt_addr;
865 mr->mmkey.size = len;
866 mr->mmkey.pd = to_mpd(pd)->pdn;
Haggai Eranb4755982014-05-22 14:50:10 +0300867
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200868 err = mlx5_ib_update_xlt(mr, 0, npages, page_shift,
869 MLX5_IB_UPD_XLT_ENABLE);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200870
Haggai Eran096f7e72014-05-22 14:50:08 +0300871 if (err) {
872 free_cached_mr(dev, mr);
873 return ERR_PTR(err);
Eli Cohene126ba92013-07-07 17:25:49 +0300874 }
875
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200876 mr->live = 1;
877
Eli Cohene126ba92013-07-07 17:25:49 +0300878 return mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300879}
880
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200881static inline int populate_xlt(struct mlx5_ib_mr *mr, int idx, int npages,
882 void *xlt, int page_shift, size_t size,
883 int flags)
884{
885 struct mlx5_ib_dev *dev = mr->dev;
886 struct ib_umem *umem = mr->umem;
887
888 npages = min_t(size_t, npages, ib_umem_num_pages(umem) - idx);
889
890 if (!(flags & MLX5_IB_UPD_XLT_ZAP)) {
891 __mlx5_ib_populate_pas(dev, umem, page_shift,
892 idx, npages, xlt,
893 MLX5_IB_MTT_PRESENT);
894 /* Clear padding after the pages
895 * brought from the umem.
896 */
897 memset(xlt + (npages * sizeof(struct mlx5_mtt)), 0,
898 size - npages * sizeof(struct mlx5_mtt));
899 }
900
901 return npages;
902}
903
904#define MLX5_MAX_UMR_CHUNK ((1 << (MLX5_MAX_UMR_SHIFT + 4)) - \
905 MLX5_UMR_MTT_ALIGNMENT)
906#define MLX5_SPARE_UMR_CHUNK 0x10000
907
908int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
909 int page_shift, int flags)
Haggai Eran832a6b02014-12-11 17:04:22 +0200910{
911 struct mlx5_ib_dev *dev = mr->dev;
912 struct device *ddev = dev->ib_dev.dma_device;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200913 struct mlx5_ib_ucontext *uctx = NULL;
Haggai Eran832a6b02014-12-11 17:04:22 +0200914 int size;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200915 void *xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200916 dma_addr_t dma;
Christoph Hellwige622f2f2015-10-08 09:16:33 +0100917 struct mlx5_umr_wr wr;
Haggai Eran832a6b02014-12-11 17:04:22 +0200918 struct ib_sge sg;
919 int err = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200920 int desc_size = sizeof(struct mlx5_mtt);
921 const int page_align = MLX5_UMR_MTT_ALIGNMENT / desc_size;
922 const int page_mask = page_align - 1;
Haggai Eran832a6b02014-12-11 17:04:22 +0200923 size_t pages_mapped = 0;
924 size_t pages_to_map = 0;
925 size_t pages_iter = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200926 gfp_t gfp;
Haggai Eran832a6b02014-12-11 17:04:22 +0200927
928 /* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes,
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200929 * so we need to align the offset and length accordingly
930 */
931 if (idx & page_mask) {
932 npages += idx & page_mask;
933 idx &= ~page_mask;
Haggai Eran832a6b02014-12-11 17:04:22 +0200934 }
935
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200936 gfp = flags & MLX5_IB_UPD_XLT_ATOMIC ? GFP_ATOMIC : GFP_KERNEL;
937 gfp |= __GFP_ZERO | __GFP_NOWARN;
Haggai Eran832a6b02014-12-11 17:04:22 +0200938
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200939 pages_to_map = ALIGN(npages, page_align);
940 size = desc_size * pages_to_map;
941 size = min_t(int, size, MLX5_MAX_UMR_CHUNK);
Haggai Eran832a6b02014-12-11 17:04:22 +0200942
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200943 xlt = (void *)__get_free_pages(gfp, get_order(size));
944 if (!xlt && size > MLX5_SPARE_UMR_CHUNK) {
945 mlx5_ib_dbg(dev, "Failed to allocate %d bytes of order %d. fallback to spare UMR allocation od %d bytes\n",
946 size, get_order(size), MLX5_SPARE_UMR_CHUNK);
947
948 size = MLX5_SPARE_UMR_CHUNK;
949 xlt = (void *)__get_free_pages(gfp, get_order(size));
Haggai Eran832a6b02014-12-11 17:04:22 +0200950 }
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200951
952 if (!xlt) {
953 uctx = to_mucontext(mr->ibmr.uobject->context);
954 mlx5_ib_warn(dev, "Using XLT emergency buffer\n");
955 size = PAGE_SIZE;
956 xlt = (void *)uctx->upd_xlt_page;
957 mutex_lock(&uctx->upd_xlt_page_mutex);
958 memset(xlt, 0, size);
959 }
960 pages_iter = size / desc_size;
961 dma = dma_map_single(ddev, xlt, size, DMA_TO_DEVICE);
Haggai Eran832a6b02014-12-11 17:04:22 +0200962 if (dma_mapping_error(ddev, dma)) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200963 mlx5_ib_err(dev, "unable to map DMA during XLT update.\n");
Haggai Eran832a6b02014-12-11 17:04:22 +0200964 err = -ENOMEM;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200965 goto free_xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200966 }
967
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200968 sg.addr = dma;
969 sg.lkey = dev->umrc.pd->local_dma_lkey;
970
971 memset(&wr, 0, sizeof(wr));
972 wr.wr.send_flags = MLX5_IB_SEND_UMR_UPDATE_XLT;
973 if (!(flags & MLX5_IB_UPD_XLT_ENABLE))
974 wr.wr.send_flags |= MLX5_IB_SEND_UMR_FAIL_IF_FREE;
975 wr.wr.sg_list = &sg;
976 wr.wr.num_sge = 1;
977 wr.wr.opcode = MLX5_IB_WR_UMR;
978
979 wr.pd = mr->ibmr.pd;
980 wr.mkey = mr->mmkey.key;
981 wr.length = mr->mmkey.size;
982 wr.virt_addr = mr->mmkey.iova;
983 wr.access_flags = mr->access_flags;
984 wr.page_shift = page_shift;
985
Haggai Eran832a6b02014-12-11 17:04:22 +0200986 for (pages_mapped = 0;
987 pages_mapped < pages_to_map && !err;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200988 pages_mapped += pages_iter, idx += pages_iter) {
Haggai Eran832a6b02014-12-11 17:04:22 +0200989 dma_sync_single_for_cpu(ddev, dma, size, DMA_TO_DEVICE);
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200990 npages = populate_xlt(mr, idx, pages_iter, xlt,
991 page_shift, size, flags);
Haggai Eran832a6b02014-12-11 17:04:22 +0200992
993 dma_sync_single_for_device(ddev, dma, size, DMA_TO_DEVICE);
994
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200995 sg.length = ALIGN(npages * desc_size,
996 MLX5_UMR_MTT_ALIGNMENT);
Haggai Eran832a6b02014-12-11 17:04:22 +0200997
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200998 if (pages_mapped + pages_iter >= pages_to_map) {
999 if (flags & MLX5_IB_UPD_XLT_ENABLE)
1000 wr.wr.send_flags |=
1001 MLX5_IB_SEND_UMR_ENABLE_MR |
1002 MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS |
1003 MLX5_IB_SEND_UMR_UPDATE_TRANSLATION;
1004 if (flags & MLX5_IB_UPD_XLT_PD ||
1005 flags & MLX5_IB_UPD_XLT_ACCESS)
1006 wr.wr.send_flags |=
1007 MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
1008 if (flags & MLX5_IB_UPD_XLT_ADDR)
1009 wr.wr.send_flags |=
1010 MLX5_IB_SEND_UMR_UPDATE_TRANSLATION;
1011 }
Haggai Eran832a6b02014-12-11 17:04:22 +02001012
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001013 wr.offset = idx * desc_size;
Artemy Kovalyov31616252017-01-02 11:37:42 +02001014 wr.xlt_size = sg.length;
Haggai Eran832a6b02014-12-11 17:04:22 +02001015
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001016 err = mlx5_ib_post_send_wait(dev, &wr);
Haggai Eran832a6b02014-12-11 17:04:22 +02001017 }
1018 dma_unmap_single(ddev, dma, size, DMA_TO_DEVICE);
1019
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001020free_xlt:
1021 if (uctx)
1022 mutex_unlock(&uctx->upd_xlt_page_mutex);
Haggai Eran832a6b02014-12-11 17:04:22 +02001023 else
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001024 free_pages((unsigned long)xlt, get_order(size));
Haggai Eran832a6b02014-12-11 17:04:22 +02001025
1026 return err;
1027}
Haggai Eran832a6b02014-12-11 17:04:22 +02001028
Noa Osherovich395a8e42016-02-29 16:46:50 +02001029/*
1030 * If ibmr is NULL it will be allocated by reg_create.
1031 * Else, the given ibmr will be used.
1032 */
1033static struct mlx5_ib_mr *reg_create(struct ib_mr *ibmr, struct ib_pd *pd,
1034 u64 virt_addr, u64 length,
1035 struct ib_umem *umem, int npages,
1036 int page_shift, int access_flags)
Eli Cohene126ba92013-07-07 17:25:49 +03001037{
1038 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +03001039 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001040 __be64 *pas;
1041 void *mkc;
Eli Cohene126ba92013-07-07 17:25:49 +03001042 int inlen;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001043 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +03001044 int err;
Saeed Mahameed938fe832015-05-28 22:28:41 +03001045 bool pg_cap = !!(MLX5_CAP_GEN(dev->mdev, pg));
Eli Cohene126ba92013-07-07 17:25:49 +03001046
Noa Osherovich395a8e42016-02-29 16:46:50 +02001047 mr = ibmr ? to_mmr(ibmr) : kzalloc(sizeof(*mr), GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +03001048 if (!mr)
1049 return ERR_PTR(-ENOMEM);
1050
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001051 inlen = MLX5_ST_SZ_BYTES(create_mkey_in) +
1052 sizeof(*pas) * ((npages + 1) / 2) * 2;
Eli Cohene126ba92013-07-07 17:25:49 +03001053 in = mlx5_vzalloc(inlen);
1054 if (!in) {
1055 err = -ENOMEM;
1056 goto err_1;
1057 }
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001058 pas = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
Artemy Kovalyovc438fde2017-01-02 11:37:43 +02001059 if (!(access_flags & IB_ACCESS_ON_DEMAND))
1060 mlx5_ib_populate_pas(dev, umem, page_shift, pas,
1061 pg_cap ? MLX5_IB_MTT_PRESENT : 0);
Eli Cohene126ba92013-07-07 17:25:49 +03001062
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001063 /* The pg_access bit allows setting the access flags
Haggai Erancc149f752014-12-11 17:04:21 +02001064 * in the page list submitted with the command. */
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001065 MLX5_SET(create_mkey_in, in, pg_access, !!(pg_cap));
1066
1067 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1068 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
1069 MLX5_SET(mkc, mkc, a, !!(access_flags & IB_ACCESS_REMOTE_ATOMIC));
1070 MLX5_SET(mkc, mkc, rw, !!(access_flags & IB_ACCESS_REMOTE_WRITE));
1071 MLX5_SET(mkc, mkc, rr, !!(access_flags & IB_ACCESS_REMOTE_READ));
1072 MLX5_SET(mkc, mkc, lw, !!(access_flags & IB_ACCESS_LOCAL_WRITE));
1073 MLX5_SET(mkc, mkc, lr, 1);
1074
1075 MLX5_SET64(mkc, mkc, start_addr, virt_addr);
1076 MLX5_SET64(mkc, mkc, len, length);
1077 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1078 MLX5_SET(mkc, mkc, bsf_octword_size, 0);
1079 MLX5_SET(mkc, mkc, translations_octword_size,
1080 get_octo_len(virt_addr, length, 1 << page_shift));
1081 MLX5_SET(mkc, mkc, log_page_size, page_shift);
1082 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1083 MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
1084 get_octo_len(virt_addr, length, 1 << page_shift));
1085
1086 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +03001087 if (err) {
1088 mlx5_ib_warn(dev, "create mkey failed\n");
1089 goto err_2;
1090 }
1091 mr->umem = umem;
Majd Dibbiny7eae20d2015-01-06 13:56:01 +02001092 mr->dev = dev;
Haggai Eranb4cfe442014-12-11 17:04:26 +02001093 mr->live = 1;
Al Viro479163f2014-11-20 08:13:57 +00001094 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001095
Matan Baraka606b0f2016-02-29 18:05:28 +02001096 mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001097
1098 return mr;
1099
1100err_2:
Al Viro479163f2014-11-20 08:13:57 +00001101 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001102
1103err_1:
Noa Osherovich395a8e42016-02-29 16:46:50 +02001104 if (!ibmr)
1105 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +03001106
1107 return ERR_PTR(err);
1108}
1109
Noa Osherovich395a8e42016-02-29 16:46:50 +02001110static void set_mr_fileds(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
1111 int npages, u64 length, int access_flags)
1112{
1113 mr->npages = npages;
1114 atomic_add(npages, &dev->mdev->priv.reg_pages);
Matan Baraka606b0f2016-02-29 18:05:28 +02001115 mr->ibmr.lkey = mr->mmkey.key;
1116 mr->ibmr.rkey = mr->mmkey.key;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001117 mr->ibmr.length = length;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001118 mr->access_flags = access_flags;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001119}
1120
Eli Cohene126ba92013-07-07 17:25:49 +03001121struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
1122 u64 virt_addr, int access_flags,
1123 struct ib_udata *udata)
1124{
1125 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1126 struct mlx5_ib_mr *mr = NULL;
1127 struct ib_umem *umem;
1128 int page_shift;
1129 int npages;
1130 int ncont;
1131 int order;
1132 int err;
1133
Eli Cohen900a6d72014-09-14 16:47:51 +03001134 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1135 start, virt_addr, length, access_flags);
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001136 err = mr_umem_get(pd, start, length, access_flags, &umem, &npages,
Noa Osherovich395a8e42016-02-29 16:46:50 +02001137 &page_shift, &ncont, &order);
1138
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001139 if (err < 0)
1140 return ERR_PTR(err);
Eli Cohene126ba92013-07-07 17:25:49 +03001141
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001142 if (use_umr(dev, order)) {
Eli Cohene126ba92013-07-07 17:25:49 +03001143 mr = reg_umr(pd, umem, virt_addr, length, ncont, page_shift,
1144 order, access_flags);
1145 if (PTR_ERR(mr) == -EAGAIN) {
1146 mlx5_ib_dbg(dev, "cache empty for order %d", order);
1147 mr = NULL;
1148 }
Artemy Kovalyovc438fde2017-01-02 11:37:43 +02001149 } else if (access_flags & IB_ACCESS_ON_DEMAND &&
1150 !MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
Haggai Eran6aec21f2014-12-11 17:04:23 +02001151 err = -EINVAL;
1152 pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB");
1153 goto error;
Eli Cohene126ba92013-07-07 17:25:49 +03001154 }
1155
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001156 if (!mr) {
1157 mutex_lock(&dev->slow_path_mutex);
Noa Osherovich395a8e42016-02-29 16:46:50 +02001158 mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
1159 page_shift, access_flags);
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001160 mutex_unlock(&dev->slow_path_mutex);
1161 }
Eli Cohene126ba92013-07-07 17:25:49 +03001162
1163 if (IS_ERR(mr)) {
1164 err = PTR_ERR(mr);
1165 goto error;
1166 }
1167
Matan Baraka606b0f2016-02-29 18:05:28 +02001168 mlx5_ib_dbg(dev, "mkey 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001169
1170 mr->umem = umem;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001171 set_mr_fileds(dev, mr, npages, length, access_flags);
Eli Cohene126ba92013-07-07 17:25:49 +03001172
Haggai Eranb4cfe442014-12-11 17:04:26 +02001173#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Noa Osherovich395a8e42016-02-29 16:46:50 +02001174 update_odp_mr(mr);
Haggai Eranb4cfe442014-12-11 17:04:26 +02001175#endif
1176
Eli Cohene126ba92013-07-07 17:25:49 +03001177 return &mr->ibmr;
1178
1179error:
1180 ib_umem_release(umem);
1181 return ERR_PTR(err);
1182}
1183
1184static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
1185{
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03001186 struct mlx5_core_dev *mdev = dev->mdev;
Doug Ledford0025b0b2016-03-03 11:23:37 -05001187 struct mlx5_umr_wr umrwr = {};
Eli Cohene126ba92013-07-07 17:25:49 +03001188
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03001189 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
1190 return 0;
1191
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001192 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_DISABLE_MR |
1193 MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1194 umrwr.wr.opcode = MLX5_IB_WR_UMR;
1195 umrwr.mkey = mr->mmkey.key;
Eli Cohene126ba92013-07-07 17:25:49 +03001196
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001197 return mlx5_ib_post_send_wait(dev, &umrwr);
Eli Cohene126ba92013-07-07 17:25:49 +03001198}
1199
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001200static int rereg_umr(struct ib_pd *pd, struct mlx5_ib_mr *mr,
Noa Osherovich56e11d62016-02-29 16:46:51 +02001201 int access_flags, int flags)
1202{
1203 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001204 struct mlx5_umr_wr umrwr = {};
Noa Osherovich56e11d62016-02-29 16:46:51 +02001205 int err;
1206
Noa Osherovich56e11d62016-02-29 16:46:51 +02001207 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1208
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001209 umrwr.wr.opcode = MLX5_IB_WR_UMR;
1210 umrwr.mkey = mr->mmkey.key;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001211
Artemy Kovalyov31616252017-01-02 11:37:42 +02001212 if (flags & IB_MR_REREG_PD || flags & IB_MR_REREG_ACCESS) {
Noa Osherovich56e11d62016-02-29 16:46:51 +02001213 umrwr.pd = pd;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001214 umrwr.access_flags = access_flags;
Artemy Kovalyov31616252017-01-02 11:37:42 +02001215 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001216 }
1217
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001218 err = mlx5_ib_post_send_wait(dev, &umrwr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001219
Noa Osherovich56e11d62016-02-29 16:46:51 +02001220 return err;
1221}
1222
1223int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
1224 u64 length, u64 virt_addr, int new_access_flags,
1225 struct ib_pd *new_pd, struct ib_udata *udata)
1226{
1227 struct mlx5_ib_dev *dev = to_mdev(ib_mr->device);
1228 struct mlx5_ib_mr *mr = to_mmr(ib_mr);
1229 struct ib_pd *pd = (flags & IB_MR_REREG_PD) ? new_pd : ib_mr->pd;
1230 int access_flags = flags & IB_MR_REREG_ACCESS ?
1231 new_access_flags :
1232 mr->access_flags;
1233 u64 addr = (flags & IB_MR_REREG_TRANS) ? virt_addr : mr->umem->address;
1234 u64 len = (flags & IB_MR_REREG_TRANS) ? length : mr->umem->length;
1235 int page_shift = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001236 int upd_flags = 0;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001237 int npages = 0;
1238 int ncont = 0;
1239 int order = 0;
1240 int err;
1241
1242 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1243 start, virt_addr, length, access_flags);
1244
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001245 atomic_sub(mr->npages, &dev->mdev->priv.reg_pages);
1246
Noa Osherovich56e11d62016-02-29 16:46:51 +02001247 if (flags != IB_MR_REREG_PD) {
1248 /*
1249 * Replace umem. This needs to be done whether or not UMR is
1250 * used.
1251 */
1252 flags |= IB_MR_REREG_TRANS;
1253 ib_umem_release(mr->umem);
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001254 err = mr_umem_get(pd, addr, len, access_flags, &mr->umem,
1255 &npages, &page_shift, &ncont, &order);
1256 if (err < 0) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001257 clean_mr(mr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001258 return err;
1259 }
1260 }
1261
1262 if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
1263 /*
1264 * UMR can't be used - MKey needs to be replaced.
1265 */
1266 if (mr->umred) {
1267 err = unreg_umr(dev, mr);
1268 if (err)
1269 mlx5_ib_warn(dev, "Failed to unregister MR\n");
1270 } else {
1271 err = destroy_mkey(dev, mr);
1272 if (err)
1273 mlx5_ib_warn(dev, "Failed to destroy MKey\n");
1274 }
1275 if (err)
1276 return err;
1277
1278 mr = reg_create(ib_mr, pd, addr, len, mr->umem, ncont,
1279 page_shift, access_flags);
1280
1281 if (IS_ERR(mr))
1282 return PTR_ERR(mr);
1283
1284 mr->umred = 0;
1285 } else {
1286 /*
1287 * Send a UMR WQE
1288 */
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001289 mr->ibmr.pd = pd;
1290 mr->access_flags = access_flags;
1291 mr->mmkey.iova = addr;
1292 mr->mmkey.size = len;
1293 mr->mmkey.pd = to_mpd(pd)->pdn;
1294
1295 if (flags & IB_MR_REREG_TRANS) {
1296 upd_flags = MLX5_IB_UPD_XLT_ADDR;
1297 if (flags & IB_MR_REREG_PD)
1298 upd_flags |= MLX5_IB_UPD_XLT_PD;
1299 if (flags & IB_MR_REREG_ACCESS)
1300 upd_flags |= MLX5_IB_UPD_XLT_ACCESS;
1301 err = mlx5_ib_update_xlt(mr, 0, npages, page_shift,
1302 upd_flags);
1303 } else {
1304 err = rereg_umr(pd, mr, access_flags, flags);
1305 }
1306
Noa Osherovich56e11d62016-02-29 16:46:51 +02001307 if (err) {
1308 mlx5_ib_warn(dev, "Failed to rereg UMR\n");
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001309 ib_umem_release(mr->umem);
1310 clean_mr(mr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001311 return err;
1312 }
1313 }
1314
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001315 set_mr_fileds(dev, mr, npages, len, access_flags);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001316
Noa Osherovich56e11d62016-02-29 16:46:51 +02001317#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
1318 update_odp_mr(mr);
1319#endif
Noa Osherovich56e11d62016-02-29 16:46:51 +02001320 return 0;
1321}
1322
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001323static int
1324mlx5_alloc_priv_descs(struct ib_device *device,
1325 struct mlx5_ib_mr *mr,
1326 int ndescs,
1327 int desc_size)
1328{
1329 int size = ndescs * desc_size;
1330 int add_size;
1331 int ret;
1332
1333 add_size = max_t(int, MLX5_UMR_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
1334
1335 mr->descs_alloc = kzalloc(size + add_size, GFP_KERNEL);
1336 if (!mr->descs_alloc)
1337 return -ENOMEM;
1338
1339 mr->descs = PTR_ALIGN(mr->descs_alloc, MLX5_UMR_ALIGN);
1340
1341 mr->desc_map = dma_map_single(device->dma_device, mr->descs,
1342 size, DMA_TO_DEVICE);
1343 if (dma_mapping_error(device->dma_device, mr->desc_map)) {
1344 ret = -ENOMEM;
1345 goto err;
1346 }
1347
1348 return 0;
1349err:
1350 kfree(mr->descs_alloc);
1351
1352 return ret;
1353}
1354
1355static void
1356mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
1357{
1358 if (mr->descs) {
1359 struct ib_device *device = mr->ibmr.device;
1360 int size = mr->max_descs * mr->desc_size;
1361
1362 dma_unmap_single(device->dma_device, mr->desc_map,
1363 size, DMA_TO_DEVICE);
1364 kfree(mr->descs_alloc);
1365 mr->descs = NULL;
1366 }
1367}
1368
Haggai Eran6aec21f2014-12-11 17:04:23 +02001369static int clean_mr(struct mlx5_ib_mr *mr)
Eli Cohene126ba92013-07-07 17:25:49 +03001370{
Haggai Eran6aec21f2014-12-11 17:04:23 +02001371 struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
Eli Cohene126ba92013-07-07 17:25:49 +03001372 int umred = mr->umred;
1373 int err;
1374
Sagi Grimberg8b91ffc2015-07-30 10:32:34 +03001375 if (mr->sig) {
1376 if (mlx5_core_destroy_psv(dev->mdev,
1377 mr->sig->psv_memory.psv_idx))
1378 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1379 mr->sig->psv_memory.psv_idx);
1380 if (mlx5_core_destroy_psv(dev->mdev,
1381 mr->sig->psv_wire.psv_idx))
1382 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1383 mr->sig->psv_wire.psv_idx);
1384 kfree(mr->sig);
1385 mr->sig = NULL;
1386 }
1387
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001388 mlx5_free_priv_descs(mr);
1389
Eli Cohene126ba92013-07-07 17:25:49 +03001390 if (!umred) {
Haggai Eranb4cfe442014-12-11 17:04:26 +02001391 err = destroy_mkey(dev, mr);
Eli Cohene126ba92013-07-07 17:25:49 +03001392 if (err) {
1393 mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
Matan Baraka606b0f2016-02-29 18:05:28 +02001394 mr->mmkey.key, err);
Eli Cohene126ba92013-07-07 17:25:49 +03001395 return err;
1396 }
1397 } else {
1398 err = unreg_umr(dev, mr);
1399 if (err) {
1400 mlx5_ib_warn(dev, "failed unregister\n");
1401 return err;
1402 }
1403 free_cached_mr(dev, mr);
1404 }
1405
Eli Cohene126ba92013-07-07 17:25:49 +03001406 if (!umred)
1407 kfree(mr);
1408
1409 return 0;
1410}
1411
Haggai Eran6aec21f2014-12-11 17:04:23 +02001412int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
1413{
1414 struct mlx5_ib_dev *dev = to_mdev(ibmr->device);
1415 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1416 int npages = mr->npages;
1417 struct ib_umem *umem = mr->umem;
1418
1419#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Haggai Eranb4cfe442014-12-11 17:04:26 +02001420 if (umem && umem->odp_data) {
1421 /* Prevent new page faults from succeeding */
1422 mr->live = 0;
Haggai Eran6aec21f2014-12-11 17:04:23 +02001423 /* Wait for all running page-fault handlers to finish. */
1424 synchronize_srcu(&dev->mr_srcu);
Haggai Eranb4cfe442014-12-11 17:04:26 +02001425 /* Destroy all page mappings */
1426 mlx5_ib_invalidate_range(umem, ib_umem_start(umem),
1427 ib_umem_end(umem));
1428 /*
1429 * We kill the umem before the MR for ODP,
1430 * so that there will not be any invalidations in
1431 * flight, looking at the *mr struct.
1432 */
1433 ib_umem_release(umem);
1434 atomic_sub(npages, &dev->mdev->priv.reg_pages);
1435
1436 /* Avoid double-freeing the umem. */
1437 umem = NULL;
1438 }
Haggai Eran6aec21f2014-12-11 17:04:23 +02001439#endif
1440
1441 clean_mr(mr);
1442
1443 if (umem) {
1444 ib_umem_release(umem);
1445 atomic_sub(npages, &dev->mdev->priv.reg_pages);
1446 }
1447
1448 return 0;
1449}
1450
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001451struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1452 enum ib_mr_type mr_type,
1453 u32 max_num_sg)
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001454{
1455 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001456 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001457 int ndescs = ALIGN(max_num_sg, 4);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001458 struct mlx5_ib_mr *mr;
1459 void *mkc;
1460 u32 *in;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001461 int err;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001462
1463 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1464 if (!mr)
1465 return ERR_PTR(-ENOMEM);
1466
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001467 in = kzalloc(inlen, GFP_KERNEL);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001468 if (!in) {
1469 err = -ENOMEM;
1470 goto err_free;
1471 }
1472
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001473 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1474 MLX5_SET(mkc, mkc, free, 1);
1475 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1476 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1477 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001478
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001479 if (mr_type == IB_MR_TYPE_MEM_REG) {
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001480 mr->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
1481 MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001482 err = mlx5_alloc_priv_descs(pd->device, mr,
Artemy Kovalyov31616252017-01-02 11:37:42 +02001483 ndescs, sizeof(struct mlx5_mtt));
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001484 if (err)
1485 goto err_free_in;
1486
Artemy Kovalyov31616252017-01-02 11:37:42 +02001487 mr->desc_size = sizeof(struct mlx5_mtt);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001488 mr->max_descs = ndescs;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001489 } else if (mr_type == IB_MR_TYPE_SG_GAPS) {
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001490 mr->access_mode = MLX5_MKC_ACCESS_MODE_KLMS;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001491
1492 err = mlx5_alloc_priv_descs(pd->device, mr,
1493 ndescs, sizeof(struct mlx5_klm));
1494 if (err)
1495 goto err_free_in;
1496 mr->desc_size = sizeof(struct mlx5_klm);
1497 mr->max_descs = ndescs;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001498 } else if (mr_type == IB_MR_TYPE_SIGNATURE) {
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001499 u32 psv_index[2];
1500
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001501 MLX5_SET(mkc, mkc, bsf_en, 1);
1502 MLX5_SET(mkc, mkc, bsf_octword_size, MLX5_MKEY_BSF_OCTO_SIZE);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001503 mr->sig = kzalloc(sizeof(*mr->sig), GFP_KERNEL);
1504 if (!mr->sig) {
1505 err = -ENOMEM;
1506 goto err_free_in;
1507 }
1508
1509 /* create mem & wire PSVs */
Jack Morgenstein9603b612014-07-28 23:30:22 +03001510 err = mlx5_core_create_psv(dev->mdev, to_mpd(pd)->pdn,
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001511 2, psv_index);
1512 if (err)
1513 goto err_free_sig;
1514
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001515 mr->access_mode = MLX5_MKC_ACCESS_MODE_KLMS;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001516 mr->sig->psv_memory.psv_idx = psv_index[0];
1517 mr->sig->psv_wire.psv_idx = psv_index[1];
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02001518
1519 mr->sig->sig_status_checked = true;
1520 mr->sig->sig_err_exists = false;
1521 /* Next UMR, Arm SIGERR */
1522 ++mr->sig->sigerr_count;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001523 } else {
1524 mlx5_ib_warn(dev, "Invalid mr type %d\n", mr_type);
1525 err = -EINVAL;
1526 goto err_free_in;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001527 }
1528
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001529 MLX5_SET(mkc, mkc, access_mode, mr->access_mode);
1530 MLX5_SET(mkc, mkc, umr_en, 1);
1531
1532 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001533 if (err)
1534 goto err_destroy_psv;
1535
Matan Baraka606b0f2016-02-29 18:05:28 +02001536 mr->ibmr.lkey = mr->mmkey.key;
1537 mr->ibmr.rkey = mr->mmkey.key;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001538 mr->umem = NULL;
1539 kfree(in);
1540
1541 return &mr->ibmr;
1542
1543err_destroy_psv:
1544 if (mr->sig) {
Jack Morgenstein9603b612014-07-28 23:30:22 +03001545 if (mlx5_core_destroy_psv(dev->mdev,
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001546 mr->sig->psv_memory.psv_idx))
1547 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1548 mr->sig->psv_memory.psv_idx);
Jack Morgenstein9603b612014-07-28 23:30:22 +03001549 if (mlx5_core_destroy_psv(dev->mdev,
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001550 mr->sig->psv_wire.psv_idx))
1551 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1552 mr->sig->psv_wire.psv_idx);
1553 }
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001554 mlx5_free_priv_descs(mr);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001555err_free_sig:
1556 kfree(mr->sig);
1557err_free_in:
1558 kfree(in);
1559err_free:
1560 kfree(mr);
1561 return ERR_PTR(err);
1562}
1563
Matan Barakd2370e02016-02-29 18:05:30 +02001564struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
1565 struct ib_udata *udata)
1566{
1567 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001568 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Matan Barakd2370e02016-02-29 18:05:30 +02001569 struct mlx5_ib_mw *mw = NULL;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001570 u32 *in = NULL;
1571 void *mkc;
Matan Barakd2370e02016-02-29 18:05:30 +02001572 int ndescs;
1573 int err;
1574 struct mlx5_ib_alloc_mw req = {};
1575 struct {
1576 __u32 comp_mask;
1577 __u32 response_length;
1578 } resp = {};
1579
1580 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
1581 if (err)
1582 return ERR_PTR(err);
1583
1584 if (req.comp_mask || req.reserved1 || req.reserved2)
1585 return ERR_PTR(-EOPNOTSUPP);
1586
1587 if (udata->inlen > sizeof(req) &&
1588 !ib_is_udata_cleared(udata, sizeof(req),
1589 udata->inlen - sizeof(req)))
1590 return ERR_PTR(-EOPNOTSUPP);
1591
1592 ndescs = req.num_klms ? roundup(req.num_klms, 4) : roundup(1, 4);
1593
1594 mw = kzalloc(sizeof(*mw), GFP_KERNEL);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001595 in = kzalloc(inlen, GFP_KERNEL);
Matan Barakd2370e02016-02-29 18:05:30 +02001596 if (!mw || !in) {
1597 err = -ENOMEM;
1598 goto free;
1599 }
1600
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001601 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Matan Barakd2370e02016-02-29 18:05:30 +02001602
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001603 MLX5_SET(mkc, mkc, free, 1);
1604 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1605 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1606 MLX5_SET(mkc, mkc, umr_en, 1);
1607 MLX5_SET(mkc, mkc, lr, 1);
1608 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_KLMS);
1609 MLX5_SET(mkc, mkc, en_rinval, !!((type == IB_MW_TYPE_2)));
1610 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1611
1612 err = mlx5_core_create_mkey(dev->mdev, &mw->mmkey, in, inlen);
Matan Barakd2370e02016-02-29 18:05:30 +02001613 if (err)
1614 goto free;
1615
1616 mw->ibmw.rkey = mw->mmkey.key;
1617
1618 resp.response_length = min(offsetof(typeof(resp), response_length) +
1619 sizeof(resp.response_length), udata->outlen);
1620 if (resp.response_length) {
1621 err = ib_copy_to_udata(udata, &resp, resp.response_length);
1622 if (err) {
1623 mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
1624 goto free;
1625 }
1626 }
1627
1628 kfree(in);
1629 return &mw->ibmw;
1630
1631free:
1632 kfree(mw);
1633 kfree(in);
1634 return ERR_PTR(err);
1635}
1636
1637int mlx5_ib_dealloc_mw(struct ib_mw *mw)
1638{
1639 struct mlx5_ib_mw *mmw = to_mmw(mw);
1640 int err;
1641
1642 err = mlx5_core_destroy_mkey((to_mdev(mw->device))->mdev,
1643 &mmw->mmkey);
1644 if (!err)
1645 kfree(mmw);
1646 return err;
1647}
1648
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02001649int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
1650 struct ib_mr_status *mr_status)
1651{
1652 struct mlx5_ib_mr *mmr = to_mmr(ibmr);
1653 int ret = 0;
1654
1655 if (check_mask & ~IB_MR_CHECK_SIG_STATUS) {
1656 pr_err("Invalid status check mask\n");
1657 ret = -EINVAL;
1658 goto done;
1659 }
1660
1661 mr_status->fail_status = 0;
1662 if (check_mask & IB_MR_CHECK_SIG_STATUS) {
1663 if (!mmr->sig) {
1664 ret = -EINVAL;
1665 pr_err("signature status check requested on a non-signature enabled MR\n");
1666 goto done;
1667 }
1668
1669 mmr->sig->sig_status_checked = true;
1670 if (!mmr->sig->sig_err_exists)
1671 goto done;
1672
1673 if (ibmr->lkey == mmr->sig->err_item.key)
1674 memcpy(&mr_status->sig_err, &mmr->sig->err_item,
1675 sizeof(mr_status->sig_err));
1676 else {
1677 mr_status->sig_err.err_type = IB_SIG_BAD_GUARD;
1678 mr_status->sig_err.sig_err_offset = 0;
1679 mr_status->sig_err.key = mmr->sig->err_item.key;
1680 }
1681
1682 mmr->sig->sig_err_exists = false;
1683 mr_status->fail_status |= IB_MR_CHECK_SIG_STATUS;
1684 }
1685
1686done:
1687 return ret;
1688}
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001689
Sagi Grimbergb005d312016-02-29 19:07:33 +02001690static int
1691mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr,
1692 struct scatterlist *sgl,
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001693 unsigned short sg_nents,
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001694 unsigned int *sg_offset_p)
Sagi Grimbergb005d312016-02-29 19:07:33 +02001695{
1696 struct scatterlist *sg = sgl;
1697 struct mlx5_klm *klms = mr->descs;
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001698 unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001699 u32 lkey = mr->ibmr.pd->local_dma_lkey;
1700 int i;
1701
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001702 mr->ibmr.iova = sg_dma_address(sg) + sg_offset;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001703 mr->ibmr.length = 0;
1704 mr->ndescs = sg_nents;
1705
1706 for_each_sg(sgl, sg, sg_nents, i) {
1707 if (unlikely(i > mr->max_descs))
1708 break;
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001709 klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset);
1710 klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001711 klms[i].key = cpu_to_be32(lkey);
1712 mr->ibmr.length += sg_dma_len(sg);
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001713
1714 sg_offset = 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001715 }
1716
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001717 if (sg_offset_p)
1718 *sg_offset_p = sg_offset;
1719
Sagi Grimbergb005d312016-02-29 19:07:33 +02001720 return i;
1721}
1722
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001723static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
1724{
1725 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1726 __be64 *descs;
1727
1728 if (unlikely(mr->ndescs == mr->max_descs))
1729 return -ENOMEM;
1730
1731 descs = mr->descs;
1732 descs[mr->ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
1733
1734 return 0;
1735}
1736
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001737int mlx5_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001738 unsigned int *sg_offset)
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001739{
1740 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1741 int n;
1742
1743 mr->ndescs = 0;
1744
1745 ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
1746 mr->desc_size * mr->max_descs,
1747 DMA_TO_DEVICE);
1748
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001749 if (mr->access_mode == MLX5_MKC_ACCESS_MODE_KLMS)
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001750 n = mlx5_ib_sg_to_klms(mr, sg, sg_nents, sg_offset);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001751 else
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001752 n = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset,
1753 mlx5_set_page);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001754
1755 ib_dma_sync_single_for_device(ibmr->device, mr->desc_map,
1756 mr->desc_size * mr->max_descs,
1757 DMA_TO_DEVICE);
1758
1759 return n;
1760}