blob: 8cf2a67f9fb0bad7bdbd201e7f359a859c782b80 [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
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +0200132 mr->mmkey.type = MLX5_MKEY_MR;
Jack Morgenstein9603b612014-07-28 23:30:22 +0300133 spin_lock_irqsave(&dev->mdev->priv.mkey_lock, flags);
134 key = dev->mdev->priv.mkey_key++;
135 spin_unlock_irqrestore(&dev->mdev->priv.mkey_lock, flags);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300136 mr->mmkey.key = mlx5_idx_to_mkey(MLX5_GET(create_mkey_out, mr->out, mkey_index)) | key;
Eli Cohen746b5582013-10-23 09:53:14 +0300137
138 cache->last_add = jiffies;
139
140 spin_lock_irqsave(&ent->lock, flags);
141 list_add_tail(&mr->list, &ent->head);
142 ent->cur++;
143 ent->size++;
144 spin_unlock_irqrestore(&ent->lock, flags);
Haggai Eran86059332014-05-22 14:50:09 +0300145
146 write_lock_irqsave(&table->lock, flags);
Matan Baraka606b0f2016-02-29 18:05:28 +0200147 err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->mmkey.key),
148 &mr->mmkey);
Haggai Eran86059332014-05-22 14:50:09 +0300149 if (err)
Matan Baraka606b0f2016-02-29 18:05:28 +0200150 pr_err("Error inserting to mkey tree. 0x%x\n", -err);
Haggai Eran86059332014-05-22 14:50:09 +0300151 write_unlock_irqrestore(&table->lock, flags);
Eli Cohen746b5582013-10-23 09:53:14 +0300152}
153
Eli Cohene126ba92013-07-07 17:25:49 +0300154static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
155{
Eli Cohene126ba92013-07-07 17:25:49 +0300156 struct mlx5_mr_cache *cache = &dev->cache;
157 struct mlx5_cache_ent *ent = &cache->ent[c];
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300158 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Eli Cohene126ba92013-07-07 17:25:49 +0300159 struct mlx5_ib_mr *mr;
160 int npages = 1 << ent->order;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300161 void *mkc;
162 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300163 int err = 0;
164 int i;
165
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300166 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300167 if (!in)
168 return -ENOMEM;
169
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300170 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300171 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300172 if (ent->pending >= MAX_PENDING_REG_MR) {
173 err = -EAGAIN;
174 break;
175 }
176
Eli Cohene126ba92013-07-07 17:25:49 +0300177 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
178 if (!mr) {
179 err = -ENOMEM;
Eli Cohen746b5582013-10-23 09:53:14 +0300180 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300181 }
182 mr->order = ent->order;
183 mr->umred = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300184 mr->dev = dev;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300185
186 MLX5_SET(mkc, mkc, free, 1);
187 MLX5_SET(mkc, mkc, umr_en, 1);
188 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
189
190 MLX5_SET(mkc, mkc, qpn, 0xffffff);
191 MLX5_SET(mkc, mkc, translations_octword_size, (npages + 1) / 2);
192 MLX5_SET(mkc, mkc, log_page_size, 12);
Eli Cohene126ba92013-07-07 17:25:49 +0300193
Eli Cohen746b5582013-10-23 09:53:14 +0300194 spin_lock_irq(&ent->lock);
195 ent->pending++;
196 spin_unlock_irq(&ent->lock);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300197 err = mlx5_core_create_mkey_cb(dev->mdev, &mr->mmkey,
198 in, inlen,
199 mr->out, sizeof(mr->out),
200 reg_mr_callback, mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300201 if (err) {
Eli Cohend14e7112014-12-02 12:26:19 +0200202 spin_lock_irq(&ent->lock);
203 ent->pending--;
204 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300205 mlx5_ib_warn(dev, "create mkey failed %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300206 kfree(mr);
Eli Cohen746b5582013-10-23 09:53:14 +0300207 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300208 }
Eli Cohene126ba92013-07-07 17:25:49 +0300209 }
210
Eli Cohene126ba92013-07-07 17:25:49 +0300211 kfree(in);
212 return err;
213}
214
215static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
216{
Eli Cohene126ba92013-07-07 17:25:49 +0300217 struct mlx5_mr_cache *cache = &dev->cache;
218 struct mlx5_cache_ent *ent = &cache->ent[c];
219 struct mlx5_ib_mr *mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300220 int err;
221 int i;
222
223 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300224 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300225 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300226 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300227 return;
228 }
229 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
230 list_del(&mr->list);
231 ent->cur--;
232 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300233 spin_unlock_irq(&ent->lock);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200234 err = destroy_mkey(dev, mr);
Eli Cohen203099f2013-09-11 16:35:26 +0300235 if (err)
Eli Cohene126ba92013-07-07 17:25:49 +0300236 mlx5_ib_warn(dev, "failed destroy mkey\n");
Eli Cohen203099f2013-09-11 16:35:26 +0300237 else
Eli Cohene126ba92013-07-07 17:25:49 +0300238 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300239 }
240}
241
242static ssize_t size_write(struct file *filp, const char __user *buf,
243 size_t count, loff_t *pos)
244{
245 struct mlx5_cache_ent *ent = filp->private_data;
246 struct mlx5_ib_dev *dev = ent->dev;
247 char lbuf[20];
248 u32 var;
249 int err;
250 int c;
251
252 if (copy_from_user(lbuf, buf, sizeof(lbuf)))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300253 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300254
255 c = order2idx(dev, ent->order);
256 lbuf[sizeof(lbuf) - 1] = 0;
257
258 if (sscanf(lbuf, "%u", &var) != 1)
259 return -EINVAL;
260
261 if (var < ent->limit)
262 return -EINVAL;
263
264 if (var > ent->size) {
Eli Cohen746b5582013-10-23 09:53:14 +0300265 do {
266 err = add_keys(dev, c, var - ent->size);
267 if (err && err != -EAGAIN)
268 return err;
269
270 usleep_range(3000, 5000);
271 } while (err);
Eli Cohene126ba92013-07-07 17:25:49 +0300272 } else if (var < ent->size) {
273 remove_keys(dev, c, ent->size - var);
274 }
275
276 return count;
277}
278
279static ssize_t size_read(struct file *filp, char __user *buf, size_t count,
280 loff_t *pos)
281{
282 struct mlx5_cache_ent *ent = filp->private_data;
283 char lbuf[20];
284 int err;
285
286 if (*pos)
287 return 0;
288
289 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->size);
290 if (err < 0)
291 return err;
292
293 if (copy_to_user(buf, lbuf, err))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300294 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300295
296 *pos += err;
297
298 return err;
299}
300
301static const struct file_operations size_fops = {
302 .owner = THIS_MODULE,
303 .open = simple_open,
304 .write = size_write,
305 .read = size_read,
306};
307
308static ssize_t limit_write(struct file *filp, const char __user *buf,
309 size_t count, loff_t *pos)
310{
311 struct mlx5_cache_ent *ent = filp->private_data;
312 struct mlx5_ib_dev *dev = ent->dev;
313 char lbuf[20];
314 u32 var;
315 int err;
316 int c;
317
318 if (copy_from_user(lbuf, buf, sizeof(lbuf)))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300319 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300320
321 c = order2idx(dev, ent->order);
322 lbuf[sizeof(lbuf) - 1] = 0;
323
324 if (sscanf(lbuf, "%u", &var) != 1)
325 return -EINVAL;
326
327 if (var > ent->size)
328 return -EINVAL;
329
330 ent->limit = var;
331
332 if (ent->cur < ent->limit) {
333 err = add_keys(dev, c, 2 * ent->limit - ent->cur);
334 if (err)
335 return err;
336 }
337
338 return count;
339}
340
341static ssize_t limit_read(struct file *filp, char __user *buf, size_t count,
342 loff_t *pos)
343{
344 struct mlx5_cache_ent *ent = filp->private_data;
345 char lbuf[20];
346 int err;
347
348 if (*pos)
349 return 0;
350
351 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->limit);
352 if (err < 0)
353 return err;
354
355 if (copy_to_user(buf, lbuf, err))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300356 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300357
358 *pos += err;
359
360 return err;
361}
362
363static const struct file_operations limit_fops = {
364 .owner = THIS_MODULE,
365 .open = simple_open,
366 .write = limit_write,
367 .read = limit_read,
368};
369
370static int someone_adding(struct mlx5_mr_cache *cache)
371{
372 int i;
373
374 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
375 if (cache->ent[i].cur < cache->ent[i].limit)
376 return 1;
377 }
378
379 return 0;
380}
381
382static void __cache_work_func(struct mlx5_cache_ent *ent)
383{
384 struct mlx5_ib_dev *dev = ent->dev;
385 struct mlx5_mr_cache *cache = &dev->cache;
386 int i = order2idx(dev, ent->order);
Eli Cohen746b5582013-10-23 09:53:14 +0300387 int err;
Eli Cohene126ba92013-07-07 17:25:49 +0300388
389 if (cache->stopped)
390 return;
391
392 ent = &dev->cache.ent[i];
Eli Cohen746b5582013-10-23 09:53:14 +0300393 if (ent->cur < 2 * ent->limit && !dev->fill_delay) {
394 err = add_keys(dev, i, 1);
395 if (ent->cur < 2 * ent->limit) {
396 if (err == -EAGAIN) {
397 mlx5_ib_dbg(dev, "returned eagain, order %d\n",
398 i + 2);
399 queue_delayed_work(cache->wq, &ent->dwork,
400 msecs_to_jiffies(3));
401 } else if (err) {
402 mlx5_ib_warn(dev, "command failed order %d, err %d\n",
403 i + 2, err);
404 queue_delayed_work(cache->wq, &ent->dwork,
405 msecs_to_jiffies(1000));
406 } else {
407 queue_work(cache->wq, &ent->work);
408 }
409 }
Eli Cohene126ba92013-07-07 17:25:49 +0300410 } else if (ent->cur > 2 * ent->limit) {
Leon Romanovskyab5cdc32015-10-21 09:21:17 +0300411 /*
412 * The remove_keys() logic is performed as garbage collection
413 * task. Such task is intended to be run when no other active
414 * processes are running.
415 *
416 * The need_resched() will return TRUE if there are user tasks
417 * to be activated in near future.
418 *
419 * In such case, we don't execute remove_keys() and postpone
420 * the garbage collection work to try to run in next cycle,
421 * in order to free CPU resources to other tasks.
422 */
423 if (!need_resched() && !someone_adding(cache) &&
Eli Cohen746b5582013-10-23 09:53:14 +0300424 time_after(jiffies, cache->last_add + 300 * HZ)) {
Eli Cohene126ba92013-07-07 17:25:49 +0300425 remove_keys(dev, i, 1);
426 if (ent->cur > ent->limit)
427 queue_work(cache->wq, &ent->work);
428 } else {
Eli Cohen746b5582013-10-23 09:53:14 +0300429 queue_delayed_work(cache->wq, &ent->dwork, 300 * HZ);
Eli Cohene126ba92013-07-07 17:25:49 +0300430 }
431 }
432}
433
434static void delayed_cache_work_func(struct work_struct *work)
435{
436 struct mlx5_cache_ent *ent;
437
438 ent = container_of(work, struct mlx5_cache_ent, dwork.work);
439 __cache_work_func(ent);
440}
441
442static void cache_work_func(struct work_struct *work)
443{
444 struct mlx5_cache_ent *ent;
445
446 ent = container_of(work, struct mlx5_cache_ent, work);
447 __cache_work_func(ent);
448}
449
450static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
451{
452 struct mlx5_mr_cache *cache = &dev->cache;
453 struct mlx5_ib_mr *mr = NULL;
454 struct mlx5_cache_ent *ent;
455 int c;
456 int i;
457
458 c = order2idx(dev, order);
459 if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
460 mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
461 return NULL;
462 }
463
464 for (i = c; i < MAX_MR_CACHE_ENTRIES; i++) {
465 ent = &cache->ent[i];
466
467 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
468
Eli Cohen746b5582013-10-23 09:53:14 +0300469 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300470 if (!list_empty(&ent->head)) {
471 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
472 list);
473 list_del(&mr->list);
474 ent->cur--;
Eli Cohen746b5582013-10-23 09:53:14 +0300475 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300476 if (ent->cur < ent->limit)
477 queue_work(cache->wq, &ent->work);
478 break;
479 }
Eli Cohen746b5582013-10-23 09:53:14 +0300480 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300481
482 queue_work(cache->wq, &ent->work);
Eli Cohene126ba92013-07-07 17:25:49 +0300483 }
484
485 if (!mr)
486 cache->ent[c].miss++;
487
488 return mr;
489}
490
491static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
492{
493 struct mlx5_mr_cache *cache = &dev->cache;
494 struct mlx5_cache_ent *ent;
495 int shrink = 0;
496 int c;
497
498 c = order2idx(dev, mr->order);
499 if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
500 mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c);
501 return;
502 }
503 ent = &cache->ent[c];
Eli Cohen746b5582013-10-23 09:53:14 +0300504 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300505 list_add_tail(&mr->list, &ent->head);
506 ent->cur++;
507 if (ent->cur > 2 * ent->limit)
508 shrink = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300509 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300510
511 if (shrink)
512 queue_work(cache->wq, &ent->work);
513}
514
515static void clean_keys(struct mlx5_ib_dev *dev, int c)
516{
Eli Cohene126ba92013-07-07 17:25:49 +0300517 struct mlx5_mr_cache *cache = &dev->cache;
518 struct mlx5_cache_ent *ent = &cache->ent[c];
519 struct mlx5_ib_mr *mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300520 int err;
521
Moshe Lazer3c461912013-09-11 16:35:23 +0300522 cancel_delayed_work(&ent->dwork);
Eli Cohene126ba92013-07-07 17:25:49 +0300523 while (1) {
Eli Cohen746b5582013-10-23 09:53:14 +0300524 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300525 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300526 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300527 return;
528 }
529 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
530 list_del(&mr->list);
531 ent->cur--;
532 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300533 spin_unlock_irq(&ent->lock);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200534 err = destroy_mkey(dev, mr);
Eli Cohen203099f2013-09-11 16:35:26 +0300535 if (err)
Eli Cohene126ba92013-07-07 17:25:49 +0300536 mlx5_ib_warn(dev, "failed destroy mkey\n");
Eli Cohen203099f2013-09-11 16:35:26 +0300537 else
Eli Cohene126ba92013-07-07 17:25:49 +0300538 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300539 }
540}
541
542static int mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev)
543{
544 struct mlx5_mr_cache *cache = &dev->cache;
545 struct mlx5_cache_ent *ent;
546 int i;
547
548 if (!mlx5_debugfs_root)
549 return 0;
550
Jack Morgenstein9603b612014-07-28 23:30:22 +0300551 cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
Eli Cohene126ba92013-07-07 17:25:49 +0300552 if (!cache->root)
553 return -ENOMEM;
554
555 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
556 ent = &cache->ent[i];
557 sprintf(ent->name, "%d", ent->order);
558 ent->dir = debugfs_create_dir(ent->name, cache->root);
559 if (!ent->dir)
560 return -ENOMEM;
561
562 ent->fsize = debugfs_create_file("size", 0600, ent->dir, ent,
563 &size_fops);
564 if (!ent->fsize)
565 return -ENOMEM;
566
567 ent->flimit = debugfs_create_file("limit", 0600, ent->dir, ent,
568 &limit_fops);
569 if (!ent->flimit)
570 return -ENOMEM;
571
572 ent->fcur = debugfs_create_u32("cur", 0400, ent->dir,
573 &ent->cur);
574 if (!ent->fcur)
575 return -ENOMEM;
576
577 ent->fmiss = debugfs_create_u32("miss", 0600, ent->dir,
578 &ent->miss);
579 if (!ent->fmiss)
580 return -ENOMEM;
581 }
582
583 return 0;
584}
585
586static void mlx5_mr_cache_debugfs_cleanup(struct mlx5_ib_dev *dev)
587{
588 if (!mlx5_debugfs_root)
589 return;
590
591 debugfs_remove_recursive(dev->cache.root);
592}
593
Eli Cohen746b5582013-10-23 09:53:14 +0300594static void delay_time_func(unsigned long ctx)
595{
596 struct mlx5_ib_dev *dev = (struct mlx5_ib_dev *)ctx;
597
598 dev->fill_delay = 0;
599}
600
Eli Cohene126ba92013-07-07 17:25:49 +0300601int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
602{
603 struct mlx5_mr_cache *cache = &dev->cache;
604 struct mlx5_cache_ent *ent;
605 int limit;
Eli Cohene126ba92013-07-07 17:25:49 +0300606 int err;
607 int i;
608
Moshe Lazer6bc1a652016-10-27 16:36:42 +0300609 mutex_init(&dev->slow_path_mutex);
Bhaktipriya Shridhar3c856c82016-08-15 23:41:18 +0530610 cache->wq = alloc_ordered_workqueue("mkey_cache", WQ_MEM_RECLAIM);
Eli Cohene126ba92013-07-07 17:25:49 +0300611 if (!cache->wq) {
612 mlx5_ib_warn(dev, "failed to create work queue\n");
613 return -ENOMEM;
614 }
615
Eli Cohen746b5582013-10-23 09:53:14 +0300616 setup_timer(&dev->delay_timer, delay_time_func, (unsigned long)dev);
Eli Cohene126ba92013-07-07 17:25:49 +0300617 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];
622 INIT_LIST_HEAD(&ent->head);
623 spin_lock_init(&ent->lock);
624 ent->order = i + 2;
625 ent->dev = dev;
626
Eli Cohenafd02cd2016-11-27 15:18:21 +0200627 if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200628 mlx5_core_is_pf(dev->mdev) &&
629 use_umr(dev, ent->order))
Jack Morgenstein9603b612014-07-28 23:30:22 +0300630 limit = dev->mdev->profile->mr_cache[i].limit;
Eli Cohen2d036fa2013-10-24 12:01:00 +0300631 else
Eli Cohene126ba92013-07-07 17:25:49 +0300632 limit = 0;
Eli Cohen2d036fa2013-10-24 12:01:00 +0300633
Eli Cohene126ba92013-07-07 17:25:49 +0300634 INIT_WORK(&ent->work, cache_work_func);
635 INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func);
636 ent->limit = limit;
637 queue_work(cache->wq, &ent->work);
638 }
639
640 err = mlx5_mr_cache_debugfs_init(dev);
641 if (err)
642 mlx5_ib_warn(dev, "cache debugfs failure\n");
643
644 return 0;
645}
646
Eli Cohenacbda522016-10-27 16:36:43 +0300647static void wait_for_async_commands(struct mlx5_ib_dev *dev)
648{
649 struct mlx5_mr_cache *cache = &dev->cache;
650 struct mlx5_cache_ent *ent;
651 int total = 0;
652 int i;
653 int j;
654
655 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
656 ent = &cache->ent[i];
657 for (j = 0 ; j < 1000; j++) {
658 if (!ent->pending)
659 break;
660 msleep(50);
661 }
662 }
663 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
664 ent = &cache->ent[i];
665 total += ent->pending;
666 }
667
668 if (total)
669 mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total);
670 else
671 mlx5_ib_warn(dev, "done with all pending requests\n");
672}
673
Eli Cohene126ba92013-07-07 17:25:49 +0300674int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
675{
676 int i;
677
678 dev->cache.stopped = 1;
Moshe Lazer3c461912013-09-11 16:35:23 +0300679 flush_workqueue(dev->cache.wq);
Eli Cohene126ba92013-07-07 17:25:49 +0300680
681 mlx5_mr_cache_debugfs_cleanup(dev);
682
683 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
684 clean_keys(dev, i);
685
Moshe Lazer3c461912013-09-11 16:35:23 +0300686 destroy_workqueue(dev->cache.wq);
Eli Cohenacbda522016-10-27 16:36:43 +0300687 wait_for_async_commands(dev);
Eli Cohen746b5582013-10-23 09:53:14 +0300688 del_timer_sync(&dev->delay_timer);
Moshe Lazer3c461912013-09-11 16:35:23 +0300689
Eli Cohene126ba92013-07-07 17:25:49 +0300690 return 0;
691}
692
693struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
694{
695 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300696 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Jack Morgenstein9603b612014-07-28 23:30:22 +0300697 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +0300698 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300699 void *mkc;
700 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300701 int err;
702
703 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
704 if (!mr)
705 return ERR_PTR(-ENOMEM);
706
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300707 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300708 if (!in) {
709 err = -ENOMEM;
710 goto err_free;
711 }
712
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300713 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300714
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300715 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_PA);
716 MLX5_SET(mkc, mkc, a, !!(acc & IB_ACCESS_REMOTE_ATOMIC));
717 MLX5_SET(mkc, mkc, rw, !!(acc & IB_ACCESS_REMOTE_WRITE));
718 MLX5_SET(mkc, mkc, rr, !!(acc & IB_ACCESS_REMOTE_READ));
719 MLX5_SET(mkc, mkc, lw, !!(acc & IB_ACCESS_LOCAL_WRITE));
720 MLX5_SET(mkc, mkc, lr, 1);
721
722 MLX5_SET(mkc, mkc, length64, 1);
723 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
724 MLX5_SET(mkc, mkc, qpn, 0xffffff);
725 MLX5_SET64(mkc, mkc, start_addr, 0);
726
727 err = mlx5_core_create_mkey(mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +0300728 if (err)
729 goto err_in;
730
731 kfree(in);
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +0200732 mr->mmkey.type = MLX5_MKEY_MR;
Matan Baraka606b0f2016-02-29 18:05:28 +0200733 mr->ibmr.lkey = mr->mmkey.key;
734 mr->ibmr.rkey = mr->mmkey.key;
Eli Cohene126ba92013-07-07 17:25:49 +0300735 mr->umem = NULL;
736
737 return &mr->ibmr;
738
739err_in:
740 kfree(in);
741
742err_free:
743 kfree(mr);
744
745 return ERR_PTR(err);
746}
747
748static int get_octo_len(u64 addr, u64 len, int page_size)
749{
750 u64 offset;
751 int npages;
752
753 offset = addr & (page_size - 1);
754 npages = ALIGN(len + offset, page_size) >> ilog2(page_size);
755 return (npages + 1) / 2;
756}
757
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200758static int use_umr(struct mlx5_ib_dev *dev, int order)
Eli Cohene126ba92013-07-07 17:25:49 +0300759{
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200760 if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
761 return order < MAX_MR_CACHE_ENTRIES + 2;
Haggai Erancc149f752014-12-11 17:04:21 +0200762 return order <= MLX5_MAX_UMR_SHIFT;
Eli Cohene126ba92013-07-07 17:25:49 +0300763}
764
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200765static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
766 int access_flags, struct ib_umem **umem,
767 int *npages, int *page_shift, int *ncont,
768 int *order)
Noa Osherovich395a8e42016-02-29 16:46:50 +0200769{
770 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200771 int err;
772
773 *umem = ib_umem_get(pd->uobject->context, start, length,
774 access_flags, 0);
775 err = PTR_ERR_OR_ZERO(*umem);
776 if (err < 0) {
Noa Osherovich395a8e42016-02-29 16:46:50 +0200777 mlx5_ib_err(dev, "umem get failed (%ld)\n", PTR_ERR(umem));
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200778 return err;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200779 }
780
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200781 mlx5_ib_cont_pages(*umem, start, MLX5_MKEY_PAGE_SHIFT_MASK, npages,
Majd Dibbiny762f8992016-10-27 16:36:47 +0300782 page_shift, ncont, order);
Noa Osherovich395a8e42016-02-29 16:46:50 +0200783 if (!*npages) {
784 mlx5_ib_warn(dev, "avoid zero region\n");
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200785 ib_umem_release(*umem);
786 return -EINVAL;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200787 }
788
789 mlx5_ib_dbg(dev, "npages %d, ncont %d, order %d, page_shift %d\n",
790 *npages, *ncont, *order, *page_shift);
791
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200792 return 0;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200793}
794
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100795static void mlx5_ib_umr_done(struct ib_cq *cq, struct ib_wc *wc)
Eli Cohene126ba92013-07-07 17:25:49 +0300796{
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100797 struct mlx5_ib_umr_context *context =
798 container_of(wc->wr_cqe, struct mlx5_ib_umr_context, cqe);
Eli Cohene126ba92013-07-07 17:25:49 +0300799
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100800 context->status = wc->status;
801 complete(&context->done);
802}
Eli Cohene126ba92013-07-07 17:25:49 +0300803
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100804static inline void mlx5_ib_init_umr_context(struct mlx5_ib_umr_context *context)
805{
806 context->cqe.done = mlx5_ib_umr_done;
807 context->status = -1;
808 init_completion(&context->done);
Eli Cohene126ba92013-07-07 17:25:49 +0300809}
810
Binoy Jayand5ea2df2017-01-02 11:37:40 +0200811static int mlx5_ib_post_send_wait(struct mlx5_ib_dev *dev,
812 struct mlx5_umr_wr *umrwr)
813{
814 struct umr_common *umrc = &dev->umrc;
815 struct ib_send_wr *bad;
816 int err;
817 struct mlx5_ib_umr_context umr_context;
818
819 mlx5_ib_init_umr_context(&umr_context);
820 umrwr->wr.wr_cqe = &umr_context.cqe;
821
822 down(&umrc->sem);
823 err = ib_post_send(umrc->qp, &umrwr->wr, &bad);
824 if (err) {
825 mlx5_ib_warn(dev, "UMR post send failed, err %d\n", err);
826 } else {
827 wait_for_completion(&umr_context.done);
828 if (umr_context.status != IB_WC_SUCCESS) {
829 mlx5_ib_warn(dev, "reg umr failed (%u)\n",
830 umr_context.status);
831 err = -EFAULT;
832 }
833 }
834 up(&umrc->sem);
835 return err;
836}
837
Eli Cohene126ba92013-07-07 17:25:49 +0300838static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem,
839 u64 virt_addr, u64 len, int npages,
840 int page_shift, int order, int access_flags)
841{
842 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +0300843 struct mlx5_ib_mr *mr;
Haggai Eran096f7e72014-05-22 14:50:08 +0300844 int err = 0;
Eli Cohene126ba92013-07-07 17:25:49 +0300845 int i;
846
Eli Cohen746b5582013-10-23 09:53:14 +0300847 for (i = 0; i < 1; i++) {
Eli Cohene126ba92013-07-07 17:25:49 +0300848 mr = alloc_cached_mr(dev, order);
849 if (mr)
850 break;
851
852 err = add_keys(dev, order2idx(dev, order), 1);
Eli Cohen746b5582013-10-23 09:53:14 +0300853 if (err && err != -EAGAIN) {
854 mlx5_ib_warn(dev, "add_keys failed, err %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300855 break;
856 }
857 }
858
859 if (!mr)
860 return ERR_PTR(-EAGAIN);
861
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200862 mr->ibmr.pd = pd;
863 mr->umem = umem;
864 mr->access_flags = access_flags;
865 mr->desc_size = sizeof(struct mlx5_mtt);
Matan Baraka606b0f2016-02-29 18:05:28 +0200866 mr->mmkey.iova = virt_addr;
867 mr->mmkey.size = len;
868 mr->mmkey.pd = to_mpd(pd)->pdn;
Haggai Eranb4755982014-05-22 14:50:10 +0300869
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200870 err = mlx5_ib_update_xlt(mr, 0, npages, page_shift,
871 MLX5_IB_UPD_XLT_ENABLE);
Haggai Eranb4cfe442014-12-11 17:04:26 +0200872
Haggai Eran096f7e72014-05-22 14:50:08 +0300873 if (err) {
874 free_cached_mr(dev, mr);
875 return ERR_PTR(err);
Eli Cohene126ba92013-07-07 17:25:49 +0300876 }
877
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200878 mr->live = 1;
879
Eli Cohene126ba92013-07-07 17:25:49 +0300880 return mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300881}
882
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200883static inline int populate_xlt(struct mlx5_ib_mr *mr, int idx, int npages,
884 void *xlt, int page_shift, size_t size,
885 int flags)
886{
887 struct mlx5_ib_dev *dev = mr->dev;
888 struct ib_umem *umem = mr->umem;
889
890 npages = min_t(size_t, npages, ib_umem_num_pages(umem) - idx);
891
892 if (!(flags & MLX5_IB_UPD_XLT_ZAP)) {
893 __mlx5_ib_populate_pas(dev, umem, page_shift,
894 idx, npages, xlt,
895 MLX5_IB_MTT_PRESENT);
896 /* Clear padding after the pages
897 * brought from the umem.
898 */
899 memset(xlt + (npages * sizeof(struct mlx5_mtt)), 0,
900 size - npages * sizeof(struct mlx5_mtt));
901 }
902
903 return npages;
904}
905
906#define MLX5_MAX_UMR_CHUNK ((1 << (MLX5_MAX_UMR_SHIFT + 4)) - \
907 MLX5_UMR_MTT_ALIGNMENT)
908#define MLX5_SPARE_UMR_CHUNK 0x10000
909
910int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
911 int page_shift, int flags)
Haggai Eran832a6b02014-12-11 17:04:22 +0200912{
913 struct mlx5_ib_dev *dev = mr->dev;
914 struct device *ddev = dev->ib_dev.dma_device;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200915 struct mlx5_ib_ucontext *uctx = NULL;
Haggai Eran832a6b02014-12-11 17:04:22 +0200916 int size;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200917 void *xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200918 dma_addr_t dma;
Christoph Hellwige622f2f2015-10-08 09:16:33 +0100919 struct mlx5_umr_wr wr;
Haggai Eran832a6b02014-12-11 17:04:22 +0200920 struct ib_sge sg;
921 int err = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200922 int desc_size = sizeof(struct mlx5_mtt);
923 const int page_align = MLX5_UMR_MTT_ALIGNMENT / desc_size;
924 const int page_mask = page_align - 1;
Haggai Eran832a6b02014-12-11 17:04:22 +0200925 size_t pages_mapped = 0;
926 size_t pages_to_map = 0;
927 size_t pages_iter = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200928 gfp_t gfp;
Haggai Eran832a6b02014-12-11 17:04:22 +0200929
930 /* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes,
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200931 * so we need to align the offset and length accordingly
932 */
933 if (idx & page_mask) {
934 npages += idx & page_mask;
935 idx &= ~page_mask;
Haggai Eran832a6b02014-12-11 17:04:22 +0200936 }
937
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200938 gfp = flags & MLX5_IB_UPD_XLT_ATOMIC ? GFP_ATOMIC : GFP_KERNEL;
939 gfp |= __GFP_ZERO | __GFP_NOWARN;
Haggai Eran832a6b02014-12-11 17:04:22 +0200940
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200941 pages_to_map = ALIGN(npages, page_align);
942 size = desc_size * pages_to_map;
943 size = min_t(int, size, MLX5_MAX_UMR_CHUNK);
Haggai Eran832a6b02014-12-11 17:04:22 +0200944
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200945 xlt = (void *)__get_free_pages(gfp, get_order(size));
946 if (!xlt && size > MLX5_SPARE_UMR_CHUNK) {
947 mlx5_ib_dbg(dev, "Failed to allocate %d bytes of order %d. fallback to spare UMR allocation od %d bytes\n",
948 size, get_order(size), MLX5_SPARE_UMR_CHUNK);
949
950 size = MLX5_SPARE_UMR_CHUNK;
951 xlt = (void *)__get_free_pages(gfp, get_order(size));
Haggai Eran832a6b02014-12-11 17:04:22 +0200952 }
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200953
954 if (!xlt) {
955 uctx = to_mucontext(mr->ibmr.uobject->context);
956 mlx5_ib_warn(dev, "Using XLT emergency buffer\n");
957 size = PAGE_SIZE;
958 xlt = (void *)uctx->upd_xlt_page;
959 mutex_lock(&uctx->upd_xlt_page_mutex);
960 memset(xlt, 0, size);
961 }
962 pages_iter = size / desc_size;
963 dma = dma_map_single(ddev, xlt, size, DMA_TO_DEVICE);
Haggai Eran832a6b02014-12-11 17:04:22 +0200964 if (dma_mapping_error(ddev, dma)) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200965 mlx5_ib_err(dev, "unable to map DMA during XLT update.\n");
Haggai Eran832a6b02014-12-11 17:04:22 +0200966 err = -ENOMEM;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200967 goto free_xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200968 }
969
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200970 sg.addr = dma;
971 sg.lkey = dev->umrc.pd->local_dma_lkey;
972
973 memset(&wr, 0, sizeof(wr));
974 wr.wr.send_flags = MLX5_IB_SEND_UMR_UPDATE_XLT;
975 if (!(flags & MLX5_IB_UPD_XLT_ENABLE))
976 wr.wr.send_flags |= MLX5_IB_SEND_UMR_FAIL_IF_FREE;
977 wr.wr.sg_list = &sg;
978 wr.wr.num_sge = 1;
979 wr.wr.opcode = MLX5_IB_WR_UMR;
980
981 wr.pd = mr->ibmr.pd;
982 wr.mkey = mr->mmkey.key;
983 wr.length = mr->mmkey.size;
984 wr.virt_addr = mr->mmkey.iova;
985 wr.access_flags = mr->access_flags;
986 wr.page_shift = page_shift;
987
Haggai Eran832a6b02014-12-11 17:04:22 +0200988 for (pages_mapped = 0;
989 pages_mapped < pages_to_map && !err;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200990 pages_mapped += pages_iter, idx += pages_iter) {
Haggai Eran832a6b02014-12-11 17:04:22 +0200991 dma_sync_single_for_cpu(ddev, dma, size, DMA_TO_DEVICE);
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200992 npages = populate_xlt(mr, idx, pages_iter, xlt,
993 page_shift, size, flags);
Haggai Eran832a6b02014-12-11 17:04:22 +0200994
995 dma_sync_single_for_device(ddev, dma, size, DMA_TO_DEVICE);
996
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200997 sg.length = ALIGN(npages * desc_size,
998 MLX5_UMR_MTT_ALIGNMENT);
Haggai Eran832a6b02014-12-11 17:04:22 +0200999
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001000 if (pages_mapped + pages_iter >= pages_to_map) {
1001 if (flags & MLX5_IB_UPD_XLT_ENABLE)
1002 wr.wr.send_flags |=
1003 MLX5_IB_SEND_UMR_ENABLE_MR |
1004 MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS |
1005 MLX5_IB_SEND_UMR_UPDATE_TRANSLATION;
1006 if (flags & MLX5_IB_UPD_XLT_PD ||
1007 flags & MLX5_IB_UPD_XLT_ACCESS)
1008 wr.wr.send_flags |=
1009 MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
1010 if (flags & MLX5_IB_UPD_XLT_ADDR)
1011 wr.wr.send_flags |=
1012 MLX5_IB_SEND_UMR_UPDATE_TRANSLATION;
1013 }
Haggai Eran832a6b02014-12-11 17:04:22 +02001014
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001015 wr.offset = idx * desc_size;
Artemy Kovalyov31616252017-01-02 11:37:42 +02001016 wr.xlt_size = sg.length;
Haggai Eran832a6b02014-12-11 17:04:22 +02001017
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001018 err = mlx5_ib_post_send_wait(dev, &wr);
Haggai Eran832a6b02014-12-11 17:04:22 +02001019 }
1020 dma_unmap_single(ddev, dma, size, DMA_TO_DEVICE);
1021
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001022free_xlt:
1023 if (uctx)
1024 mutex_unlock(&uctx->upd_xlt_page_mutex);
Haggai Eran832a6b02014-12-11 17:04:22 +02001025 else
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001026 free_pages((unsigned long)xlt, get_order(size));
Haggai Eran832a6b02014-12-11 17:04:22 +02001027
1028 return err;
1029}
Haggai Eran832a6b02014-12-11 17:04:22 +02001030
Noa Osherovich395a8e42016-02-29 16:46:50 +02001031/*
1032 * If ibmr is NULL it will be allocated by reg_create.
1033 * Else, the given ibmr will be used.
1034 */
1035static struct mlx5_ib_mr *reg_create(struct ib_mr *ibmr, struct ib_pd *pd,
1036 u64 virt_addr, u64 length,
1037 struct ib_umem *umem, int npages,
1038 int page_shift, int access_flags)
Eli Cohene126ba92013-07-07 17:25:49 +03001039{
1040 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +03001041 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001042 __be64 *pas;
1043 void *mkc;
Eli Cohene126ba92013-07-07 17:25:49 +03001044 int inlen;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001045 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +03001046 int err;
Saeed Mahameed938fe832015-05-28 22:28:41 +03001047 bool pg_cap = !!(MLX5_CAP_GEN(dev->mdev, pg));
Eli Cohene126ba92013-07-07 17:25:49 +03001048
Noa Osherovich395a8e42016-02-29 16:46:50 +02001049 mr = ibmr ? to_mmr(ibmr) : kzalloc(sizeof(*mr), GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +03001050 if (!mr)
1051 return ERR_PTR(-ENOMEM);
1052
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001053 inlen = MLX5_ST_SZ_BYTES(create_mkey_in) +
1054 sizeof(*pas) * ((npages + 1) / 2) * 2;
Eli Cohene126ba92013-07-07 17:25:49 +03001055 in = mlx5_vzalloc(inlen);
1056 if (!in) {
1057 err = -ENOMEM;
1058 goto err_1;
1059 }
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001060 pas = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
Artemy Kovalyovc438fde2017-01-02 11:37:43 +02001061 if (!(access_flags & IB_ACCESS_ON_DEMAND))
1062 mlx5_ib_populate_pas(dev, umem, page_shift, pas,
1063 pg_cap ? MLX5_IB_MTT_PRESENT : 0);
Eli Cohene126ba92013-07-07 17:25:49 +03001064
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001065 /* The pg_access bit allows setting the access flags
Haggai Erancc149f752014-12-11 17:04:21 +02001066 * in the page list submitted with the command. */
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001067 MLX5_SET(create_mkey_in, in, pg_access, !!(pg_cap));
1068
1069 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1070 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
1071 MLX5_SET(mkc, mkc, a, !!(access_flags & IB_ACCESS_REMOTE_ATOMIC));
1072 MLX5_SET(mkc, mkc, rw, !!(access_flags & IB_ACCESS_REMOTE_WRITE));
1073 MLX5_SET(mkc, mkc, rr, !!(access_flags & IB_ACCESS_REMOTE_READ));
1074 MLX5_SET(mkc, mkc, lw, !!(access_flags & IB_ACCESS_LOCAL_WRITE));
1075 MLX5_SET(mkc, mkc, lr, 1);
1076
1077 MLX5_SET64(mkc, mkc, start_addr, virt_addr);
1078 MLX5_SET64(mkc, mkc, len, length);
1079 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1080 MLX5_SET(mkc, mkc, bsf_octword_size, 0);
1081 MLX5_SET(mkc, mkc, translations_octword_size,
1082 get_octo_len(virt_addr, length, 1 << page_shift));
1083 MLX5_SET(mkc, mkc, log_page_size, page_shift);
1084 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1085 MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
1086 get_octo_len(virt_addr, length, 1 << page_shift));
1087
1088 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +03001089 if (err) {
1090 mlx5_ib_warn(dev, "create mkey failed\n");
1091 goto err_2;
1092 }
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +02001093 mr->mmkey.type = MLX5_MKEY_MR;
Eli Cohene126ba92013-07-07 17:25:49 +03001094 mr->umem = umem;
Majd Dibbiny7eae20d2015-01-06 13:56:01 +02001095 mr->dev = dev;
Haggai Eranb4cfe442014-12-11 17:04:26 +02001096 mr->live = 1;
Al Viro479163f2014-11-20 08:13:57 +00001097 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001098
Matan Baraka606b0f2016-02-29 18:05:28 +02001099 mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001100
1101 return mr;
1102
1103err_2:
Al Viro479163f2014-11-20 08:13:57 +00001104 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001105
1106err_1:
Noa Osherovich395a8e42016-02-29 16:46:50 +02001107 if (!ibmr)
1108 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +03001109
1110 return ERR_PTR(err);
1111}
1112
Noa Osherovich395a8e42016-02-29 16:46:50 +02001113static void set_mr_fileds(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
1114 int npages, u64 length, int access_flags)
1115{
1116 mr->npages = npages;
1117 atomic_add(npages, &dev->mdev->priv.reg_pages);
Matan Baraka606b0f2016-02-29 18:05:28 +02001118 mr->ibmr.lkey = mr->mmkey.key;
1119 mr->ibmr.rkey = mr->mmkey.key;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001120 mr->ibmr.length = length;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001121 mr->access_flags = access_flags;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001122}
1123
Eli Cohene126ba92013-07-07 17:25:49 +03001124struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
1125 u64 virt_addr, int access_flags,
1126 struct ib_udata *udata)
1127{
1128 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1129 struct mlx5_ib_mr *mr = NULL;
1130 struct ib_umem *umem;
1131 int page_shift;
1132 int npages;
1133 int ncont;
1134 int order;
1135 int err;
1136
Eli Cohen900a6d72014-09-14 16:47:51 +03001137 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1138 start, virt_addr, length, access_flags);
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001139 err = mr_umem_get(pd, start, length, access_flags, &umem, &npages,
Noa Osherovich395a8e42016-02-29 16:46:50 +02001140 &page_shift, &ncont, &order);
1141
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001142 if (err < 0)
1143 return ERR_PTR(err);
Eli Cohene126ba92013-07-07 17:25:49 +03001144
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001145 if (use_umr(dev, order)) {
Eli Cohene126ba92013-07-07 17:25:49 +03001146 mr = reg_umr(pd, umem, virt_addr, length, ncont, page_shift,
1147 order, access_flags);
1148 if (PTR_ERR(mr) == -EAGAIN) {
1149 mlx5_ib_dbg(dev, "cache empty for order %d", order);
1150 mr = NULL;
1151 }
Artemy Kovalyovc438fde2017-01-02 11:37:43 +02001152 } else if (access_flags & IB_ACCESS_ON_DEMAND &&
1153 !MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
Haggai Eran6aec21f2014-12-11 17:04:23 +02001154 err = -EINVAL;
1155 pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB");
1156 goto error;
Eli Cohene126ba92013-07-07 17:25:49 +03001157 }
1158
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001159 if (!mr) {
1160 mutex_lock(&dev->slow_path_mutex);
Noa Osherovich395a8e42016-02-29 16:46:50 +02001161 mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
1162 page_shift, access_flags);
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001163 mutex_unlock(&dev->slow_path_mutex);
1164 }
Eli Cohene126ba92013-07-07 17:25:49 +03001165
1166 if (IS_ERR(mr)) {
1167 err = PTR_ERR(mr);
1168 goto error;
1169 }
1170
Matan Baraka606b0f2016-02-29 18:05:28 +02001171 mlx5_ib_dbg(dev, "mkey 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001172
1173 mr->umem = umem;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001174 set_mr_fileds(dev, mr, npages, length, access_flags);
Eli Cohene126ba92013-07-07 17:25:49 +03001175
Haggai Eranb4cfe442014-12-11 17:04:26 +02001176#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Noa Osherovich395a8e42016-02-29 16:46:50 +02001177 update_odp_mr(mr);
Haggai Eranb4cfe442014-12-11 17:04:26 +02001178#endif
1179
Eli Cohene126ba92013-07-07 17:25:49 +03001180 return &mr->ibmr;
1181
1182error:
1183 ib_umem_release(umem);
1184 return ERR_PTR(err);
1185}
1186
1187static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
1188{
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03001189 struct mlx5_core_dev *mdev = dev->mdev;
Doug Ledford0025b0b2016-03-03 11:23:37 -05001190 struct mlx5_umr_wr umrwr = {};
Eli Cohene126ba92013-07-07 17:25:49 +03001191
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03001192 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
1193 return 0;
1194
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001195 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_DISABLE_MR |
1196 MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1197 umrwr.wr.opcode = MLX5_IB_WR_UMR;
1198 umrwr.mkey = mr->mmkey.key;
Eli Cohene126ba92013-07-07 17:25:49 +03001199
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001200 return mlx5_ib_post_send_wait(dev, &umrwr);
Eli Cohene126ba92013-07-07 17:25:49 +03001201}
1202
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001203static int rereg_umr(struct ib_pd *pd, struct mlx5_ib_mr *mr,
Noa Osherovich56e11d62016-02-29 16:46:51 +02001204 int access_flags, int flags)
1205{
1206 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001207 struct mlx5_umr_wr umrwr = {};
Noa Osherovich56e11d62016-02-29 16:46:51 +02001208 int err;
1209
Noa Osherovich56e11d62016-02-29 16:46:51 +02001210 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1211
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001212 umrwr.wr.opcode = MLX5_IB_WR_UMR;
1213 umrwr.mkey = mr->mmkey.key;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001214
Artemy Kovalyov31616252017-01-02 11:37:42 +02001215 if (flags & IB_MR_REREG_PD || flags & IB_MR_REREG_ACCESS) {
Noa Osherovich56e11d62016-02-29 16:46:51 +02001216 umrwr.pd = pd;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001217 umrwr.access_flags = access_flags;
Artemy Kovalyov31616252017-01-02 11:37:42 +02001218 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001219 }
1220
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001221 err = mlx5_ib_post_send_wait(dev, &umrwr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001222
Noa Osherovich56e11d62016-02-29 16:46:51 +02001223 return err;
1224}
1225
1226int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
1227 u64 length, u64 virt_addr, int new_access_flags,
1228 struct ib_pd *new_pd, struct ib_udata *udata)
1229{
1230 struct mlx5_ib_dev *dev = to_mdev(ib_mr->device);
1231 struct mlx5_ib_mr *mr = to_mmr(ib_mr);
1232 struct ib_pd *pd = (flags & IB_MR_REREG_PD) ? new_pd : ib_mr->pd;
1233 int access_flags = flags & IB_MR_REREG_ACCESS ?
1234 new_access_flags :
1235 mr->access_flags;
1236 u64 addr = (flags & IB_MR_REREG_TRANS) ? virt_addr : mr->umem->address;
1237 u64 len = (flags & IB_MR_REREG_TRANS) ? length : mr->umem->length;
1238 int page_shift = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001239 int upd_flags = 0;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001240 int npages = 0;
1241 int ncont = 0;
1242 int order = 0;
1243 int err;
1244
1245 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1246 start, virt_addr, length, access_flags);
1247
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001248 atomic_sub(mr->npages, &dev->mdev->priv.reg_pages);
1249
Noa Osherovich56e11d62016-02-29 16:46:51 +02001250 if (flags != IB_MR_REREG_PD) {
1251 /*
1252 * Replace umem. This needs to be done whether or not UMR is
1253 * used.
1254 */
1255 flags |= IB_MR_REREG_TRANS;
1256 ib_umem_release(mr->umem);
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001257 err = mr_umem_get(pd, addr, len, access_flags, &mr->umem,
1258 &npages, &page_shift, &ncont, &order);
1259 if (err < 0) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001260 clean_mr(mr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001261 return err;
1262 }
1263 }
1264
1265 if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
1266 /*
1267 * UMR can't be used - MKey needs to be replaced.
1268 */
1269 if (mr->umred) {
1270 err = unreg_umr(dev, mr);
1271 if (err)
1272 mlx5_ib_warn(dev, "Failed to unregister MR\n");
1273 } else {
1274 err = destroy_mkey(dev, mr);
1275 if (err)
1276 mlx5_ib_warn(dev, "Failed to destroy MKey\n");
1277 }
1278 if (err)
1279 return err;
1280
1281 mr = reg_create(ib_mr, pd, addr, len, mr->umem, ncont,
1282 page_shift, access_flags);
1283
1284 if (IS_ERR(mr))
1285 return PTR_ERR(mr);
1286
1287 mr->umred = 0;
1288 } else {
1289 /*
1290 * Send a UMR WQE
1291 */
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001292 mr->ibmr.pd = pd;
1293 mr->access_flags = access_flags;
1294 mr->mmkey.iova = addr;
1295 mr->mmkey.size = len;
1296 mr->mmkey.pd = to_mpd(pd)->pdn;
1297
1298 if (flags & IB_MR_REREG_TRANS) {
1299 upd_flags = MLX5_IB_UPD_XLT_ADDR;
1300 if (flags & IB_MR_REREG_PD)
1301 upd_flags |= MLX5_IB_UPD_XLT_PD;
1302 if (flags & IB_MR_REREG_ACCESS)
1303 upd_flags |= MLX5_IB_UPD_XLT_ACCESS;
1304 err = mlx5_ib_update_xlt(mr, 0, npages, page_shift,
1305 upd_flags);
1306 } else {
1307 err = rereg_umr(pd, mr, access_flags, flags);
1308 }
1309
Noa Osherovich56e11d62016-02-29 16:46:51 +02001310 if (err) {
1311 mlx5_ib_warn(dev, "Failed to rereg UMR\n");
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001312 ib_umem_release(mr->umem);
1313 clean_mr(mr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001314 return err;
1315 }
1316 }
1317
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001318 set_mr_fileds(dev, mr, npages, len, access_flags);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001319
Noa Osherovich56e11d62016-02-29 16:46:51 +02001320#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
1321 update_odp_mr(mr);
1322#endif
Noa Osherovich56e11d62016-02-29 16:46:51 +02001323 return 0;
1324}
1325
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001326static int
1327mlx5_alloc_priv_descs(struct ib_device *device,
1328 struct mlx5_ib_mr *mr,
1329 int ndescs,
1330 int desc_size)
1331{
1332 int size = ndescs * desc_size;
1333 int add_size;
1334 int ret;
1335
1336 add_size = max_t(int, MLX5_UMR_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
1337
1338 mr->descs_alloc = kzalloc(size + add_size, GFP_KERNEL);
1339 if (!mr->descs_alloc)
1340 return -ENOMEM;
1341
1342 mr->descs = PTR_ALIGN(mr->descs_alloc, MLX5_UMR_ALIGN);
1343
1344 mr->desc_map = dma_map_single(device->dma_device, mr->descs,
1345 size, DMA_TO_DEVICE);
1346 if (dma_mapping_error(device->dma_device, mr->desc_map)) {
1347 ret = -ENOMEM;
1348 goto err;
1349 }
1350
1351 return 0;
1352err:
1353 kfree(mr->descs_alloc);
1354
1355 return ret;
1356}
1357
1358static void
1359mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
1360{
1361 if (mr->descs) {
1362 struct ib_device *device = mr->ibmr.device;
1363 int size = mr->max_descs * mr->desc_size;
1364
1365 dma_unmap_single(device->dma_device, mr->desc_map,
1366 size, DMA_TO_DEVICE);
1367 kfree(mr->descs_alloc);
1368 mr->descs = NULL;
1369 }
1370}
1371
Haggai Eran6aec21f2014-12-11 17:04:23 +02001372static int clean_mr(struct mlx5_ib_mr *mr)
Eli Cohene126ba92013-07-07 17:25:49 +03001373{
Haggai Eran6aec21f2014-12-11 17:04:23 +02001374 struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
Eli Cohene126ba92013-07-07 17:25:49 +03001375 int umred = mr->umred;
1376 int err;
1377
Sagi Grimberg8b91ffc2015-07-30 10:32:34 +03001378 if (mr->sig) {
1379 if (mlx5_core_destroy_psv(dev->mdev,
1380 mr->sig->psv_memory.psv_idx))
1381 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1382 mr->sig->psv_memory.psv_idx);
1383 if (mlx5_core_destroy_psv(dev->mdev,
1384 mr->sig->psv_wire.psv_idx))
1385 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1386 mr->sig->psv_wire.psv_idx);
1387 kfree(mr->sig);
1388 mr->sig = NULL;
1389 }
1390
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001391 mlx5_free_priv_descs(mr);
1392
Eli Cohene126ba92013-07-07 17:25:49 +03001393 if (!umred) {
Haggai Eranb4cfe442014-12-11 17:04:26 +02001394 err = destroy_mkey(dev, mr);
Eli Cohene126ba92013-07-07 17:25:49 +03001395 if (err) {
1396 mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
Matan Baraka606b0f2016-02-29 18:05:28 +02001397 mr->mmkey.key, err);
Eli Cohene126ba92013-07-07 17:25:49 +03001398 return err;
1399 }
1400 } else {
1401 err = unreg_umr(dev, mr);
1402 if (err) {
1403 mlx5_ib_warn(dev, "failed unregister\n");
1404 return err;
1405 }
1406 free_cached_mr(dev, mr);
1407 }
1408
Eli Cohene126ba92013-07-07 17:25:49 +03001409 if (!umred)
1410 kfree(mr);
1411
1412 return 0;
1413}
1414
Haggai Eran6aec21f2014-12-11 17:04:23 +02001415int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
1416{
1417 struct mlx5_ib_dev *dev = to_mdev(ibmr->device);
1418 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1419 int npages = mr->npages;
1420 struct ib_umem *umem = mr->umem;
1421
1422#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Haggai Eranb4cfe442014-12-11 17:04:26 +02001423 if (umem && umem->odp_data) {
1424 /* Prevent new page faults from succeeding */
1425 mr->live = 0;
Haggai Eran6aec21f2014-12-11 17:04:23 +02001426 /* Wait for all running page-fault handlers to finish. */
1427 synchronize_srcu(&dev->mr_srcu);
Haggai Eranb4cfe442014-12-11 17:04:26 +02001428 /* Destroy all page mappings */
1429 mlx5_ib_invalidate_range(umem, ib_umem_start(umem),
1430 ib_umem_end(umem));
1431 /*
1432 * We kill the umem before the MR for ODP,
1433 * so that there will not be any invalidations in
1434 * flight, looking at the *mr struct.
1435 */
1436 ib_umem_release(umem);
1437 atomic_sub(npages, &dev->mdev->priv.reg_pages);
1438
1439 /* Avoid double-freeing the umem. */
1440 umem = NULL;
1441 }
Haggai Eran6aec21f2014-12-11 17:04:23 +02001442#endif
1443
1444 clean_mr(mr);
1445
1446 if (umem) {
1447 ib_umem_release(umem);
1448 atomic_sub(npages, &dev->mdev->priv.reg_pages);
1449 }
1450
1451 return 0;
1452}
1453
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001454struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
1455 enum ib_mr_type mr_type,
1456 u32 max_num_sg)
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001457{
1458 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001459 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001460 int ndescs = ALIGN(max_num_sg, 4);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001461 struct mlx5_ib_mr *mr;
1462 void *mkc;
1463 u32 *in;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001464 int err;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001465
1466 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1467 if (!mr)
1468 return ERR_PTR(-ENOMEM);
1469
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001470 in = kzalloc(inlen, GFP_KERNEL);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001471 if (!in) {
1472 err = -ENOMEM;
1473 goto err_free;
1474 }
1475
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001476 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1477 MLX5_SET(mkc, mkc, free, 1);
1478 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1479 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1480 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001481
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001482 if (mr_type == IB_MR_TYPE_MEM_REG) {
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001483 mr->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
1484 MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001485 err = mlx5_alloc_priv_descs(pd->device, mr,
Artemy Kovalyov31616252017-01-02 11:37:42 +02001486 ndescs, sizeof(struct mlx5_mtt));
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001487 if (err)
1488 goto err_free_in;
1489
Artemy Kovalyov31616252017-01-02 11:37:42 +02001490 mr->desc_size = sizeof(struct mlx5_mtt);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001491 mr->max_descs = ndescs;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001492 } else if (mr_type == IB_MR_TYPE_SG_GAPS) {
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001493 mr->access_mode = MLX5_MKC_ACCESS_MODE_KLMS;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001494
1495 err = mlx5_alloc_priv_descs(pd->device, mr,
1496 ndescs, sizeof(struct mlx5_klm));
1497 if (err)
1498 goto err_free_in;
1499 mr->desc_size = sizeof(struct mlx5_klm);
1500 mr->max_descs = ndescs;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001501 } else if (mr_type == IB_MR_TYPE_SIGNATURE) {
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001502 u32 psv_index[2];
1503
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001504 MLX5_SET(mkc, mkc, bsf_en, 1);
1505 MLX5_SET(mkc, mkc, bsf_octword_size, MLX5_MKEY_BSF_OCTO_SIZE);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001506 mr->sig = kzalloc(sizeof(*mr->sig), GFP_KERNEL);
1507 if (!mr->sig) {
1508 err = -ENOMEM;
1509 goto err_free_in;
1510 }
1511
1512 /* create mem & wire PSVs */
Jack Morgenstein9603b612014-07-28 23:30:22 +03001513 err = mlx5_core_create_psv(dev->mdev, to_mpd(pd)->pdn,
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001514 2, psv_index);
1515 if (err)
1516 goto err_free_sig;
1517
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001518 mr->access_mode = MLX5_MKC_ACCESS_MODE_KLMS;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001519 mr->sig->psv_memory.psv_idx = psv_index[0];
1520 mr->sig->psv_wire.psv_idx = psv_index[1];
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02001521
1522 mr->sig->sig_status_checked = true;
1523 mr->sig->sig_err_exists = false;
1524 /* Next UMR, Arm SIGERR */
1525 ++mr->sig->sigerr_count;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001526 } else {
1527 mlx5_ib_warn(dev, "Invalid mr type %d\n", mr_type);
1528 err = -EINVAL;
1529 goto err_free_in;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001530 }
1531
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001532 MLX5_SET(mkc, mkc, access_mode, mr->access_mode);
1533 MLX5_SET(mkc, mkc, umr_en, 1);
1534
1535 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001536 if (err)
1537 goto err_destroy_psv;
1538
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +02001539 mr->mmkey.type = MLX5_MKEY_MR;
Matan Baraka606b0f2016-02-29 18:05:28 +02001540 mr->ibmr.lkey = mr->mmkey.key;
1541 mr->ibmr.rkey = mr->mmkey.key;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001542 mr->umem = NULL;
1543 kfree(in);
1544
1545 return &mr->ibmr;
1546
1547err_destroy_psv:
1548 if (mr->sig) {
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_memory.psv_idx))
1551 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1552 mr->sig->psv_memory.psv_idx);
Jack Morgenstein9603b612014-07-28 23:30:22 +03001553 if (mlx5_core_destroy_psv(dev->mdev,
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001554 mr->sig->psv_wire.psv_idx))
1555 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1556 mr->sig->psv_wire.psv_idx);
1557 }
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001558 mlx5_free_priv_descs(mr);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001559err_free_sig:
1560 kfree(mr->sig);
1561err_free_in:
1562 kfree(in);
1563err_free:
1564 kfree(mr);
1565 return ERR_PTR(err);
1566}
1567
Matan Barakd2370e02016-02-29 18:05:30 +02001568struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
1569 struct ib_udata *udata)
1570{
1571 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001572 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Matan Barakd2370e02016-02-29 18:05:30 +02001573 struct mlx5_ib_mw *mw = NULL;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001574 u32 *in = NULL;
1575 void *mkc;
Matan Barakd2370e02016-02-29 18:05:30 +02001576 int ndescs;
1577 int err;
1578 struct mlx5_ib_alloc_mw req = {};
1579 struct {
1580 __u32 comp_mask;
1581 __u32 response_length;
1582 } resp = {};
1583
1584 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
1585 if (err)
1586 return ERR_PTR(err);
1587
1588 if (req.comp_mask || req.reserved1 || req.reserved2)
1589 return ERR_PTR(-EOPNOTSUPP);
1590
1591 if (udata->inlen > sizeof(req) &&
1592 !ib_is_udata_cleared(udata, sizeof(req),
1593 udata->inlen - sizeof(req)))
1594 return ERR_PTR(-EOPNOTSUPP);
1595
1596 ndescs = req.num_klms ? roundup(req.num_klms, 4) : roundup(1, 4);
1597
1598 mw = kzalloc(sizeof(*mw), GFP_KERNEL);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001599 in = kzalloc(inlen, GFP_KERNEL);
Matan Barakd2370e02016-02-29 18:05:30 +02001600 if (!mw || !in) {
1601 err = -ENOMEM;
1602 goto free;
1603 }
1604
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001605 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Matan Barakd2370e02016-02-29 18:05:30 +02001606
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001607 MLX5_SET(mkc, mkc, free, 1);
1608 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1609 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1610 MLX5_SET(mkc, mkc, umr_en, 1);
1611 MLX5_SET(mkc, mkc, lr, 1);
1612 MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_KLMS);
1613 MLX5_SET(mkc, mkc, en_rinval, !!((type == IB_MW_TYPE_2)));
1614 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1615
1616 err = mlx5_core_create_mkey(dev->mdev, &mw->mmkey, in, inlen);
Matan Barakd2370e02016-02-29 18:05:30 +02001617 if (err)
1618 goto free;
1619
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +02001620 mw->mmkey.type = MLX5_MKEY_MW;
Matan Barakd2370e02016-02-29 18:05:30 +02001621 mw->ibmw.rkey = mw->mmkey.key;
1622
1623 resp.response_length = min(offsetof(typeof(resp), response_length) +
1624 sizeof(resp.response_length), udata->outlen);
1625 if (resp.response_length) {
1626 err = ib_copy_to_udata(udata, &resp, resp.response_length);
1627 if (err) {
1628 mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
1629 goto free;
1630 }
1631 }
1632
1633 kfree(in);
1634 return &mw->ibmw;
1635
1636free:
1637 kfree(mw);
1638 kfree(in);
1639 return ERR_PTR(err);
1640}
1641
1642int mlx5_ib_dealloc_mw(struct ib_mw *mw)
1643{
1644 struct mlx5_ib_mw *mmw = to_mmw(mw);
1645 int err;
1646
1647 err = mlx5_core_destroy_mkey((to_mdev(mw->device))->mdev,
1648 &mmw->mmkey);
1649 if (!err)
1650 kfree(mmw);
1651 return err;
1652}
1653
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02001654int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
1655 struct ib_mr_status *mr_status)
1656{
1657 struct mlx5_ib_mr *mmr = to_mmr(ibmr);
1658 int ret = 0;
1659
1660 if (check_mask & ~IB_MR_CHECK_SIG_STATUS) {
1661 pr_err("Invalid status check mask\n");
1662 ret = -EINVAL;
1663 goto done;
1664 }
1665
1666 mr_status->fail_status = 0;
1667 if (check_mask & IB_MR_CHECK_SIG_STATUS) {
1668 if (!mmr->sig) {
1669 ret = -EINVAL;
1670 pr_err("signature status check requested on a non-signature enabled MR\n");
1671 goto done;
1672 }
1673
1674 mmr->sig->sig_status_checked = true;
1675 if (!mmr->sig->sig_err_exists)
1676 goto done;
1677
1678 if (ibmr->lkey == mmr->sig->err_item.key)
1679 memcpy(&mr_status->sig_err, &mmr->sig->err_item,
1680 sizeof(mr_status->sig_err));
1681 else {
1682 mr_status->sig_err.err_type = IB_SIG_BAD_GUARD;
1683 mr_status->sig_err.sig_err_offset = 0;
1684 mr_status->sig_err.key = mmr->sig->err_item.key;
1685 }
1686
1687 mmr->sig->sig_err_exists = false;
1688 mr_status->fail_status |= IB_MR_CHECK_SIG_STATUS;
1689 }
1690
1691done:
1692 return ret;
1693}
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001694
Sagi Grimbergb005d312016-02-29 19:07:33 +02001695static int
1696mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr,
1697 struct scatterlist *sgl,
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001698 unsigned short sg_nents,
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001699 unsigned int *sg_offset_p)
Sagi Grimbergb005d312016-02-29 19:07:33 +02001700{
1701 struct scatterlist *sg = sgl;
1702 struct mlx5_klm *klms = mr->descs;
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001703 unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001704 u32 lkey = mr->ibmr.pd->local_dma_lkey;
1705 int i;
1706
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001707 mr->ibmr.iova = sg_dma_address(sg) + sg_offset;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001708 mr->ibmr.length = 0;
1709 mr->ndescs = sg_nents;
1710
1711 for_each_sg(sgl, sg, sg_nents, i) {
1712 if (unlikely(i > mr->max_descs))
1713 break;
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001714 klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset);
1715 klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001716 klms[i].key = cpu_to_be32(lkey);
1717 mr->ibmr.length += sg_dma_len(sg);
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001718
1719 sg_offset = 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001720 }
1721
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001722 if (sg_offset_p)
1723 *sg_offset_p = sg_offset;
1724
Sagi Grimbergb005d312016-02-29 19:07:33 +02001725 return i;
1726}
1727
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001728static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
1729{
1730 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1731 __be64 *descs;
1732
1733 if (unlikely(mr->ndescs == mr->max_descs))
1734 return -ENOMEM;
1735
1736 descs = mr->descs;
1737 descs[mr->ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
1738
1739 return 0;
1740}
1741
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001742int mlx5_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
Bart Van Assche9aa8b322016-05-12 10:49:15 -07001743 unsigned int *sg_offset)
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001744{
1745 struct mlx5_ib_mr *mr = to_mmr(ibmr);
1746 int n;
1747
1748 mr->ndescs = 0;
1749
1750 ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
1751 mr->desc_size * mr->max_descs,
1752 DMA_TO_DEVICE);
1753
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001754 if (mr->access_mode == MLX5_MKC_ACCESS_MODE_KLMS)
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001755 n = mlx5_ib_sg_to_klms(mr, sg, sg_nents, sg_offset);
Sagi Grimbergb005d312016-02-29 19:07:33 +02001756 else
Christoph Hellwigff2ba992016-05-03 18:01:04 +02001757 n = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset,
1758 mlx5_set_page);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001759
1760 ib_dma_sync_single_for_device(ibmr->device, mr->desc_map,
1761 mr->desc_size * mr->max_descs,
1762 DMA_TO_DEVICE);
1763
1764 return n;
1765}