blob: f79bb44b94fe8be571ecb4b5cd57273e8b793000 [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
Leon Romanovskyeeea6952018-03-13 15:29:28 +020050static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
51static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +030052static int mr_cache_max_order(struct mlx5_ib_dev *dev);
Majd Dibbinyc8d75a92018-03-22 15:34:04 +020053
54static bool umr_can_use_indirect_mkey(struct mlx5_ib_dev *dev)
55{
56 return !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled);
57}
58
Haggai Eranb4cfe442014-12-11 17:04:26 +020059static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
60{
Jason Gunthorpe806b1012019-10-09 13:09:23 -030061 WARN_ON(xa_load(&dev->odp_mkeys, mlx5_base_mkey(mr->mmkey.key)));
Haggai Eranb4cfe442014-12-11 17:04:26 +020062
Jason Gunthorpe806b1012019-10-09 13:09:23 -030063 return mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
Haggai Eranb4cfe442014-12-11 17:04:26 +020064}
65
Eli Cohene126ba92013-07-07 17:25:49 +030066static int order2idx(struct mlx5_ib_dev *dev, int order)
67{
68 struct mlx5_mr_cache *cache = &dev->cache;
69
70 if (order < cache->ent[0].order)
71 return 0;
72 else
73 return order - cache->ent[0].order;
74}
75
Noa Osherovich56e11d62016-02-29 16:46:51 +020076static bool use_umr_mtt_update(struct mlx5_ib_mr *mr, u64 start, u64 length)
77{
78 return ((u64)1 << mr->order) * MLX5_ADAPTER_PAGE_SIZE >=
79 length + (start & (MLX5_ADAPTER_PAGE_SIZE - 1));
80}
81
Jason Gunthorpee3554772019-01-18 16:33:10 -080082static void reg_mr_callback(int status, struct mlx5_async_work *context)
Eli Cohen746b5582013-10-23 09:53:14 +030083{
Jason Gunthorpee3554772019-01-18 16:33:10 -080084 struct mlx5_ib_mr *mr =
85 container_of(context, struct mlx5_ib_mr, cb_work);
Eli Cohen746b5582013-10-23 09:53:14 +030086 struct mlx5_ib_dev *dev = mr->dev;
87 struct mlx5_mr_cache *cache = &dev->cache;
88 int c = order2idx(dev, mr->order);
89 struct mlx5_cache_ent *ent = &cache->ent[c];
90 u8 key;
Eli Cohen746b5582013-10-23 09:53:14 +030091 unsigned long flags;
92
Eli Cohen746b5582013-10-23 09:53:14 +030093 spin_lock_irqsave(&ent->lock, flags);
94 ent->pending--;
95 spin_unlock_irqrestore(&ent->lock, flags);
96 if (status) {
97 mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
98 kfree(mr);
99 dev->fill_delay = 1;
100 mod_timer(&dev->delay_timer, jiffies + HZ);
101 return;
102 }
103
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +0200104 mr->mmkey.type = MLX5_MKEY_MR;
Jack Morgenstein9603b612014-07-28 23:30:22 +0300105 spin_lock_irqsave(&dev->mdev->priv.mkey_lock, flags);
106 key = dev->mdev->priv.mkey_key++;
107 spin_unlock_irqrestore(&dev->mdev->priv.mkey_lock, flags);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300108 mr->mmkey.key = mlx5_idx_to_mkey(MLX5_GET(create_mkey_out, mr->out, mkey_index)) | key;
Eli Cohen746b5582013-10-23 09:53:14 +0300109
110 cache->last_add = jiffies;
111
112 spin_lock_irqsave(&ent->lock, flags);
113 list_add_tail(&mr->list, &ent->head);
114 ent->cur++;
115 ent->size++;
116 spin_unlock_irqrestore(&ent->lock, flags);
Haggai Eran86059332014-05-22 14:50:09 +0300117
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200118 if (!completion_done(&ent->compl))
119 complete(&ent->compl);
Eli Cohen746b5582013-10-23 09:53:14 +0300120}
121
Eli Cohene126ba92013-07-07 17:25:49 +0300122static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
123{
Eli Cohene126ba92013-07-07 17:25:49 +0300124 struct mlx5_mr_cache *cache = &dev->cache;
125 struct mlx5_cache_ent *ent = &cache->ent[c];
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300126 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Eli Cohene126ba92013-07-07 17:25:49 +0300127 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300128 void *mkc;
129 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300130 int err = 0;
131 int i;
132
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300133 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300134 if (!in)
135 return -ENOMEM;
136
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300137 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300138 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300139 if (ent->pending >= MAX_PENDING_REG_MR) {
140 err = -EAGAIN;
141 break;
142 }
143
Eli Cohene126ba92013-07-07 17:25:49 +0300144 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
145 if (!mr) {
146 err = -ENOMEM;
Eli Cohen746b5582013-10-23 09:53:14 +0300147 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300148 }
149 mr->order = ent->order;
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300150 mr->allocated_from_cache = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300151 mr->dev = dev;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300152
153 MLX5_SET(mkc, mkc, free, 1);
154 MLX5_SET(mkc, mkc, umr_en, 1);
Ariel Levkovichcdbd0d22018-04-05 18:53:28 +0300155 MLX5_SET(mkc, mkc, access_mode_1_0, ent->access_mode & 0x3);
156 MLX5_SET(mkc, mkc, access_mode_4_2,
157 (ent->access_mode >> 2) & 0x7);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300158
159 MLX5_SET(mkc, mkc, qpn, 0xffffff);
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200160 MLX5_SET(mkc, mkc, translations_octword_size, ent->xlt);
161 MLX5_SET(mkc, mkc, log_page_size, ent->page);
Eli Cohene126ba92013-07-07 17:25:49 +0300162
Eli Cohen746b5582013-10-23 09:53:14 +0300163 spin_lock_irq(&ent->lock);
164 ent->pending++;
165 spin_unlock_irq(&ent->lock);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300166 err = mlx5_core_create_mkey_cb(dev->mdev, &mr->mmkey,
Jason Gunthorpee3554772019-01-18 16:33:10 -0800167 &dev->async_ctx, in, inlen,
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300168 mr->out, sizeof(mr->out),
Jason Gunthorpee3554772019-01-18 16:33:10 -0800169 reg_mr_callback, &mr->cb_work);
Eli Cohene126ba92013-07-07 17:25:49 +0300170 if (err) {
Eli Cohend14e7112014-12-02 12:26:19 +0200171 spin_lock_irq(&ent->lock);
172 ent->pending--;
173 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300174 mlx5_ib_warn(dev, "create mkey failed %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300175 kfree(mr);
Eli Cohen746b5582013-10-23 09:53:14 +0300176 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300177 }
Eli Cohene126ba92013-07-07 17:25:49 +0300178 }
179
Eli Cohene126ba92013-07-07 17:25:49 +0300180 kfree(in);
181 return err;
182}
183
184static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
185{
Eli Cohene126ba92013-07-07 17:25:49 +0300186 struct mlx5_mr_cache *cache = &dev->cache;
187 struct mlx5_cache_ent *ent = &cache->ent[c];
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200188 struct mlx5_ib_mr *tmp_mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300189 struct mlx5_ib_mr *mr;
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200190 LIST_HEAD(del_list);
Eli Cohene126ba92013-07-07 17:25:49 +0300191 int i;
192
193 for (i = 0; i < num; i++) {
Eli Cohen746b5582013-10-23 09:53:14 +0300194 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300195 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300196 spin_unlock_irq(&ent->lock);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200197 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300198 }
199 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200200 list_move(&mr->list, &del_list);
Eli Cohene126ba92013-07-07 17:25:49 +0300201 ent->cur--;
202 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300203 spin_unlock_irq(&ent->lock);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200204 mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
205 }
206
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200207 list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
208 list_del(&mr->list);
209 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300210 }
211}
212
213static ssize_t size_write(struct file *filp, const char __user *buf,
214 size_t count, loff_t *pos)
215{
216 struct mlx5_cache_ent *ent = filp->private_data;
217 struct mlx5_ib_dev *dev = ent->dev;
Jann Horn60e66272018-07-06 22:48:03 +0200218 char lbuf[20] = {0};
Eli Cohene126ba92013-07-07 17:25:49 +0300219 u32 var;
220 int err;
221 int c;
222
Jann Horn60e66272018-07-06 22:48:03 +0200223 count = min(count, sizeof(lbuf) - 1);
224 if (copy_from_user(lbuf, buf, count))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300225 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300226
227 c = order2idx(dev, ent->order);
Eli Cohene126ba92013-07-07 17:25:49 +0300228
229 if (sscanf(lbuf, "%u", &var) != 1)
230 return -EINVAL;
231
232 if (var < ent->limit)
233 return -EINVAL;
234
235 if (var > ent->size) {
Eli Cohen746b5582013-10-23 09:53:14 +0300236 do {
237 err = add_keys(dev, c, var - ent->size);
238 if (err && err != -EAGAIN)
239 return err;
240
241 usleep_range(3000, 5000);
242 } while (err);
Eli Cohene126ba92013-07-07 17:25:49 +0300243 } else if (var < ent->size) {
244 remove_keys(dev, c, ent->size - var);
245 }
246
247 return count;
248}
249
250static ssize_t size_read(struct file *filp, char __user *buf, size_t count,
251 loff_t *pos)
252{
253 struct mlx5_cache_ent *ent = filp->private_data;
254 char lbuf[20];
255 int err;
256
Eli Cohene126ba92013-07-07 17:25:49 +0300257 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->size);
258 if (err < 0)
259 return err;
260
Jann Horn60e66272018-07-06 22:48:03 +0200261 return simple_read_from_buffer(buf, count, pos, lbuf, err);
Eli Cohene126ba92013-07-07 17:25:49 +0300262}
263
264static const struct file_operations size_fops = {
265 .owner = THIS_MODULE,
266 .open = simple_open,
267 .write = size_write,
268 .read = size_read,
269};
270
271static ssize_t limit_write(struct file *filp, const char __user *buf,
272 size_t count, loff_t *pos)
273{
274 struct mlx5_cache_ent *ent = filp->private_data;
275 struct mlx5_ib_dev *dev = ent->dev;
Jann Horn60e66272018-07-06 22:48:03 +0200276 char lbuf[20] = {0};
Eli Cohene126ba92013-07-07 17:25:49 +0300277 u32 var;
278 int err;
279 int c;
280
Jann Horn60e66272018-07-06 22:48:03 +0200281 count = min(count, sizeof(lbuf) - 1);
282 if (copy_from_user(lbuf, buf, count))
Dan Carpenter5e631a02013-07-10 13:58:59 +0300283 return -EFAULT;
Eli Cohene126ba92013-07-07 17:25:49 +0300284
285 c = order2idx(dev, ent->order);
Eli Cohene126ba92013-07-07 17:25:49 +0300286
287 if (sscanf(lbuf, "%u", &var) != 1)
288 return -EINVAL;
289
290 if (var > ent->size)
291 return -EINVAL;
292
293 ent->limit = var;
294
295 if (ent->cur < ent->limit) {
296 err = add_keys(dev, c, 2 * ent->limit - ent->cur);
297 if (err)
298 return err;
299 }
300
301 return count;
302}
303
304static ssize_t limit_read(struct file *filp, char __user *buf, size_t count,
305 loff_t *pos)
306{
307 struct mlx5_cache_ent *ent = filp->private_data;
308 char lbuf[20];
309 int err;
310
Eli Cohene126ba92013-07-07 17:25:49 +0300311 err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->limit);
312 if (err < 0)
313 return err;
314
Jann Horn60e66272018-07-06 22:48:03 +0200315 return simple_read_from_buffer(buf, count, pos, lbuf, err);
Eli Cohene126ba92013-07-07 17:25:49 +0300316}
317
318static const struct file_operations limit_fops = {
319 .owner = THIS_MODULE,
320 .open = simple_open,
321 .write = limit_write,
322 .read = limit_read,
323};
324
325static int someone_adding(struct mlx5_mr_cache *cache)
326{
327 int i;
328
329 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
330 if (cache->ent[i].cur < cache->ent[i].limit)
331 return 1;
332 }
333
334 return 0;
335}
336
337static void __cache_work_func(struct mlx5_cache_ent *ent)
338{
339 struct mlx5_ib_dev *dev = ent->dev;
340 struct mlx5_mr_cache *cache = &dev->cache;
341 int i = order2idx(dev, ent->order);
Eli Cohen746b5582013-10-23 09:53:14 +0300342 int err;
Eli Cohene126ba92013-07-07 17:25:49 +0300343
344 if (cache->stopped)
345 return;
346
347 ent = &dev->cache.ent[i];
Eli Cohen746b5582013-10-23 09:53:14 +0300348 if (ent->cur < 2 * ent->limit && !dev->fill_delay) {
349 err = add_keys(dev, i, 1);
350 if (ent->cur < 2 * ent->limit) {
351 if (err == -EAGAIN) {
352 mlx5_ib_dbg(dev, "returned eagain, order %d\n",
353 i + 2);
354 queue_delayed_work(cache->wq, &ent->dwork,
355 msecs_to_jiffies(3));
356 } else if (err) {
357 mlx5_ib_warn(dev, "command failed order %d, err %d\n",
358 i + 2, err);
359 queue_delayed_work(cache->wq, &ent->dwork,
360 msecs_to_jiffies(1000));
361 } else {
362 queue_work(cache->wq, &ent->work);
363 }
364 }
Eli Cohene126ba92013-07-07 17:25:49 +0300365 } else if (ent->cur > 2 * ent->limit) {
Leon Romanovskyab5cdc32015-10-21 09:21:17 +0300366 /*
367 * The remove_keys() logic is performed as garbage collection
368 * task. Such task is intended to be run when no other active
369 * processes are running.
370 *
371 * The need_resched() will return TRUE if there are user tasks
372 * to be activated in near future.
373 *
374 * In such case, we don't execute remove_keys() and postpone
375 * the garbage collection work to try to run in next cycle,
376 * in order to free CPU resources to other tasks.
377 */
378 if (!need_resched() && !someone_adding(cache) &&
Eli Cohen746b5582013-10-23 09:53:14 +0300379 time_after(jiffies, cache->last_add + 300 * HZ)) {
Eli Cohene126ba92013-07-07 17:25:49 +0300380 remove_keys(dev, i, 1);
381 if (ent->cur > ent->limit)
382 queue_work(cache->wq, &ent->work);
383 } else {
Eli Cohen746b5582013-10-23 09:53:14 +0300384 queue_delayed_work(cache->wq, &ent->dwork, 300 * HZ);
Eli Cohene126ba92013-07-07 17:25:49 +0300385 }
386 }
387}
388
389static void delayed_cache_work_func(struct work_struct *work)
390{
391 struct mlx5_cache_ent *ent;
392
393 ent = container_of(work, struct mlx5_cache_ent, dwork.work);
394 __cache_work_func(ent);
395}
396
397static void cache_work_func(struct work_struct *work)
398{
399 struct mlx5_cache_ent *ent;
400
401 ent = container_of(work, struct mlx5_cache_ent, work);
402 __cache_work_func(ent);
403}
404
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200405struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev, int entry)
406{
407 struct mlx5_mr_cache *cache = &dev->cache;
408 struct mlx5_cache_ent *ent;
409 struct mlx5_ib_mr *mr;
410 int err;
411
412 if (entry < 0 || entry >= MAX_MR_CACHE_ENTRIES) {
413 mlx5_ib_err(dev, "cache entry %d is out of range\n", entry);
Leon Romanovsky546d3002019-10-29 07:57:21 +0200414 return ERR_PTR(-EINVAL);
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200415 }
416
417 ent = &cache->ent[entry];
418 while (1) {
419 spin_lock_irq(&ent->lock);
420 if (list_empty(&ent->head)) {
421 spin_unlock_irq(&ent->lock);
422
423 err = add_keys(dev, entry, 1);
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200424 if (err && err != -EAGAIN)
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200425 return ERR_PTR(err);
426
427 wait_for_completion(&ent->compl);
428 } else {
429 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
430 list);
431 list_del(&mr->list);
432 ent->cur--;
433 spin_unlock_irq(&ent->lock);
434 if (ent->cur < ent->limit)
435 queue_work(cache->wq, &ent->work);
436 return mr;
437 }
438 }
439}
440
Eli Cohene126ba92013-07-07 17:25:49 +0300441static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
442{
443 struct mlx5_mr_cache *cache = &dev->cache;
444 struct mlx5_ib_mr *mr = NULL;
445 struct mlx5_cache_ent *ent;
Majd Dibbiny4c25b7a2017-06-12 10:36:15 +0300446 int last_umr_cache_entry;
Eli Cohene126ba92013-07-07 17:25:49 +0300447 int c;
448 int i;
449
450 c = order2idx(dev, order);
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300451 last_umr_cache_entry = order2idx(dev, mr_cache_max_order(dev));
Majd Dibbiny4c25b7a2017-06-12 10:36:15 +0300452 if (c < 0 || c > last_umr_cache_entry) {
Eli Cohene126ba92013-07-07 17:25:49 +0300453 mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
454 return NULL;
455 }
456
Majd Dibbiny4c25b7a2017-06-12 10:36:15 +0300457 for (i = c; i <= last_umr_cache_entry; i++) {
Eli Cohene126ba92013-07-07 17:25:49 +0300458 ent = &cache->ent[i];
459
460 mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
461
Eli Cohen746b5582013-10-23 09:53:14 +0300462 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300463 if (!list_empty(&ent->head)) {
464 mr = list_first_entry(&ent->head, struct mlx5_ib_mr,
465 list);
466 list_del(&mr->list);
467 ent->cur--;
Eli Cohen746b5582013-10-23 09:53:14 +0300468 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300469 if (ent->cur < ent->limit)
470 queue_work(cache->wq, &ent->work);
471 break;
472 }
Eli Cohen746b5582013-10-23 09:53:14 +0300473 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300474
475 queue_work(cache->wq, &ent->work);
Eli Cohene126ba92013-07-07 17:25:49 +0300476 }
477
478 if (!mr)
479 cache->ent[c].miss++;
480
481 return mr;
482}
483
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200484void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
Eli Cohene126ba92013-07-07 17:25:49 +0300485{
486 struct mlx5_mr_cache *cache = &dev->cache;
487 struct mlx5_cache_ent *ent;
488 int shrink = 0;
489 int c;
490
Valentine Fatievdd9a4032018-10-10 09:56:25 +0300491 if (!mr->allocated_from_cache)
492 return;
493
Eli Cohene126ba92013-07-07 17:25:49 +0300494 c = order2idx(dev, mr->order);
Yishai Hadasafd14172019-07-23 09:57:26 +0300495 WARN_ON(c < 0 || c >= MAX_MR_CACHE_ENTRIES);
496
Jason Gunthorpe09689702019-10-09 13:09:34 -0300497 if (mlx5_mr_cache_invalidate(mr)) {
Yishai Hadasafd14172019-07-23 09:57:26 +0300498 mr->allocated_from_cache = false;
499 destroy_mkey(dev, mr);
500 ent = &cache->ent[c];
501 if (ent->cur < ent->limit)
502 queue_work(cache->wq, &ent->work);
Eli Cohene126ba92013-07-07 17:25:49 +0300503 return;
504 }
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200505
Eli Cohene126ba92013-07-07 17:25:49 +0300506 ent = &cache->ent[c];
Eli Cohen746b5582013-10-23 09:53:14 +0300507 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300508 list_add_tail(&mr->list, &ent->head);
509 ent->cur++;
510 if (ent->cur > 2 * ent->limit)
511 shrink = 1;
Eli Cohen746b5582013-10-23 09:53:14 +0300512 spin_unlock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300513
514 if (shrink)
515 queue_work(cache->wq, &ent->work);
516}
517
518static void clean_keys(struct mlx5_ib_dev *dev, int c)
519{
Eli Cohene126ba92013-07-07 17:25:49 +0300520 struct mlx5_mr_cache *cache = &dev->cache;
521 struct mlx5_cache_ent *ent = &cache->ent[c];
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200522 struct mlx5_ib_mr *tmp_mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300523 struct mlx5_ib_mr *mr;
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200524 LIST_HEAD(del_list);
Eli Cohene126ba92013-07-07 17:25:49 +0300525
Moshe Lazer3c461912013-09-11 16:35:23 +0300526 cancel_delayed_work(&ent->dwork);
Eli Cohene126ba92013-07-07 17:25:49 +0300527 while (1) {
Eli Cohen746b5582013-10-23 09:53:14 +0300528 spin_lock_irq(&ent->lock);
Eli Cohene126ba92013-07-07 17:25:49 +0300529 if (list_empty(&ent->head)) {
Eli Cohen746b5582013-10-23 09:53:14 +0300530 spin_unlock_irq(&ent->lock);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200531 break;
Eli Cohene126ba92013-07-07 17:25:49 +0300532 }
533 mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200534 list_move(&mr->list, &del_list);
Eli Cohene126ba92013-07-07 17:25:49 +0300535 ent->cur--;
536 ent->size--;
Eli Cohen746b5582013-10-23 09:53:14 +0300537 spin_unlock_irq(&ent->lock);
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200538 mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
539 }
540
Daniel Jurgens65edd0e2018-03-13 15:18:47 +0200541 list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
542 list_del(&mr->list);
543 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +0300544 }
545}
546
Leon Romanovsky12cc1a02017-05-30 09:44:48 +0300547static void mlx5_mr_cache_debugfs_cleanup(struct mlx5_ib_dev *dev)
548{
Mark Bloch6a4d00b2019-03-28 15:27:37 +0200549 if (!mlx5_debugfs_root || dev->is_rep)
Leon Romanovsky12cc1a02017-05-30 09:44:48 +0300550 return;
551
552 debugfs_remove_recursive(dev->cache.root);
553 dev->cache.root = NULL;
554}
555
Greg Kroah-Hartman73eb8f02019-01-22 16:17:57 +0100556static void mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev)
Eli Cohene126ba92013-07-07 17:25:49 +0300557{
558 struct mlx5_mr_cache *cache = &dev->cache;
559 struct mlx5_cache_ent *ent;
Greg Kroah-Hartman73eb8f02019-01-22 16:17:57 +0100560 struct dentry *dir;
Eli Cohene126ba92013-07-07 17:25:49 +0300561 int i;
562
Mark Bloch6a4d00b2019-03-28 15:27:37 +0200563 if (!mlx5_debugfs_root || dev->is_rep)
Greg Kroah-Hartman73eb8f02019-01-22 16:17:57 +0100564 return;
Eli Cohene126ba92013-07-07 17:25:49 +0300565
Jack Morgenstein9603b612014-07-28 23:30:22 +0300566 cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
Eli Cohene126ba92013-07-07 17:25:49 +0300567
568 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
569 ent = &cache->ent[i];
570 sprintf(ent->name, "%d", ent->order);
Greg Kroah-Hartman73eb8f02019-01-22 16:17:57 +0100571 dir = debugfs_create_dir(ent->name, cache->root);
572 debugfs_create_file("size", 0600, dir, ent, &size_fops);
573 debugfs_create_file("limit", 0600, dir, ent, &limit_fops);
574 debugfs_create_u32("cur", 0400, dir, &ent->cur);
575 debugfs_create_u32("miss", 0600, dir, &ent->miss);
Eli Cohene126ba92013-07-07 17:25:49 +0300576 }
Eli Cohene126ba92013-07-07 17:25:49 +0300577}
578
Kees Cooke99e88a2017-10-16 14:43:17 -0700579static void delay_time_func(struct timer_list *t)
Eli Cohen746b5582013-10-23 09:53:14 +0300580{
Kees Cooke99e88a2017-10-16 14:43:17 -0700581 struct mlx5_ib_dev *dev = from_timer(dev, t, delay_timer);
Eli Cohen746b5582013-10-23 09:53:14 +0300582
583 dev->fill_delay = 0;
584}
585
Eli Cohene126ba92013-07-07 17:25:49 +0300586int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
587{
588 struct mlx5_mr_cache *cache = &dev->cache;
589 struct mlx5_cache_ent *ent;
Eli Cohene126ba92013-07-07 17:25:49 +0300590 int i;
591
Moshe Lazer6bc1a652016-10-27 16:36:42 +0300592 mutex_init(&dev->slow_path_mutex);
Bhaktipriya Shridhar3c856c82016-08-15 23:41:18 +0530593 cache->wq = alloc_ordered_workqueue("mkey_cache", WQ_MEM_RECLAIM);
Eli Cohene126ba92013-07-07 17:25:49 +0300594 if (!cache->wq) {
595 mlx5_ib_warn(dev, "failed to create work queue\n");
596 return -ENOMEM;
597 }
598
Jason Gunthorpee3554772019-01-18 16:33:10 -0800599 mlx5_cmd_init_async_ctx(dev->mdev, &dev->async_ctx);
Kees Cooke99e88a2017-10-16 14:43:17 -0700600 timer_setup(&dev->delay_timer, delay_time_func, 0);
Eli Cohene126ba92013-07-07 17:25:49 +0300601 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
Eli Cohene126ba92013-07-07 17:25:49 +0300602 ent = &cache->ent[i];
603 INIT_LIST_HEAD(&ent->head);
604 spin_lock_init(&ent->lock);
605 ent->order = i + 2;
606 ent->dev = dev;
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200607 ent->limit = 0;
Eli Cohene126ba92013-07-07 17:25:49 +0300608
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200609 init_completion(&ent->compl);
Eli Cohene126ba92013-07-07 17:25:49 +0300610 INIT_WORK(&ent->work, cache_work_func);
611 INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func);
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200612
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300613 if (i > MR_CACHE_LAST_STD_ENTRY) {
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200614 mlx5_odp_init_mr_cache_entry(ent);
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200615 continue;
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200616 }
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200617
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300618 if (ent->order > mr_cache_max_order(dev))
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200619 continue;
620
621 ent->page = PAGE_SHIFT;
622 ent->xlt = (1 << ent->order) * sizeof(struct mlx5_mtt) /
623 MLX5_IB_UMR_OCTOWORD;
624 ent->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
625 if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
Mark Bloch6a4d00b2019-03-28 15:27:37 +0200626 !dev->is_rep &&
Artemy Kovalyov49780d42017-01-18 16:58:10 +0200627 mlx5_core_is_pf(dev->mdev))
628 ent->limit = dev->mdev->profile->mr_cache[i].limit;
629 else
630 ent->limit = 0;
Artemy Kovalyov013c2402018-10-15 14:13:35 +0300631 queue_work(cache->wq, &ent->work);
Eli Cohene126ba92013-07-07 17:25:49 +0300632 }
633
Greg Kroah-Hartman73eb8f02019-01-22 16:17:57 +0100634 mlx5_mr_cache_debugfs_init(dev);
Leon Romanovsky12cc1a02017-05-30 09:44:48 +0300635
Eli Cohene126ba92013-07-07 17:25:49 +0300636 return 0;
637}
638
639int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
640{
641 int i;
642
Mark Bloch32927e22018-03-20 15:45:37 +0200643 if (!dev->cache.wq)
644 return 0;
645
Eli Cohene126ba92013-07-07 17:25:49 +0300646 dev->cache.stopped = 1;
Moshe Lazer3c461912013-09-11 16:35:23 +0300647 flush_workqueue(dev->cache.wq);
Eli Cohene126ba92013-07-07 17:25:49 +0300648
649 mlx5_mr_cache_debugfs_cleanup(dev);
Jason Gunthorpee3554772019-01-18 16:33:10 -0800650 mlx5_cmd_cleanup_async_ctx(&dev->async_ctx);
Eli Cohene126ba92013-07-07 17:25:49 +0300651
652 for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
653 clean_keys(dev, i);
654
Moshe Lazer3c461912013-09-11 16:35:23 +0300655 destroy_workqueue(dev->cache.wq);
Eli Cohen746b5582013-10-23 09:53:14 +0300656 del_timer_sync(&dev->delay_timer);
Moshe Lazer3c461912013-09-11 16:35:23 +0300657
Eli Cohene126ba92013-07-07 17:25:49 +0300658 return 0;
659}
660
Parav Pandit03232cc2019-10-06 18:54:43 +0300661static void set_mkc_access_pd_addr_fields(void *mkc, int acc, u64 start_addr,
662 struct ib_pd *pd)
663{
664 MLX5_SET(mkc, mkc, a, !!(acc & IB_ACCESS_REMOTE_ATOMIC));
665 MLX5_SET(mkc, mkc, rw, !!(acc & IB_ACCESS_REMOTE_WRITE));
666 MLX5_SET(mkc, mkc, rr, !!(acc & IB_ACCESS_REMOTE_READ));
667 MLX5_SET(mkc, mkc, lw, !!(acc & IB_ACCESS_LOCAL_WRITE));
668 MLX5_SET(mkc, mkc, lr, 1);
669
670 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
671 MLX5_SET(mkc, mkc, qpn, 0xffffff);
672 MLX5_SET64(mkc, mkc, start_addr, start_addr);
673}
674
Eli Cohene126ba92013-07-07 17:25:49 +0300675struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
676{
677 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300678 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Jack Morgenstein9603b612014-07-28 23:30:22 +0300679 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +0300680 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300681 void *mkc;
682 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +0300683 int err;
684
685 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
686 if (!mr)
687 return ERR_PTR(-ENOMEM);
688
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300689 in = kzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +0300690 if (!in) {
691 err = -ENOMEM;
692 goto err_free;
693 }
694
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300695 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Eli Cohene126ba92013-07-07 17:25:49 +0300696
Ariel Levkovichcdbd0d22018-04-05 18:53:28 +0300697 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300698 MLX5_SET(mkc, mkc, length64, 1);
Parav Pandit03232cc2019-10-06 18:54:43 +0300699 set_mkc_access_pd_addr_fields(mkc, acc, 0, pd);
Saeed Mahameedec22eb52016-07-16 06:28:36 +0300700
701 err = mlx5_core_create_mkey(mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +0300702 if (err)
703 goto err_in;
704
705 kfree(in);
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +0200706 mr->mmkey.type = MLX5_MKEY_MR;
Matan Baraka606b0f2016-02-29 18:05:28 +0200707 mr->ibmr.lkey = mr->mmkey.key;
708 mr->ibmr.rkey = mr->mmkey.key;
Eli Cohene126ba92013-07-07 17:25:49 +0300709 mr->umem = NULL;
710
711 return &mr->ibmr;
712
713err_in:
714 kfree(in);
715
716err_free:
717 kfree(mr);
718
719 return ERR_PTR(err);
720}
721
Ilya Lesokhin7b4cdaa2017-08-17 15:52:32 +0300722static int get_octo_len(u64 addr, u64 len, int page_shift)
Eli Cohene126ba92013-07-07 17:25:49 +0300723{
Ilya Lesokhin7b4cdaa2017-08-17 15:52:32 +0300724 u64 page_size = 1ULL << page_shift;
Eli Cohene126ba92013-07-07 17:25:49 +0300725 u64 offset;
726 int npages;
727
728 offset = addr & (page_size - 1);
Ilya Lesokhin7b4cdaa2017-08-17 15:52:32 +0300729 npages = ALIGN(len + offset, page_size) >> page_shift;
Eli Cohene126ba92013-07-07 17:25:49 +0300730 return (npages + 1) / 2;
731}
732
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300733static int mr_cache_max_order(struct mlx5_ib_dev *dev)
Eli Cohene126ba92013-07-07 17:25:49 +0300734{
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200735 if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +0300736 return MR_CACHE_LAST_STD_ENTRY + 2;
Majd Dibbiny4c25b7a2017-06-12 10:36:15 +0300737 return MLX5_MAX_UMR_SHIFT;
738}
739
Moni Shouac320e522020-01-15 14:43:31 +0200740static int mr_umem_get(struct mlx5_ib_dev *dev, u64 start, u64 length,
741 int access_flags, struct ib_umem **umem, int *npages,
742 int *page_shift, int *ncont, int *order)
Noa Osherovich395a8e42016-02-29 16:46:50 +0200743{
Leon Romanovskyb4bd7012018-04-23 17:01:52 +0300744 struct ib_umem *u;
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200745
Leon Romanovskyb4bd7012018-04-23 17:01:52 +0300746 *umem = NULL;
747
Jason Gunthorpe261dc532019-08-19 14:17:04 +0300748 if (access_flags & IB_ACCESS_ON_DEMAND) {
749 struct ib_umem_odp *odp;
750
Moni Shouac320e522020-01-15 14:43:31 +0200751 odp = ib_umem_odp_get(&dev->ib_dev, start, length, access_flags,
Jason Gunthorpef25a5462019-11-12 16:22:22 -0400752 &mlx5_mn_ops);
Jason Gunthorpe261dc532019-08-19 14:17:04 +0300753 if (IS_ERR(odp)) {
754 mlx5_ib_dbg(dev, "umem get failed (%ld)\n",
755 PTR_ERR(odp));
756 return PTR_ERR(odp);
757 }
758
759 u = &odp->umem;
760
761 *page_shift = odp->page_shift;
762 *ncont = ib_umem_odp_num_pages(odp);
763 *npages = *ncont << (*page_shift - PAGE_SHIFT);
764 if (order)
765 *order = ilog2(roundup_pow_of_two(*ncont));
766 } else {
Moni Shouac320e522020-01-15 14:43:31 +0200767 u = ib_umem_get(&dev->ib_dev, start, length, access_flags);
Jason Gunthorpe261dc532019-08-19 14:17:04 +0300768 if (IS_ERR(u)) {
769 mlx5_ib_dbg(dev, "umem get failed (%ld)\n", PTR_ERR(u));
770 return PTR_ERR(u);
771 }
772
773 mlx5_ib_cont_pages(u, start, MLX5_MKEY_PAGE_SHIFT_MASK, npages,
774 page_shift, ncont, order);
Noa Osherovich395a8e42016-02-29 16:46:50 +0200775 }
776
Noa Osherovich395a8e42016-02-29 16:46:50 +0200777 if (!*npages) {
778 mlx5_ib_warn(dev, "avoid zero region\n");
Leon Romanovskyb4bd7012018-04-23 17:01:52 +0300779 ib_umem_release(u);
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200780 return -EINVAL;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200781 }
782
Leon Romanovskyb4bd7012018-04-23 17:01:52 +0300783 *umem = u;
784
Noa Osherovich395a8e42016-02-29 16:46:50 +0200785 mlx5_ib_dbg(dev, "npages %d, ncont %d, order %d, page_shift %d\n",
786 *npages, *ncont, *order, *page_shift);
787
Arnd Bergmann14ab8892016-10-24 22:48:21 +0200788 return 0;
Noa Osherovich395a8e42016-02-29 16:46:50 +0200789}
790
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100791static void mlx5_ib_umr_done(struct ib_cq *cq, struct ib_wc *wc)
Eli Cohene126ba92013-07-07 17:25:49 +0300792{
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100793 struct mlx5_ib_umr_context *context =
794 container_of(wc->wr_cqe, struct mlx5_ib_umr_context, cqe);
Eli Cohene126ba92013-07-07 17:25:49 +0300795
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100796 context->status = wc->status;
797 complete(&context->done);
798}
Eli Cohene126ba92013-07-07 17:25:49 +0300799
Christoph Hellwigadd08d72016-03-03 09:38:22 +0100800static inline void mlx5_ib_init_umr_context(struct mlx5_ib_umr_context *context)
801{
802 context->cqe.done = mlx5_ib_umr_done;
803 context->status = -1;
804 init_completion(&context->done);
Eli Cohene126ba92013-07-07 17:25:49 +0300805}
806
Binoy Jayand5ea2df2017-01-02 11:37:40 +0200807static int mlx5_ib_post_send_wait(struct mlx5_ib_dev *dev,
808 struct mlx5_umr_wr *umrwr)
809{
810 struct umr_common *umrc = &dev->umrc;
Bart Van Assched34ac5c2018-07-18 09:25:32 -0700811 const struct ib_send_wr *bad;
Binoy Jayand5ea2df2017-01-02 11:37:40 +0200812 int err;
813 struct mlx5_ib_umr_context umr_context;
814
815 mlx5_ib_init_umr_context(&umr_context);
816 umrwr->wr.wr_cqe = &umr_context.cqe;
817
818 down(&umrc->sem);
819 err = ib_post_send(umrc->qp, &umrwr->wr, &bad);
820 if (err) {
821 mlx5_ib_warn(dev, "UMR post send failed, err %d\n", err);
822 } else {
823 wait_for_completion(&umr_context.done);
824 if (umr_context.status != IB_WC_SUCCESS) {
825 mlx5_ib_warn(dev, "reg umr failed (%u)\n",
826 umr_context.status);
827 err = -EFAULT;
828 }
829 }
830 up(&umrc->sem);
831 return err;
832}
833
Ilya Lesokhinff740ae2017-08-17 15:52:30 +0300834static struct mlx5_ib_mr *alloc_mr_from_cache(
835 struct ib_pd *pd, struct ib_umem *umem,
Eli Cohene126ba92013-07-07 17:25:49 +0300836 u64 virt_addr, u64 len, int npages,
837 int page_shift, int order, int access_flags)
838{
839 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +0300840 struct mlx5_ib_mr *mr;
Haggai Eran096f7e72014-05-22 14:50:08 +0300841 int err = 0;
Eli Cohene126ba92013-07-07 17:25:49 +0300842 int i;
843
Eli Cohen746b5582013-10-23 09:53:14 +0300844 for (i = 0; i < 1; i++) {
Eli Cohene126ba92013-07-07 17:25:49 +0300845 mr = alloc_cached_mr(dev, order);
846 if (mr)
847 break;
848
849 err = add_keys(dev, order2idx(dev, order), 1);
Eli Cohen746b5582013-10-23 09:53:14 +0300850 if (err && err != -EAGAIN) {
851 mlx5_ib_warn(dev, "add_keys failed, err %d\n", err);
Eli Cohene126ba92013-07-07 17:25:49 +0300852 break;
853 }
854 }
855
856 if (!mr)
857 return ERR_PTR(-EAGAIN);
858
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200859 mr->ibmr.pd = pd;
860 mr->umem = umem;
861 mr->access_flags = access_flags;
862 mr->desc_size = sizeof(struct mlx5_mtt);
Matan Baraka606b0f2016-02-29 18:05:28 +0200863 mr->mmkey.iova = virt_addr;
864 mr->mmkey.size = len;
865 mr->mmkey.pd = to_mpd(pd)->pdn;
Haggai Eranb4755982014-05-22 14:50:10 +0300866
Eli Cohene126ba92013-07-07 17:25:49 +0300867 return mr;
Eli Cohene126ba92013-07-07 17:25:49 +0300868}
869
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200870static inline int populate_xlt(struct mlx5_ib_mr *mr, int idx, int npages,
871 void *xlt, int page_shift, size_t size,
872 int flags)
873{
874 struct mlx5_ib_dev *dev = mr->dev;
875 struct ib_umem *umem = mr->umem;
Majd Dibbinyc8d75a92018-03-22 15:34:04 +0200876
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200877 if (flags & MLX5_IB_UPD_XLT_INDIRECT) {
Majd Dibbinyc8d75a92018-03-22 15:34:04 +0200878 if (!umr_can_use_indirect_mkey(dev))
879 return -EPERM;
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200880 mlx5_odp_populate_klm(xlt, idx, npages, mr, flags);
881 return npages;
882 }
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200883
884 npages = min_t(size_t, npages, ib_umem_num_pages(umem) - idx);
885
886 if (!(flags & MLX5_IB_UPD_XLT_ZAP)) {
887 __mlx5_ib_populate_pas(dev, umem, page_shift,
888 idx, npages, xlt,
889 MLX5_IB_MTT_PRESENT);
890 /* Clear padding after the pages
891 * brought from the umem.
892 */
893 memset(xlt + (npages * sizeof(struct mlx5_mtt)), 0,
894 size - npages * sizeof(struct mlx5_mtt));
895 }
896
897 return npages;
898}
899
900#define MLX5_MAX_UMR_CHUNK ((1 << (MLX5_MAX_UMR_SHIFT + 4)) - \
901 MLX5_UMR_MTT_ALIGNMENT)
902#define MLX5_SPARE_UMR_CHUNK 0x10000
903
904int mlx5_ib_update_xlt(struct mlx5_ib_mr *mr, u64 idx, int npages,
905 int page_shift, int flags)
Haggai Eran832a6b02014-12-11 17:04:22 +0200906{
907 struct mlx5_ib_dev *dev = mr->dev;
Bart Van Assche9b0c2892017-01-20 13:04:21 -0800908 struct device *ddev = dev->ib_dev.dev.parent;
Haggai Eran832a6b02014-12-11 17:04:22 +0200909 int size;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200910 void *xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200911 dma_addr_t dma;
Christoph Hellwige622f2f2015-10-08 09:16:33 +0100912 struct mlx5_umr_wr wr;
Haggai Eran832a6b02014-12-11 17:04:22 +0200913 struct ib_sge sg;
914 int err = 0;
Artemy Kovalyov81713d32017-01-18 16:58:11 +0200915 int desc_size = (flags & MLX5_IB_UPD_XLT_INDIRECT)
916 ? sizeof(struct mlx5_klm)
917 : sizeof(struct mlx5_mtt);
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200918 const int page_align = MLX5_UMR_MTT_ALIGNMENT / desc_size;
919 const int page_mask = page_align - 1;
Haggai Eran832a6b02014-12-11 17:04:22 +0200920 size_t pages_mapped = 0;
921 size_t pages_to_map = 0;
922 size_t pages_iter = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200923 gfp_t gfp;
Ilya Lesokhinc44ef992018-03-13 15:18:48 +0200924 bool use_emergency_page = false;
Haggai Eran832a6b02014-12-11 17:04:22 +0200925
Majd Dibbinyc8d75a92018-03-22 15:34:04 +0200926 if ((flags & MLX5_IB_UPD_XLT_INDIRECT) &&
927 !umr_can_use_indirect_mkey(dev))
928 return -EPERM;
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) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200955 mlx5_ib_warn(dev, "Using XLT emergency buffer\n");
Ilya Lesokhinc44ef992018-03-13 15:18:48 +0200956 xlt = (void *)mlx5_ib_get_xlt_emergency_page();
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200957 size = PAGE_SIZE;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200958 memset(xlt, 0, size);
Ilya Lesokhinc44ef992018-03-13 15:18:48 +0200959 use_emergency_page = true;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200960 }
961 pages_iter = size / desc_size;
962 dma = dma_map_single(ddev, xlt, size, DMA_TO_DEVICE);
Haggai Eran832a6b02014-12-11 17:04:22 +0200963 if (dma_mapping_error(ddev, dma)) {
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200964 mlx5_ib_err(dev, "unable to map DMA during XLT update.\n");
Haggai Eran832a6b02014-12-11 17:04:22 +0200965 err = -ENOMEM;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200966 goto free_xlt;
Haggai Eran832a6b02014-12-11 17:04:22 +0200967 }
968
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200969 sg.addr = dma;
970 sg.lkey = dev->umrc.pd->local_dma_lkey;
971
972 memset(&wr, 0, sizeof(wr));
973 wr.wr.send_flags = MLX5_IB_SEND_UMR_UPDATE_XLT;
974 if (!(flags & MLX5_IB_UPD_XLT_ENABLE))
975 wr.wr.send_flags |= MLX5_IB_SEND_UMR_FAIL_IF_FREE;
976 wr.wr.sg_list = &sg;
977 wr.wr.num_sge = 1;
978 wr.wr.opcode = MLX5_IB_WR_UMR;
979
980 wr.pd = mr->ibmr.pd;
981 wr.mkey = mr->mmkey.key;
982 wr.length = mr->mmkey.size;
983 wr.virt_addr = mr->mmkey.iova;
984 wr.access_flags = mr->access_flags;
985 wr.page_shift = page_shift;
986
Haggai Eran832a6b02014-12-11 17:04:22 +0200987 for (pages_mapped = 0;
988 pages_mapped < pages_to_map && !err;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200989 pages_mapped += pages_iter, idx += pages_iter) {
Artemy Kovalyov438b2282017-04-05 09:23:52 +0300990 npages = min_t(int, pages_iter, pages_to_map - pages_mapped);
Haggai Eran832a6b02014-12-11 17:04:22 +0200991 dma_sync_single_for_cpu(ddev, dma, size, DMA_TO_DEVICE);
Artemy Kovalyov438b2282017-04-05 09:23:52 +0300992 npages = populate_xlt(mr, idx, npages, xlt,
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +0200993 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:
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02001023 if (use_emergency_page)
1024 mlx5_ib_put_xlt_emergency_page();
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,
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001038 int page_shift, int access_flags,
1039 bool populate)
Eli Cohene126ba92013-07-07 17:25:49 +03001040{
1041 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Eli Cohene126ba92013-07-07 17:25:49 +03001042 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001043 __be64 *pas;
1044 void *mkc;
Eli Cohene126ba92013-07-07 17:25:49 +03001045 int inlen;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001046 u32 *in;
Eli Cohene126ba92013-07-07 17:25:49 +03001047 int err;
Saeed Mahameed938fe832015-05-28 22:28:41 +03001048 bool pg_cap = !!(MLX5_CAP_GEN(dev->mdev, pg));
Eli Cohene126ba92013-07-07 17:25:49 +03001049
Noa Osherovich395a8e42016-02-29 16:46:50 +02001050 mr = ibmr ? to_mmr(ibmr) : kzalloc(sizeof(*mr), GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +03001051 if (!mr)
1052 return ERR_PTR(-ENOMEM);
1053
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001054 mr->ibmr.pd = pd;
1055 mr->access_flags = access_flags;
1056
1057 inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
1058 if (populate)
1059 inlen += sizeof(*pas) * roundup(npages, 2);
Leon Romanovsky1b9a07e2017-05-10 21:32:18 +03001060 in = kvzalloc(inlen, GFP_KERNEL);
Eli Cohene126ba92013-07-07 17:25:49 +03001061 if (!in) {
1062 err = -ENOMEM;
1063 goto err_1;
1064 }
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001065 pas = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001066 if (populate && !(access_flags & IB_ACCESS_ON_DEMAND))
Artemy Kovalyovc438fde2017-01-02 11:37:43 +02001067 mlx5_ib_populate_pas(dev, umem, page_shift, pas,
1068 pg_cap ? MLX5_IB_MTT_PRESENT : 0);
Eli Cohene126ba92013-07-07 17:25:49 +03001069
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001070 /* The pg_access bit allows setting the access flags
Haggai Erancc149f752014-12-11 17:04:21 +02001071 * in the page list submitted with the command. */
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001072 MLX5_SET(create_mkey_in, in, pg_access, !!(pg_cap));
1073
1074 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001075 MLX5_SET(mkc, mkc, free, !populate);
Ariel Levkovichcdbd0d22018-04-05 18:53:28 +03001076 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001077 MLX5_SET(mkc, mkc, a, !!(access_flags & IB_ACCESS_REMOTE_ATOMIC));
1078 MLX5_SET(mkc, mkc, rw, !!(access_flags & IB_ACCESS_REMOTE_WRITE));
1079 MLX5_SET(mkc, mkc, rr, !!(access_flags & IB_ACCESS_REMOTE_READ));
1080 MLX5_SET(mkc, mkc, lw, !!(access_flags & IB_ACCESS_LOCAL_WRITE));
1081 MLX5_SET(mkc, mkc, lr, 1);
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +03001082 MLX5_SET(mkc, mkc, umr_en, 1);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001083
1084 MLX5_SET64(mkc, mkc, start_addr, virt_addr);
1085 MLX5_SET64(mkc, mkc, len, length);
1086 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1087 MLX5_SET(mkc, mkc, bsf_octword_size, 0);
1088 MLX5_SET(mkc, mkc, translations_octword_size,
Ilya Lesokhin7b4cdaa2017-08-17 15:52:32 +03001089 get_octo_len(virt_addr, length, page_shift));
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001090 MLX5_SET(mkc, mkc, log_page_size, page_shift);
1091 MLX5_SET(mkc, mkc, qpn, 0xffffff);
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001092 if (populate) {
1093 MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
Ilya Lesokhin7b4cdaa2017-08-17 15:52:32 +03001094 get_octo_len(virt_addr, length, page_shift));
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001095 }
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001096
1097 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
Eli Cohene126ba92013-07-07 17:25:49 +03001098 if (err) {
1099 mlx5_ib_warn(dev, "create mkey failed\n");
1100 goto err_2;
1101 }
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +02001102 mr->mmkey.type = MLX5_MKEY_MR;
Artemy Kovalyov49780d42017-01-18 16:58:10 +02001103 mr->desc_size = sizeof(struct mlx5_mtt);
Majd Dibbiny7eae20d2015-01-06 13:56:01 +02001104 mr->dev = dev;
Al Viro479163f2014-11-20 08:13:57 +00001105 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001106
Matan Baraka606b0f2016-02-29 18:05:28 +02001107 mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001108
1109 return mr;
1110
1111err_2:
Al Viro479163f2014-11-20 08:13:57 +00001112 kvfree(in);
Eli Cohene126ba92013-07-07 17:25:49 +03001113
1114err_1:
Noa Osherovich395a8e42016-02-29 16:46:50 +02001115 if (!ibmr)
1116 kfree(mr);
Eli Cohene126ba92013-07-07 17:25:49 +03001117
1118 return ERR_PTR(err);
1119}
1120
Gal Pressmanac2f7e62018-12-18 17:57:32 +02001121static void set_mr_fields(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
Noa Osherovich395a8e42016-02-29 16:46:50 +02001122 int npages, u64 length, int access_flags)
1123{
1124 mr->npages = npages;
1125 atomic_add(npages, &dev->mdev->priv.reg_pages);
Matan Baraka606b0f2016-02-29 18:05:28 +02001126 mr->ibmr.lkey = mr->mmkey.key;
1127 mr->ibmr.rkey = mr->mmkey.key;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001128 mr->ibmr.length = length;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001129 mr->access_flags = access_flags;
Noa Osherovich395a8e42016-02-29 16:46:50 +02001130}
1131
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001132static struct ib_mr *mlx5_ib_get_dm_mr(struct ib_pd *pd, u64 start_addr,
1133 u64 length, int acc, int mode)
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001134{
1135 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1136 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
1137 struct mlx5_core_dev *mdev = dev->mdev;
1138 struct mlx5_ib_mr *mr;
1139 void *mkc;
1140 u32 *in;
1141 int err;
1142
1143 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1144 if (!mr)
1145 return ERR_PTR(-ENOMEM);
1146
1147 in = kzalloc(inlen, GFP_KERNEL);
1148 if (!in) {
1149 err = -ENOMEM;
1150 goto err_free;
1151 }
1152
1153 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1154
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001155 MLX5_SET(mkc, mkc, access_mode_1_0, mode & 0x3);
1156 MLX5_SET(mkc, mkc, access_mode_4_2, (mode >> 2) & 0x7);
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001157 MLX5_SET64(mkc, mkc, len, length);
Parav Pandit03232cc2019-10-06 18:54:43 +03001158 set_mkc_access_pd_addr_fields(mkc, acc, start_addr, pd);
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001159
1160 err = mlx5_core_create_mkey(mdev, &mr->mmkey, in, inlen);
1161 if (err)
1162 goto err_in;
1163
1164 kfree(in);
1165
1166 mr->umem = NULL;
Gal Pressmanac2f7e62018-12-18 17:57:32 +02001167 set_mr_fields(dev, mr, 0, length, acc);
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001168
1169 return &mr->ibmr;
1170
1171err_in:
1172 kfree(in);
1173
1174err_free:
1175 kfree(mr);
1176
1177 return ERR_PTR(err);
1178}
1179
Moni Shoua813e90b2018-12-11 13:37:53 +02001180int mlx5_ib_advise_mr(struct ib_pd *pd,
1181 enum ib_uverbs_advise_mr_advice advice,
1182 u32 flags,
1183 struct ib_sge *sg_list,
1184 u32 num_sge,
1185 struct uverbs_attr_bundle *attrs)
1186{
1187 if (advice != IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH &&
1188 advice != IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE)
1189 return -EOPNOTSUPP;
1190
1191 return mlx5_ib_advise_mr_prefetch(pd, advice, flags,
1192 sg_list, num_sge);
1193}
1194
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001195struct ib_mr *mlx5_ib_reg_dm_mr(struct ib_pd *pd, struct ib_dm *dm,
1196 struct ib_dm_mr_attr *attr,
1197 struct uverbs_attr_bundle *attrs)
1198{
1199 struct mlx5_ib_dm *mdm = to_mdm(dm);
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001200 struct mlx5_core_dev *dev = to_mdev(dm->device)->mdev;
1201 u64 start_addr = mdm->dev_addr + attr->offset;
1202 int mode;
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001203
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001204 switch (mdm->type) {
1205 case MLX5_IB_UAPI_DM_TYPE_MEMIC:
1206 if (attr->access_flags & ~MLX5_IB_DM_MEMIC_ALLOWED_ACCESS)
1207 return ERR_PTR(-EINVAL);
1208
1209 mode = MLX5_MKC_ACCESS_MODE_MEMIC;
1210 start_addr -= pci_resource_start(dev->pdev, 0);
1211 break;
Ariel Levkovich25c13322019-05-05 17:07:13 +03001212 case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
1213 case MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM:
1214 if (attr->access_flags & ~MLX5_IB_DM_SW_ICM_ALLOWED_ACCESS)
1215 return ERR_PTR(-EINVAL);
1216
1217 mode = MLX5_MKC_ACCESS_MODE_SW_ICM;
1218 break;
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001219 default:
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001220 return ERR_PTR(-EINVAL);
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001221 }
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001222
Ariel Levkovich3b113a12019-05-05 17:07:11 +03001223 return mlx5_ib_get_dm_mr(pd, start_addr, attr->length,
1224 attr->access_flags, mode);
Ariel Levkovich6c29f572018-04-05 18:53:29 +03001225}
1226
Eli Cohene126ba92013-07-07 17:25:49 +03001227struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
1228 u64 virt_addr, int access_flags,
1229 struct ib_udata *udata)
1230{
1231 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1232 struct mlx5_ib_mr *mr = NULL;
Guy Levie5366d32019-07-31 11:19:29 +03001233 bool use_umr;
Eli Cohene126ba92013-07-07 17:25:49 +03001234 struct ib_umem *umem;
1235 int page_shift;
1236 int npages;
1237 int ncont;
1238 int order;
1239 int err;
1240
Arnd Bergmann1b19b9512017-12-11 12:45:44 +01001241 if (!IS_ENABLED(CONFIG_INFINIBAND_USER_MEM))
Leon Romanovskyea30f012018-03-13 15:29:25 +02001242 return ERR_PTR(-EOPNOTSUPP);
Arnd Bergmann1b19b9512017-12-11 12:45:44 +01001243
Eli Cohen900a6d72014-09-14 16:47:51 +03001244 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1245 start, virt_addr, length, access_flags);
Artemy Kovalyov81713d32017-01-18 16:58:11 +02001246
Leon Romanovsky13859d5d2019-01-08 16:07:26 +02001247 if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING) && !start &&
1248 length == U64_MAX) {
Artemy Kovalyov81713d32017-01-18 16:58:11 +02001249 if (!(access_flags & IB_ACCESS_ON_DEMAND) ||
1250 !(dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT))
1251 return ERR_PTR(-EINVAL);
1252
Jason Gunthorpeb0ea0fa2019-01-09 11:15:16 +02001253 mr = mlx5_ib_alloc_implicit_mr(to_mpd(pd), udata, access_flags);
Leon Romanovsky42898612018-03-13 15:29:24 +02001254 if (IS_ERR(mr))
1255 return ERR_CAST(mr);
Artemy Kovalyov81713d32017-01-18 16:58:11 +02001256 return &mr->ibmr;
1257 }
Artemy Kovalyov81713d32017-01-18 16:58:11 +02001258
Moni Shouac320e522020-01-15 14:43:31 +02001259 err = mr_umem_get(dev, start, length, access_flags, &umem,
Jason Gunthorpeb0ea0fa2019-01-09 11:15:16 +02001260 &npages, &page_shift, &ncont, &order);
Noa Osherovich395a8e42016-02-29 16:46:50 +02001261
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001262 if (err < 0)
Arnd Bergmann14ab8892016-10-24 22:48:21 +02001263 return ERR_PTR(err);
Eli Cohene126ba92013-07-07 17:25:49 +03001264
Moni Shoua0e6613b2019-08-15 11:38:31 +03001265 use_umr = mlx5_ib_can_use_umr(dev, true);
Guy Levie5366d32019-07-31 11:19:29 +03001266
1267 if (order <= mr_cache_max_order(dev) && use_umr) {
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001268 mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
1269 page_shift, order, access_flags);
Eli Cohene126ba92013-07-07 17:25:49 +03001270 if (PTR_ERR(mr) == -EAGAIN) {
Arvind Yadavd23a8ba2017-09-26 12:20:01 +05301271 mlx5_ib_dbg(dev, "cache empty for order %d\n", order);
Eli Cohene126ba92013-07-07 17:25:49 +03001272 mr = NULL;
1273 }
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001274 } else if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
1275 if (access_flags & IB_ACCESS_ON_DEMAND) {
1276 err = -EINVAL;
Arvind Yadavd23a8ba2017-09-26 12:20:01 +05301277 pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB\n");
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001278 goto error;
1279 }
Guy Levie5366d32019-07-31 11:19:29 +03001280 use_umr = false;
Eli Cohene126ba92013-07-07 17:25:49 +03001281 }
1282
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001283 if (!mr) {
1284 mutex_lock(&dev->slow_path_mutex);
Noa Osherovich395a8e42016-02-29 16:46:50 +02001285 mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
Guy Levie5366d32019-07-31 11:19:29 +03001286 page_shift, access_flags, !use_umr);
Moshe Lazer6bc1a652016-10-27 16:36:42 +03001287 mutex_unlock(&dev->slow_path_mutex);
1288 }
Eli Cohene126ba92013-07-07 17:25:49 +03001289
1290 if (IS_ERR(mr)) {
1291 err = PTR_ERR(mr);
1292 goto error;
1293 }
1294
Matan Baraka606b0f2016-02-29 18:05:28 +02001295 mlx5_ib_dbg(dev, "mkey 0x%x\n", mr->mmkey.key);
Eli Cohene126ba92013-07-07 17:25:49 +03001296
1297 mr->umem = umem;
Gal Pressmanac2f7e62018-12-18 17:57:32 +02001298 set_mr_fields(dev, mr, npages, length, access_flags);
Eli Cohene126ba92013-07-07 17:25:49 +03001299
Guy Levie5366d32019-07-31 11:19:29 +03001300 if (use_umr) {
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001301 int update_xlt_flags = MLX5_IB_UPD_XLT_ENABLE;
Eli Cohene126ba92013-07-07 17:25:49 +03001302
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001303 if (access_flags & IB_ACCESS_ON_DEMAND)
1304 update_xlt_flags |= MLX5_IB_UPD_XLT_ZAP;
1305
1306 err = mlx5_ib_update_xlt(mr, 0, ncont, page_shift,
1307 update_xlt_flags);
Ilya Lesokhinfbcd4982017-09-24 21:46:35 +03001308
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001309 if (err) {
Ilya Lesokhinfbcd4982017-09-24 21:46:35 +03001310 dereg_mr(dev, mr);
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001311 return ERR_PTR(err);
1312 }
1313 }
1314
Jason Gunthorpeaa603812019-10-01 12:38:20 -03001315 if (is_odp_mr(mr)) {
1316 to_ib_umem_odp(mr->umem)->private = mr;
Jason Gunthorpe5256edc2019-10-09 13:09:32 -03001317 atomic_set(&mr->num_deferred_work, 0);
Jason Gunthorpe806b1012019-10-09 13:09:23 -03001318 err = xa_err(xa_store(&dev->odp_mkeys,
1319 mlx5_base_mkey(mr->mmkey.key), &mr->mmkey,
1320 GFP_KERNEL));
1321 if (err) {
1322 dereg_mr(dev, mr);
1323 return ERR_PTR(err);
1324 }
Moni Shouaa6bc3872019-02-17 16:08:22 +02001325 }
Leon Romanovsky13859d5d2019-01-08 16:07:26 +02001326
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001327 return &mr->ibmr;
Eli Cohene126ba92013-07-07 17:25:49 +03001328error:
1329 ib_umem_release(umem);
1330 return ERR_PTR(err);
1331}
1332
Jason Gunthorpe09689702019-10-09 13:09:34 -03001333/**
1334 * mlx5_mr_cache_invalidate - Fence all DMA on the MR
1335 * @mr: The MR to fence
1336 *
1337 * Upon return the NIC will not be doing any DMA to the pages under the MR,
1338 * and any DMA inprogress will be completed. Failure of this function
1339 * indicates the HW has failed catastrophically.
1340 */
1341int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr)
Eli Cohene126ba92013-07-07 17:25:49 +03001342{
Doug Ledford0025b0b2016-03-03 11:23:37 -05001343 struct mlx5_umr_wr umrwr = {};
Eli Cohene126ba92013-07-07 17:25:49 +03001344
Jason Gunthorpe09689702019-10-09 13:09:34 -03001345 if (mr->dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03001346 return 0;
1347
Yishai Hadas9ec44832019-07-23 09:57:27 +03001348 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_DISABLE_MR |
1349 MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001350 umrwr.wr.opcode = MLX5_IB_WR_UMR;
Jason Gunthorpe09689702019-10-09 13:09:34 -03001351 umrwr.pd = mr->dev->umrc.pd;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001352 umrwr.mkey = mr->mmkey.key;
Yishai Hadas6a053952019-07-23 09:57:25 +03001353 umrwr.ignore_free_state = 1;
Eli Cohene126ba92013-07-07 17:25:49 +03001354
Jason Gunthorpe09689702019-10-09 13:09:34 -03001355 return mlx5_ib_post_send_wait(mr->dev, &umrwr);
Eli Cohene126ba92013-07-07 17:25:49 +03001356}
1357
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001358static int rereg_umr(struct ib_pd *pd, struct mlx5_ib_mr *mr,
Noa Osherovich56e11d62016-02-29 16:46:51 +02001359 int access_flags, int flags)
1360{
1361 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001362 struct mlx5_umr_wr umrwr = {};
Noa Osherovich56e11d62016-02-29 16:46:51 +02001363 int err;
1364
Noa Osherovich56e11d62016-02-29 16:46:51 +02001365 umrwr.wr.send_flags = MLX5_IB_SEND_UMR_FAIL_IF_FREE;
1366
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001367 umrwr.wr.opcode = MLX5_IB_WR_UMR;
1368 umrwr.mkey = mr->mmkey.key;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001369
Artemy Kovalyov31616252017-01-02 11:37:42 +02001370 if (flags & IB_MR_REREG_PD || flags & IB_MR_REREG_ACCESS) {
Noa Osherovich56e11d62016-02-29 16:46:51 +02001371 umrwr.pd = pd;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001372 umrwr.access_flags = access_flags;
Artemy Kovalyov31616252017-01-02 11:37:42 +02001373 umrwr.wr.send_flags |= MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001374 }
1375
Binoy Jayand5ea2df2017-01-02 11:37:40 +02001376 err = mlx5_ib_post_send_wait(dev, &umrwr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001377
Noa Osherovich56e11d62016-02-29 16:46:51 +02001378 return err;
1379}
1380
1381int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
1382 u64 length, u64 virt_addr, int new_access_flags,
1383 struct ib_pd *new_pd, struct ib_udata *udata)
1384{
1385 struct mlx5_ib_dev *dev = to_mdev(ib_mr->device);
1386 struct mlx5_ib_mr *mr = to_mmr(ib_mr);
1387 struct ib_pd *pd = (flags & IB_MR_REREG_PD) ? new_pd : ib_mr->pd;
1388 int access_flags = flags & IB_MR_REREG_ACCESS ?
1389 new_access_flags :
1390 mr->access_flags;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001391 int page_shift = 0;
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001392 int upd_flags = 0;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001393 int npages = 0;
1394 int ncont = 0;
1395 int order = 0;
Leon Romanovskyb4bd7012018-04-23 17:01:52 +03001396 u64 addr, len;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001397 int err;
1398
1399 mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
1400 start, virt_addr, length, access_flags);
1401
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001402 atomic_sub(mr->npages, &dev->mdev->priv.reg_pages);
1403
Leon Romanovskyb4bd7012018-04-23 17:01:52 +03001404 if (!mr->umem)
1405 return -EINVAL;
1406
Jason Gunthorpe880505c2019-10-01 12:38:16 -03001407 if (is_odp_mr(mr))
1408 return -EOPNOTSUPP;
1409
Leon Romanovskyb4bd7012018-04-23 17:01:52 +03001410 if (flags & IB_MR_REREG_TRANS) {
1411 addr = virt_addr;
1412 len = length;
1413 } else {
1414 addr = mr->umem->address;
1415 len = mr->umem->length;
1416 }
1417
Noa Osherovich56e11d62016-02-29 16:46:51 +02001418 if (flags != IB_MR_REREG_PD) {
1419 /*
1420 * Replace umem. This needs to be done whether or not UMR is
1421 * used.
1422 */
1423 flags |= IB_MR_REREG_TRANS;
1424 ib_umem_release(mr->umem);
Leon Romanovskyb4bd7012018-04-23 17:01:52 +03001425 mr->umem = NULL;
Moni Shouac320e522020-01-15 14:43:31 +02001426 err = mr_umem_get(dev, addr, len, access_flags, &mr->umem,
1427 &npages, &page_shift, &ncont, &order);
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001428 if (err)
1429 goto err;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001430 }
1431
Moni Shoua25a45172019-08-15 11:38:33 +03001432 if (!mlx5_ib_can_use_umr(dev, true) ||
1433 (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len))) {
Noa Osherovich56e11d62016-02-29 16:46:51 +02001434 /*
1435 * UMR can't be used - MKey needs to be replaced.
1436 */
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001437 if (mr->allocated_from_cache)
Jason Gunthorpe09689702019-10-09 13:09:34 -03001438 err = mlx5_mr_cache_invalidate(mr);
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001439 else
Noa Osherovich56e11d62016-02-29 16:46:51 +02001440 err = destroy_mkey(dev, mr);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001441 if (err)
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001442 goto err;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001443
1444 mr = reg_create(ib_mr, pd, addr, len, mr->umem, ncont,
Ilya Lesokhinff740ae2017-08-17 15:52:30 +03001445 page_shift, access_flags, true);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001446
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001447 if (IS_ERR(mr)) {
1448 err = PTR_ERR(mr);
1449 mr = to_mmr(ib_mr);
1450 goto err;
1451 }
Noa Osherovich56e11d62016-02-29 16:46:51 +02001452
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +03001453 mr->allocated_from_cache = 0;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001454 } else {
1455 /*
1456 * Send a UMR WQE
1457 */
Artemy Kovalyov7d0cc6e2017-01-02 11:37:44 +02001458 mr->ibmr.pd = pd;
1459 mr->access_flags = access_flags;
1460 mr->mmkey.iova = addr;
1461 mr->mmkey.size = len;
1462 mr->mmkey.pd = to_mpd(pd)->pdn;
1463
1464 if (flags & IB_MR_REREG_TRANS) {
1465 upd_flags = MLX5_IB_UPD_XLT_ADDR;
1466 if (flags & IB_MR_REREG_PD)
1467 upd_flags |= MLX5_IB_UPD_XLT_PD;
1468 if (flags & IB_MR_REREG_ACCESS)
1469 upd_flags |= MLX5_IB_UPD_XLT_ACCESS;
1470 err = mlx5_ib_update_xlt(mr, 0, npages, page_shift,
1471 upd_flags);
1472 } else {
1473 err = rereg_umr(pd, mr, access_flags, flags);
1474 }
1475
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001476 if (err)
1477 goto err;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001478 }
1479
Gal Pressmanac2f7e62018-12-18 17:57:32 +02001480 set_mr_fields(dev, mr, npages, len, access_flags);
Noa Osherovich56e11d62016-02-29 16:46:51 +02001481
Noa Osherovich56e11d62016-02-29 16:46:51 +02001482 return 0;
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001483
1484err:
Leon Romanovsky836a0fb2019-06-16 15:05:20 +03001485 ib_umem_release(mr->umem);
1486 mr->umem = NULL;
1487
Leon Romanovsky4638a3b2018-03-13 15:29:26 +02001488 clean_mr(dev, mr);
1489 return err;
Noa Osherovich56e11d62016-02-29 16:46:51 +02001490}
1491
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001492static int
1493mlx5_alloc_priv_descs(struct ib_device *device,
1494 struct mlx5_ib_mr *mr,
1495 int ndescs,
1496 int desc_size)
1497{
1498 int size = ndescs * desc_size;
1499 int add_size;
1500 int ret;
1501
1502 add_size = max_t(int, MLX5_UMR_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
1503
1504 mr->descs_alloc = kzalloc(size + add_size, GFP_KERNEL);
1505 if (!mr->descs_alloc)
1506 return -ENOMEM;
1507
1508 mr->descs = PTR_ALIGN(mr->descs_alloc, MLX5_UMR_ALIGN);
1509
Bart Van Assche9b0c2892017-01-20 13:04:21 -08001510 mr->desc_map = dma_map_single(device->dev.parent, mr->descs,
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001511 size, DMA_TO_DEVICE);
Bart Van Assche9b0c2892017-01-20 13:04:21 -08001512 if (dma_mapping_error(device->dev.parent, mr->desc_map)) {
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001513 ret = -ENOMEM;
1514 goto err;
1515 }
1516
1517 return 0;
1518err:
1519 kfree(mr->descs_alloc);
1520
1521 return ret;
1522}
1523
1524static void
1525mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
1526{
1527 if (mr->descs) {
1528 struct ib_device *device = mr->ibmr.device;
1529 int size = mr->max_descs * mr->desc_size;
1530
Bart Van Assche9b0c2892017-01-20 13:04:21 -08001531 dma_unmap_single(device->dev.parent, mr->desc_map,
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03001532 size, DMA_TO_DEVICE);
1533 kfree(mr->descs_alloc);
1534 mr->descs = NULL;
1535 }
1536}
1537
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001538static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
Eli Cohene126ba92013-07-07 17:25:49 +03001539{
Ilya Lesokhin8b7ff7f2017-08-17 15:52:29 +03001540 int allocated_from_cache = mr->allocated_from_cache;
Eli Cohene126ba92013-07-07 17:25:49 +03001541
Sagi Grimberg8b91ffc2015-07-30 10:32:34 +03001542 if (mr->sig) {
1543 if (mlx5_core_destroy_psv(dev->mdev,
1544 mr->sig->psv_memory.psv_idx))
1545 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1546 mr->sig->psv_memory.psv_idx);
1547 if (mlx5_core_destroy_psv(dev->mdev,
1548 mr->sig->psv_wire.psv_idx))
1549 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1550 mr->sig->psv_wire.psv_idx);
Jason Gunthorpe50211ec2019-10-09 13:09:22 -03001551 xa_erase(&dev->sig_mrs, mlx5_base_mkey(mr->mmkey.key));
Sagi Grimberg8b91ffc2015-07-30 10:32:34 +03001552 kfree(mr->sig);
1553 mr->sig = NULL;
1554 }
1555
Yishai Hadasb9332da2019-07-23 09:57:28 +03001556 if (!allocated_from_cache) {
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001557 destroy_mkey(dev, mr);
Yishai Hadasb9332da2019-07-23 09:57:28 +03001558 mlx5_free_priv_descs(mr);
1559 }
Eli Cohene126ba92013-07-07 17:25:49 +03001560}
1561
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001562static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
Haggai Eran6aec21f2014-12-11 17:04:23 +02001563{
Haggai Eran6aec21f2014-12-11 17:04:23 +02001564 int npages = mr->npages;
1565 struct ib_umem *umem = mr->umem;
1566
Jason Gunthorpe09689702019-10-09 13:09:34 -03001567 /* Stop all DMA */
1568 if (is_odp_mr(mr))
1569 mlx5_ib_fence_odp_mr(mr);
1570 else
1571 clean_mr(dev, mr);
Jason Gunthorpe597ecc52018-09-16 20:48:06 +03001572
Jason Gunthorpe09689702019-10-09 13:09:34 -03001573 if (mr->allocated_from_cache)
1574 mlx5_mr_cache_free(dev, mr);
1575 else
Leon Romanovskyf3f134f2018-03-12 21:26:37 +02001576 kfree(mr);
Jason Gunthorpe09689702019-10-09 13:09:34 -03001577
1578 ib_umem_release(umem);
1579 atomic_sub(npages, &dev->mdev->priv.reg_pages);
1580
Haggai Eran6aec21f2014-12-11 17:04:23 +02001581}
1582
Shamir Rabinovitchc4367a22019-03-31 19:10:05 +03001583int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
Ilya Lesokhinfbcd4982017-09-24 21:46:35 +03001584{
Max Gurtovoy6c984472019-06-11 18:52:42 +03001585 struct mlx5_ib_mr *mmr = to_mmr(ibmr);
1586
Israel Rukshinde0ae952019-06-11 18:52:55 +03001587 if (ibmr->type == IB_MR_TYPE_INTEGRITY) {
1588 dereg_mr(to_mdev(mmr->mtt_mr->ibmr.device), mmr->mtt_mr);
1589 dereg_mr(to_mdev(mmr->klm_mr->ibmr.device), mmr->klm_mr);
1590 }
Max Gurtovoy6c984472019-06-11 18:52:42 +03001591
Jason Gunthorpe5256edc2019-10-09 13:09:32 -03001592 if (is_odp_mr(mmr) && to_ib_umem_odp(mmr->umem)->is_implicit_odp) {
1593 mlx5_ib_free_implicit_mr(mmr);
1594 return 0;
1595 }
1596
Max Gurtovoy6c984472019-06-11 18:52:42 +03001597 dereg_mr(to_mdev(ibmr->device), mmr);
1598
Leon Romanovskyeeea6952018-03-13 15:29:28 +02001599 return 0;
Ilya Lesokhinfbcd4982017-09-24 21:46:35 +03001600}
1601
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001602static void mlx5_set_umr_free_mkey(struct ib_pd *pd, u32 *in, int ndescs,
1603 int access_mode, int page_shift)
1604{
1605 void *mkc;
1606
1607 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1608
1609 MLX5_SET(mkc, mkc, free, 1);
1610 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1611 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1612 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1613 MLX5_SET(mkc, mkc, access_mode_1_0, access_mode & 0x3);
1614 MLX5_SET(mkc, mkc, access_mode_4_2, (access_mode >> 2) & 0x7);
1615 MLX5_SET(mkc, mkc, umr_en, 1);
1616 MLX5_SET(mkc, mkc, log_page_size, page_shift);
1617}
1618
1619static int _mlx5_alloc_mkey_descs(struct ib_pd *pd, struct mlx5_ib_mr *mr,
1620 int ndescs, int desc_size, int page_shift,
1621 int access_mode, u32 *in, int inlen)
1622{
1623 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1624 int err;
1625
1626 mr->access_mode = access_mode;
1627 mr->desc_size = desc_size;
1628 mr->max_descs = ndescs;
1629
1630 err = mlx5_alloc_priv_descs(pd->device, mr, ndescs, desc_size);
1631 if (err)
1632 return err;
1633
1634 mlx5_set_umr_free_mkey(pd, in, ndescs, access_mode, page_shift);
1635
1636 err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
1637 if (err)
1638 goto err_free_descs;
1639
1640 mr->mmkey.type = MLX5_MKEY_MR;
1641 mr->ibmr.lkey = mr->mmkey.key;
1642 mr->ibmr.rkey = mr->mmkey.key;
1643
1644 return 0;
1645
1646err_free_descs:
1647 mlx5_free_priv_descs(mr);
1648 return err;
1649}
1650
Max Gurtovoy6c984472019-06-11 18:52:42 +03001651static struct mlx5_ib_mr *mlx5_ib_alloc_pi_mr(struct ib_pd *pd,
Israel Rukshinde0ae952019-06-11 18:52:55 +03001652 u32 max_num_sg, u32 max_num_meta_sg,
1653 int desc_size, int access_mode)
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001654{
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001655 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Max Gurtovoy6c984472019-06-11 18:52:42 +03001656 int ndescs = ALIGN(max_num_sg + max_num_meta_sg, 4);
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001657 int page_shift = 0;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001658 struct mlx5_ib_mr *mr;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001659 u32 *in;
Sagi Grimbergb005d312016-02-29 19:07:33 +02001660 int err;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001661
1662 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1663 if (!mr)
1664 return ERR_PTR(-ENOMEM);
1665
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001666 mr->ibmr.pd = pd;
1667 mr->ibmr.device = pd->device;
1668
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001669 in = kzalloc(inlen, GFP_KERNEL);
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001670 if (!in) {
1671 err = -ENOMEM;
1672 goto err_free;
1673 }
1674
Israel Rukshinde0ae952019-06-11 18:52:55 +03001675 if (access_mode == MLX5_MKC_ACCESS_MODE_MTT)
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001676 page_shift = PAGE_SHIFT;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001677
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001678 err = _mlx5_alloc_mkey_descs(pd, mr, ndescs, desc_size, page_shift,
1679 access_mode, in, inlen);
Max Gurtovoy6c984472019-06-11 18:52:42 +03001680 if (err)
1681 goto err_free_in;
Max Gurtovoy6c984472019-06-11 18:52:42 +03001682
Max Gurtovoy6c984472019-06-11 18:52:42 +03001683 mr->umem = NULL;
1684 kfree(in);
1685
1686 return mr;
1687
Max Gurtovoy6c984472019-06-11 18:52:42 +03001688err_free_in:
1689 kfree(in);
1690err_free:
1691 kfree(mr);
1692 return ERR_PTR(err);
1693}
1694
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001695static int mlx5_alloc_mem_reg_descs(struct ib_pd *pd, struct mlx5_ib_mr *mr,
1696 int ndescs, u32 *in, int inlen)
1697{
1698 return _mlx5_alloc_mkey_descs(pd, mr, ndescs, sizeof(struct mlx5_mtt),
1699 PAGE_SHIFT, MLX5_MKC_ACCESS_MODE_MTT, in,
1700 inlen);
1701}
1702
1703static int mlx5_alloc_sg_gaps_descs(struct ib_pd *pd, struct mlx5_ib_mr *mr,
1704 int ndescs, u32 *in, int inlen)
1705{
1706 return _mlx5_alloc_mkey_descs(pd, mr, ndescs, sizeof(struct mlx5_klm),
1707 0, MLX5_MKC_ACCESS_MODE_KLMS, in, inlen);
1708}
1709
1710static int mlx5_alloc_integrity_descs(struct ib_pd *pd, struct mlx5_ib_mr *mr,
1711 int max_num_sg, int max_num_meta_sg,
1712 u32 *in, int inlen)
1713{
1714 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1715 u32 psv_index[2];
1716 void *mkc;
1717 int err;
1718
1719 mr->sig = kzalloc(sizeof(*mr->sig), GFP_KERNEL);
1720 if (!mr->sig)
1721 return -ENOMEM;
1722
1723 /* create mem & wire PSVs */
1724 err = mlx5_core_create_psv(dev->mdev, to_mpd(pd)->pdn, 2, psv_index);
1725 if (err)
1726 goto err_free_sig;
1727
1728 mr->sig->psv_memory.psv_idx = psv_index[0];
1729 mr->sig->psv_wire.psv_idx = psv_index[1];
1730
1731 mr->sig->sig_status_checked = true;
1732 mr->sig->sig_err_exists = false;
1733 /* Next UMR, Arm SIGERR */
1734 ++mr->sig->sigerr_count;
1735 mr->klm_mr = mlx5_ib_alloc_pi_mr(pd, max_num_sg, max_num_meta_sg,
1736 sizeof(struct mlx5_klm),
1737 MLX5_MKC_ACCESS_MODE_KLMS);
1738 if (IS_ERR(mr->klm_mr)) {
1739 err = PTR_ERR(mr->klm_mr);
1740 goto err_destroy_psv;
1741 }
1742 mr->mtt_mr = mlx5_ib_alloc_pi_mr(pd, max_num_sg, max_num_meta_sg,
1743 sizeof(struct mlx5_mtt),
1744 MLX5_MKC_ACCESS_MODE_MTT);
1745 if (IS_ERR(mr->mtt_mr)) {
1746 err = PTR_ERR(mr->mtt_mr);
1747 goto err_free_klm_mr;
1748 }
1749
1750 /* Set bsf descriptors for mkey */
1751 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
1752 MLX5_SET(mkc, mkc, bsf_en, 1);
1753 MLX5_SET(mkc, mkc, bsf_octword_size, MLX5_MKEY_BSF_OCTO_SIZE);
1754
1755 err = _mlx5_alloc_mkey_descs(pd, mr, 4, sizeof(struct mlx5_klm), 0,
1756 MLX5_MKC_ACCESS_MODE_KLMS, in, inlen);
1757 if (err)
1758 goto err_free_mtt_mr;
1759
Jason Gunthorpe50211ec2019-10-09 13:09:22 -03001760 err = xa_err(xa_store(&dev->sig_mrs, mlx5_base_mkey(mr->mmkey.key),
1761 mr->sig, GFP_KERNEL));
1762 if (err)
1763 goto err_free_descs;
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001764 return 0;
1765
Jason Gunthorpe50211ec2019-10-09 13:09:22 -03001766err_free_descs:
1767 destroy_mkey(dev, mr);
1768 mlx5_free_priv_descs(mr);
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001769err_free_mtt_mr:
1770 dereg_mr(to_mdev(mr->mtt_mr->ibmr.device), mr->mtt_mr);
1771 mr->mtt_mr = NULL;
1772err_free_klm_mr:
1773 dereg_mr(to_mdev(mr->klm_mr->ibmr.device), mr->klm_mr);
1774 mr->klm_mr = NULL;
1775err_destroy_psv:
1776 if (mlx5_core_destroy_psv(dev->mdev, mr->sig->psv_memory.psv_idx))
1777 mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
1778 mr->sig->psv_memory.psv_idx);
1779 if (mlx5_core_destroy_psv(dev->mdev, mr->sig->psv_wire.psv_idx))
1780 mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
1781 mr->sig->psv_wire.psv_idx);
1782err_free_sig:
1783 kfree(mr->sig);
1784
1785 return err;
1786}
1787
Max Gurtovoy6c984472019-06-11 18:52:42 +03001788static struct ib_mr *__mlx5_ib_alloc_mr(struct ib_pd *pd,
1789 enum ib_mr_type mr_type, u32 max_num_sg,
1790 u32 max_num_meta_sg)
1791{
1792 struct mlx5_ib_dev *dev = to_mdev(pd->device);
1793 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
1794 int ndescs = ALIGN(max_num_sg, 4);
1795 struct mlx5_ib_mr *mr;
Max Gurtovoy6c984472019-06-11 18:52:42 +03001796 u32 *in;
1797 int err;
1798
1799 mr = kzalloc(sizeof(*mr), GFP_KERNEL);
1800 if (!mr)
1801 return ERR_PTR(-ENOMEM);
1802
1803 in = kzalloc(inlen, GFP_KERNEL);
1804 if (!in) {
1805 err = -ENOMEM;
1806 goto err_free;
1807 }
1808
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001809 mr->ibmr.device = pd->device;
1810 mr->umem = NULL;
Max Gurtovoy6c984472019-06-11 18:52:42 +03001811
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001812 switch (mr_type) {
1813 case IB_MR_TYPE_MEM_REG:
1814 err = mlx5_alloc_mem_reg_descs(pd, mr, ndescs, in, inlen);
1815 break;
1816 case IB_MR_TYPE_SG_GAPS:
1817 err = mlx5_alloc_sg_gaps_descs(pd, mr, ndescs, in, inlen);
1818 break;
1819 case IB_MR_TYPE_INTEGRITY:
1820 err = mlx5_alloc_integrity_descs(pd, mr, max_num_sg,
1821 max_num_meta_sg, in, inlen);
1822 break;
1823 default:
Sagi Grimberg9bee1782015-07-30 10:32:35 +03001824 mlx5_ib_warn(dev, "Invalid mr type %d\n", mr_type);
1825 err = -EINVAL;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001826 }
1827
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001828 if (err)
Max Gurtovoy7796d2a2019-06-11 18:52:57 +03001829 goto err_free_in;
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001830
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001831 kfree(in);
1832
1833 return &mr->ibmr;
1834
Sagi Grimberg3121e3c2014-02-23 14:19:06 +02001835err_free_in:
1836 kfree(in);
1837err_free:
1838 kfree(mr);
1839 return ERR_PTR(err);
1840}
1841
Max Gurtovoy6c984472019-06-11 18:52:42 +03001842struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
1843 u32 max_num_sg, struct ib_udata *udata)
1844{
1845 return __mlx5_ib_alloc_mr(pd, mr_type, max_num_sg, 0);
1846}
1847
1848struct ib_mr *mlx5_ib_alloc_mr_integrity(struct ib_pd *pd,
1849 u32 max_num_sg, u32 max_num_meta_sg)
1850{
1851 return __mlx5_ib_alloc_mr(pd, IB_MR_TYPE_INTEGRITY, max_num_sg,
1852 max_num_meta_sg);
1853}
1854
Matan Barakd2370e02016-02-29 18:05:30 +02001855struct ib_mw *mlx5_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
1856 struct ib_udata *udata)
1857{
1858 struct mlx5_ib_dev *dev = to_mdev(pd->device);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001859 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
Matan Barakd2370e02016-02-29 18:05:30 +02001860 struct mlx5_ib_mw *mw = NULL;
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001861 u32 *in = NULL;
1862 void *mkc;
Matan Barakd2370e02016-02-29 18:05:30 +02001863 int ndescs;
1864 int err;
1865 struct mlx5_ib_alloc_mw req = {};
1866 struct {
1867 __u32 comp_mask;
1868 __u32 response_length;
1869 } resp = {};
1870
1871 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
1872 if (err)
1873 return ERR_PTR(err);
1874
1875 if (req.comp_mask || req.reserved1 || req.reserved2)
1876 return ERR_PTR(-EOPNOTSUPP);
1877
1878 if (udata->inlen > sizeof(req) &&
1879 !ib_is_udata_cleared(udata, sizeof(req),
1880 udata->inlen - sizeof(req)))
1881 return ERR_PTR(-EOPNOTSUPP);
1882
1883 ndescs = req.num_klms ? roundup(req.num_klms, 4) : roundup(1, 4);
1884
1885 mw = kzalloc(sizeof(*mw), GFP_KERNEL);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001886 in = kzalloc(inlen, GFP_KERNEL);
Matan Barakd2370e02016-02-29 18:05:30 +02001887 if (!mw || !in) {
1888 err = -ENOMEM;
1889 goto free;
1890 }
1891
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001892 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
Matan Barakd2370e02016-02-29 18:05:30 +02001893
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001894 MLX5_SET(mkc, mkc, free, 1);
1895 MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
1896 MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
1897 MLX5_SET(mkc, mkc, umr_en, 1);
1898 MLX5_SET(mkc, mkc, lr, 1);
Ariel Levkovichcdbd0d22018-04-05 18:53:28 +03001899 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_KLMS);
Saeed Mahameedec22eb52016-07-16 06:28:36 +03001900 MLX5_SET(mkc, mkc, en_rinval, !!((type == IB_MW_TYPE_2)));
1901 MLX5_SET(mkc, mkc, qpn, 0xffffff);
1902
1903 err = mlx5_core_create_mkey(dev->mdev, &mw->mmkey, in, inlen);
Matan Barakd2370e02016-02-29 18:05:30 +02001904 if (err)
1905 goto free;
1906
Artemy Kovalyovaa8e08d2017-01-02 11:37:48 +02001907 mw->mmkey.type = MLX5_MKEY_MW;
Matan Barakd2370e02016-02-29 18:05:30 +02001908 mw->ibmw.rkey = mw->mmkey.key;
Artemy Kovalyovdb570d72017-04-05 09:23:59 +03001909 mw->ndescs = ndescs;
Matan Barakd2370e02016-02-29 18:05:30 +02001910
1911 resp.response_length = min(offsetof(typeof(resp), response_length) +
1912 sizeof(resp.response_length), udata->outlen);
1913 if (resp.response_length) {
1914 err = ib_copy_to_udata(udata, &resp, resp.response_length);
1915 if (err) {
1916 mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
1917 goto free;
1918 }
1919 }
1920
Jason Gunthorpe806b1012019-10-09 13:09:23 -03001921 if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
1922 err = xa_err(xa_store(&dev->odp_mkeys,
1923 mlx5_base_mkey(mw->mmkey.key), &mw->mmkey,
1924 GFP_KERNEL));
1925 if (err)
1926 goto free_mkey;
1927 }
1928
Matan Barakd2370e02016-02-29 18:05:30 +02001929 kfree(in);
1930 return &mw->ibmw;
1931
Jason Gunthorpe806b1012019-10-09 13:09:23 -03001932free_mkey:
1933 mlx5_core_destroy_mkey(dev->mdev, &mw->mmkey);
Matan Barakd2370e02016-02-29 18:05:30 +02001934free:
1935 kfree(mw);
1936 kfree(in);
1937 return ERR_PTR(err);
1938}
1939
1940int mlx5_ib_dealloc_mw(struct ib_mw *mw)
1941{
Jason Gunthorpe04177912019-10-01 12:38:21 -03001942 struct mlx5_ib_dev *dev = to_mdev(mw->device);
Matan Barakd2370e02016-02-29 18:05:30 +02001943 struct mlx5_ib_mw *mmw = to_mmw(mw);
1944 int err;
1945
Jason Gunthorpe04177912019-10-01 12:38:21 -03001946 if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
Jason Gunthorpe806b1012019-10-09 13:09:23 -03001947 xa_erase(&dev->odp_mkeys, mlx5_base_mkey(mmw->mmkey.key));
Jason Gunthorpe04177912019-10-01 12:38:21 -03001948 /*
1949 * pagefault_single_data_segment() may be accessing mmw under
1950 * SRCU if the user bound an ODP MR to this MW.
1951 */
Jason Gunthorpe806b1012019-10-09 13:09:23 -03001952 synchronize_srcu(&dev->odp_srcu);
Jason Gunthorpe04177912019-10-01 12:38:21 -03001953 }
1954
1955 err = mlx5_core_destroy_mkey(dev->mdev, &mmw->mmkey);
1956 if (err)
1957 return err;
1958 kfree(mmw);
1959 return 0;
Matan Barakd2370e02016-02-29 18:05:30 +02001960}
1961
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02001962int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
1963 struct ib_mr_status *mr_status)
1964{
1965 struct mlx5_ib_mr *mmr = to_mmr(ibmr);
1966 int ret = 0;
1967
1968 if (check_mask & ~IB_MR_CHECK_SIG_STATUS) {
1969 pr_err("Invalid status check mask\n");
1970 ret = -EINVAL;
1971 goto done;
1972 }
1973
1974 mr_status->fail_status = 0;
1975 if (check_mask & IB_MR_CHECK_SIG_STATUS) {
1976 if (!mmr->sig) {
1977 ret = -EINVAL;
1978 pr_err("signature status check requested on a non-signature enabled MR\n");
1979 goto done;
1980 }
1981
1982 mmr->sig->sig_status_checked = true;
1983 if (!mmr->sig->sig_err_exists)
1984 goto done;
1985
1986 if (ibmr->lkey == mmr->sig->err_item.key)
1987 memcpy(&mr_status->sig_err, &mmr->sig->err_item,
1988 sizeof(mr_status->sig_err));
1989 else {
1990 mr_status->sig_err.err_type = IB_SIG_BAD_GUARD;
1991 mr_status->sig_err.sig_err_offset = 0;
1992 mr_status->sig_err.key = mmr->sig->err_item.key;
1993 }
1994
1995 mmr->sig->sig_err_exists = false;
1996 mr_status->fail_status |= IB_MR_CHECK_SIG_STATUS;
1997 }
1998
1999done:
2000 return ret;
2001}
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03002002
Sagi Grimbergb005d312016-02-29 19:07:33 +02002003static int
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002004mlx5_ib_map_pa_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
2005 int data_sg_nents, unsigned int *data_sg_offset,
2006 struct scatterlist *meta_sg, int meta_sg_nents,
2007 unsigned int *meta_sg_offset)
2008{
2009 struct mlx5_ib_mr *mr = to_mmr(ibmr);
2010 unsigned int sg_offset = 0;
2011 int n = 0;
2012
2013 mr->meta_length = 0;
2014 if (data_sg_nents == 1) {
2015 n++;
2016 mr->ndescs = 1;
2017 if (data_sg_offset)
2018 sg_offset = *data_sg_offset;
2019 mr->data_length = sg_dma_len(data_sg) - sg_offset;
2020 mr->data_iova = sg_dma_address(data_sg) + sg_offset;
2021 if (meta_sg_nents == 1) {
2022 n++;
2023 mr->meta_ndescs = 1;
2024 if (meta_sg_offset)
2025 sg_offset = *meta_sg_offset;
2026 else
2027 sg_offset = 0;
2028 mr->meta_length = sg_dma_len(meta_sg) - sg_offset;
2029 mr->pi_iova = sg_dma_address(meta_sg) + sg_offset;
2030 }
2031 ibmr->length = mr->data_length + mr->meta_length;
2032 }
2033
2034 return n;
2035}
2036
2037static int
Sagi Grimbergb005d312016-02-29 19:07:33 +02002038mlx5_ib_sg_to_klms(struct mlx5_ib_mr *mr,
2039 struct scatterlist *sgl,
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002040 unsigned short sg_nents,
Max Gurtovoy6c984472019-06-11 18:52:42 +03002041 unsigned int *sg_offset_p,
2042 struct scatterlist *meta_sgl,
2043 unsigned short meta_sg_nents,
2044 unsigned int *meta_sg_offset_p)
Sagi Grimbergb005d312016-02-29 19:07:33 +02002045{
2046 struct scatterlist *sg = sgl;
2047 struct mlx5_klm *klms = mr->descs;
Bart Van Assche9aa8b322016-05-12 10:49:15 -07002048 unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002049 u32 lkey = mr->ibmr.pd->local_dma_lkey;
Max Gurtovoy6c984472019-06-11 18:52:42 +03002050 int i, j = 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002051
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002052 mr->ibmr.iova = sg_dma_address(sg) + sg_offset;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002053 mr->ibmr.length = 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002054
2055 for_each_sg(sgl, sg, sg_nents, i) {
Bart Van Assche99975cd2017-04-24 15:15:28 -07002056 if (unlikely(i >= mr->max_descs))
Sagi Grimbergb005d312016-02-29 19:07:33 +02002057 break;
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002058 klms[i].va = cpu_to_be64(sg_dma_address(sg) + sg_offset);
2059 klms[i].bcount = cpu_to_be32(sg_dma_len(sg) - sg_offset);
Sagi Grimbergb005d312016-02-29 19:07:33 +02002060 klms[i].key = cpu_to_be32(lkey);
Sagi Grimberg0a49f2c2017-04-23 14:31:42 +03002061 mr->ibmr.length += sg_dma_len(sg) - sg_offset;
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002062
2063 sg_offset = 0;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002064 }
2065
Bart Van Assche9aa8b322016-05-12 10:49:15 -07002066 if (sg_offset_p)
2067 *sg_offset_p = sg_offset;
2068
Max Gurtovoy6c984472019-06-11 18:52:42 +03002069 mr->ndescs = i;
2070 mr->data_length = mr->ibmr.length;
2071
2072 if (meta_sg_nents) {
2073 sg = meta_sgl;
2074 sg_offset = meta_sg_offset_p ? *meta_sg_offset_p : 0;
2075 for_each_sg(meta_sgl, sg, meta_sg_nents, j) {
2076 if (unlikely(i + j >= mr->max_descs))
2077 break;
2078 klms[i + j].va = cpu_to_be64(sg_dma_address(sg) +
2079 sg_offset);
2080 klms[i + j].bcount = cpu_to_be32(sg_dma_len(sg) -
2081 sg_offset);
2082 klms[i + j].key = cpu_to_be32(lkey);
2083 mr->ibmr.length += sg_dma_len(sg) - sg_offset;
2084
2085 sg_offset = 0;
2086 }
2087 if (meta_sg_offset_p)
2088 *meta_sg_offset_p = sg_offset;
2089
2090 mr->meta_ndescs = j;
2091 mr->meta_length = mr->ibmr.length - mr->data_length;
2092 }
2093
2094 return i + j;
Sagi Grimbergb005d312016-02-29 19:07:33 +02002095}
2096
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03002097static int mlx5_set_page(struct ib_mr *ibmr, u64 addr)
2098{
2099 struct mlx5_ib_mr *mr = to_mmr(ibmr);
2100 __be64 *descs;
2101
2102 if (unlikely(mr->ndescs == mr->max_descs))
2103 return -ENOMEM;
2104
2105 descs = mr->descs;
2106 descs[mr->ndescs++] = cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
2107
2108 return 0;
2109}
2110
Israel Rukshinde0ae952019-06-11 18:52:55 +03002111static int mlx5_set_page_pi(struct ib_mr *ibmr, u64 addr)
2112{
2113 struct mlx5_ib_mr *mr = to_mmr(ibmr);
2114 __be64 *descs;
2115
2116 if (unlikely(mr->ndescs + mr->meta_ndescs == mr->max_descs))
2117 return -ENOMEM;
2118
2119 descs = mr->descs;
2120 descs[mr->ndescs + mr->meta_ndescs++] =
2121 cpu_to_be64(addr | MLX5_EN_RD | MLX5_EN_WR);
2122
2123 return 0;
2124}
2125
2126static int
2127mlx5_ib_map_mtt_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
Max Gurtovoy6c984472019-06-11 18:52:42 +03002128 int data_sg_nents, unsigned int *data_sg_offset,
2129 struct scatterlist *meta_sg, int meta_sg_nents,
2130 unsigned int *meta_sg_offset)
2131{
2132 struct mlx5_ib_mr *mr = to_mmr(ibmr);
Israel Rukshinde0ae952019-06-11 18:52:55 +03002133 struct mlx5_ib_mr *pi_mr = mr->mtt_mr;
Max Gurtovoy6c984472019-06-11 18:52:42 +03002134 int n;
2135
Israel Rukshinde0ae952019-06-11 18:52:55 +03002136 pi_mr->ndescs = 0;
2137 pi_mr->meta_ndescs = 0;
2138 pi_mr->meta_length = 0;
2139
2140 ib_dma_sync_single_for_cpu(ibmr->device, pi_mr->desc_map,
2141 pi_mr->desc_size * pi_mr->max_descs,
2142 DMA_TO_DEVICE);
2143
2144 pi_mr->ibmr.page_size = ibmr->page_size;
2145 n = ib_sg_to_pages(&pi_mr->ibmr, data_sg, data_sg_nents, data_sg_offset,
2146 mlx5_set_page);
2147 if (n != data_sg_nents)
2148 return n;
2149
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002150 pi_mr->data_iova = pi_mr->ibmr.iova;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002151 pi_mr->data_length = pi_mr->ibmr.length;
2152 pi_mr->ibmr.length = pi_mr->data_length;
2153 ibmr->length = pi_mr->data_length;
2154
2155 if (meta_sg_nents) {
2156 u64 page_mask = ~((u64)ibmr->page_size - 1);
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002157 u64 iova = pi_mr->data_iova;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002158
2159 n += ib_sg_to_pages(&pi_mr->ibmr, meta_sg, meta_sg_nents,
2160 meta_sg_offset, mlx5_set_page_pi);
2161
2162 pi_mr->meta_length = pi_mr->ibmr.length;
2163 /*
2164 * PI address for the HW is the offset of the metadata address
2165 * relative to the first data page address.
2166 * It equals to first data page address + size of data pages +
2167 * metadata offset at the first metadata page
2168 */
2169 pi_mr->pi_iova = (iova & page_mask) +
2170 pi_mr->ndescs * ibmr->page_size +
2171 (pi_mr->ibmr.iova & ~page_mask);
2172 /*
2173 * In order to use one MTT MR for data and metadata, we register
2174 * also the gaps between the end of the data and the start of
2175 * the metadata (the sig MR will verify that the HW will access
2176 * to right addresses). This mapping is safe because we use
2177 * internal mkey for the registration.
2178 */
2179 pi_mr->ibmr.length = pi_mr->pi_iova + pi_mr->meta_length - iova;
2180 pi_mr->ibmr.iova = iova;
2181 ibmr->length += pi_mr->meta_length;
2182 }
2183
2184 ib_dma_sync_single_for_device(ibmr->device, pi_mr->desc_map,
2185 pi_mr->desc_size * pi_mr->max_descs,
2186 DMA_TO_DEVICE);
2187
2188 return n;
2189}
2190
2191static int
2192mlx5_ib_map_klm_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
2193 int data_sg_nents, unsigned int *data_sg_offset,
2194 struct scatterlist *meta_sg, int meta_sg_nents,
2195 unsigned int *meta_sg_offset)
2196{
2197 struct mlx5_ib_mr *mr = to_mmr(ibmr);
2198 struct mlx5_ib_mr *pi_mr = mr->klm_mr;
2199 int n;
Max Gurtovoy6c984472019-06-11 18:52:42 +03002200
2201 pi_mr->ndescs = 0;
2202 pi_mr->meta_ndescs = 0;
2203 pi_mr->meta_length = 0;
2204
2205 ib_dma_sync_single_for_cpu(ibmr->device, pi_mr->desc_map,
2206 pi_mr->desc_size * pi_mr->max_descs,
2207 DMA_TO_DEVICE);
2208
2209 n = mlx5_ib_sg_to_klms(pi_mr, data_sg, data_sg_nents, data_sg_offset,
2210 meta_sg, meta_sg_nents, meta_sg_offset);
2211
Max Gurtovoy6c984472019-06-11 18:52:42 +03002212 ib_dma_sync_single_for_device(ibmr->device, pi_mr->desc_map,
2213 pi_mr->desc_size * pi_mr->max_descs,
2214 DMA_TO_DEVICE);
2215
Israel Rukshinde0ae952019-06-11 18:52:55 +03002216 /* This is zero-based memory region */
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002217 pi_mr->data_iova = 0;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002218 pi_mr->ibmr.iova = 0;
2219 pi_mr->pi_iova = pi_mr->data_length;
2220 ibmr->length = pi_mr->ibmr.length;
2221
2222 return n;
2223}
2224
2225int mlx5_ib_map_mr_sg_pi(struct ib_mr *ibmr, struct scatterlist *data_sg,
2226 int data_sg_nents, unsigned int *data_sg_offset,
2227 struct scatterlist *meta_sg, int meta_sg_nents,
2228 unsigned int *meta_sg_offset)
2229{
2230 struct mlx5_ib_mr *mr = to_mmr(ibmr);
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002231 struct mlx5_ib_mr *pi_mr = NULL;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002232 int n;
2233
2234 WARN_ON(ibmr->type != IB_MR_TYPE_INTEGRITY);
2235
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002236 mr->ndescs = 0;
2237 mr->data_length = 0;
2238 mr->data_iova = 0;
2239 mr->meta_ndescs = 0;
2240 mr->pi_iova = 0;
2241 /*
2242 * As a performance optimization, if possible, there is no need to
2243 * perform UMR operation to register the data/metadata buffers.
2244 * First try to map the sg lists to PA descriptors with local_dma_lkey.
2245 * Fallback to UMR only in case of a failure.
2246 */
2247 n = mlx5_ib_map_pa_mr_sg_pi(ibmr, data_sg, data_sg_nents,
2248 data_sg_offset, meta_sg, meta_sg_nents,
2249 meta_sg_offset);
2250 if (n == data_sg_nents + meta_sg_nents)
2251 goto out;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002252 /*
2253 * As a performance optimization, if possible, there is no need to map
2254 * the sg lists to KLM descriptors. First try to map the sg lists to MTT
2255 * descriptors and fallback to KLM only in case of a failure.
2256 * It's more efficient for the HW to work with MTT descriptors
2257 * (especially in high load).
2258 * Use KLM (indirect access) only if it's mandatory.
2259 */
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002260 pi_mr = mr->mtt_mr;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002261 n = mlx5_ib_map_mtt_mr_sg_pi(ibmr, data_sg, data_sg_nents,
2262 data_sg_offset, meta_sg, meta_sg_nents,
2263 meta_sg_offset);
2264 if (n == data_sg_nents + meta_sg_nents)
2265 goto out;
2266
2267 pi_mr = mr->klm_mr;
2268 n = mlx5_ib_map_klm_mr_sg_pi(ibmr, data_sg, data_sg_nents,
2269 data_sg_offset, meta_sg, meta_sg_nents,
2270 meta_sg_offset);
Max Gurtovoy6c984472019-06-11 18:52:42 +03002271 if (unlikely(n != data_sg_nents + meta_sg_nents))
2272 return -ENOMEM;
2273
Israel Rukshinde0ae952019-06-11 18:52:55 +03002274out:
2275 /* This is zero-based memory region */
2276 ibmr->iova = 0;
2277 mr->pi_mr = pi_mr;
Max Gurtovoy2563e2f2019-06-11 18:52:56 +03002278 if (pi_mr)
2279 ibmr->sig_attrs->meta_length = pi_mr->meta_length;
2280 else
2281 ibmr->sig_attrs->meta_length = mr->meta_length;
Israel Rukshinde0ae952019-06-11 18:52:55 +03002282
Max Gurtovoy6c984472019-06-11 18:52:42 +03002283 return 0;
2284}
2285
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002286int mlx5_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
Bart Van Assche9aa8b322016-05-12 10:49:15 -07002287 unsigned int *sg_offset)
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03002288{
2289 struct mlx5_ib_mr *mr = to_mmr(ibmr);
2290 int n;
2291
2292 mr->ndescs = 0;
2293
2294 ib_dma_sync_single_for_cpu(ibmr->device, mr->desc_map,
2295 mr->desc_size * mr->max_descs,
2296 DMA_TO_DEVICE);
2297
Saeed Mahameedec22eb52016-07-16 06:28:36 +03002298 if (mr->access_mode == MLX5_MKC_ACCESS_MODE_KLMS)
Max Gurtovoy6c984472019-06-11 18:52:42 +03002299 n = mlx5_ib_sg_to_klms(mr, sg, sg_nents, sg_offset, NULL, 0,
2300 NULL);
Sagi Grimbergb005d312016-02-29 19:07:33 +02002301 else
Christoph Hellwigff2ba992016-05-03 18:01:04 +02002302 n = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset,
2303 mlx5_set_page);
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03002304
2305 ib_dma_sync_single_for_device(ibmr->device, mr->desc_map,
2306 mr->desc_size * mr->max_descs,
2307 DMA_TO_DEVICE);
2308
2309 return n;
2310}