Merge tag 'drm-msm-fixes-2024-02-28' of https://gitlab.freedesktop.org/drm/msm into...
[linux-2.6-microblaze.git] / drivers / vdpa / mlx5 / core / mr.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies Ltd. */
3
4 #include <linux/vhost_types.h>
5 #include <linux/vdpa.h>
6 #include <linux/gcd.h>
7 #include <linux/string.h>
8 #include <linux/mlx5/qp.h>
9 #include "mlx5_vdpa.h"
10
11 /* DIV_ROUND_UP where the divider is a power of 2 give by its log base 2 value */
12 #define MLX5_DIV_ROUND_UP_POW2(_n, _s) \
13 ({ \
14         u64 __s = _s; \
15         u64 _res; \
16         _res = (((_n) + (1 << (__s)) - 1) >> (__s)); \
17         _res; \
18 })
19
20 static int get_octo_len(u64 len, int page_shift)
21 {
22         u64 page_size = 1ULL << page_shift;
23         int npages;
24
25         npages = ALIGN(len, page_size) >> page_shift;
26         return (npages + 1) / 2;
27 }
28
29 static void mlx5_set_access_mode(void *mkc, int mode)
30 {
31         MLX5_SET(mkc, mkc, access_mode_1_0, mode & 0x3);
32         MLX5_SET(mkc, mkc, access_mode_4_2, mode >> 2);
33 }
34
35 static void populate_mtts(struct mlx5_vdpa_direct_mr *mr, __be64 *mtt)
36 {
37         struct scatterlist *sg;
38         int nsg = mr->nsg;
39         u64 dma_addr;
40         u64 dma_len;
41         int j = 0;
42         int i;
43
44         for_each_sg(mr->sg_head.sgl, sg, mr->nent, i) {
45                 for (dma_addr = sg_dma_address(sg), dma_len = sg_dma_len(sg);
46                      nsg && dma_len;
47                      nsg--, dma_addr += BIT(mr->log_size), dma_len -= BIT(mr->log_size))
48                         mtt[j++] = cpu_to_be64(dma_addr);
49         }
50 }
51
52 static int create_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr)
53 {
54         int inlen;
55         void *mkc;
56         void *in;
57         int err;
58
59         inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + roundup(MLX5_ST_SZ_BYTES(mtt) * mr->nsg, 16);
60         in = kvzalloc(inlen, GFP_KERNEL);
61         if (!in)
62                 return -ENOMEM;
63
64         MLX5_SET(create_mkey_in, in, uid, mvdev->res.uid);
65         mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
66         MLX5_SET(mkc, mkc, lw, !!(mr->perm & VHOST_MAP_WO));
67         MLX5_SET(mkc, mkc, lr, !!(mr->perm & VHOST_MAP_RO));
68         mlx5_set_access_mode(mkc, MLX5_MKC_ACCESS_MODE_MTT);
69         MLX5_SET(mkc, mkc, qpn, 0xffffff);
70         MLX5_SET(mkc, mkc, pd, mvdev->res.pdn);
71         MLX5_SET64(mkc, mkc, start_addr, mr->offset);
72         MLX5_SET64(mkc, mkc, len, mr->end - mr->start);
73         MLX5_SET(mkc, mkc, log_page_size, mr->log_size);
74         MLX5_SET(mkc, mkc, translations_octword_size,
75                  get_octo_len(mr->end - mr->start, mr->log_size));
76         MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
77                  get_octo_len(mr->end - mr->start, mr->log_size));
78         populate_mtts(mr, MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt));
79         err = mlx5_vdpa_create_mkey(mvdev, &mr->mr, in, inlen);
80         kvfree(in);
81         if (err) {
82                 mlx5_vdpa_warn(mvdev, "Failed to create direct MR\n");
83                 return err;
84         }
85
86         return 0;
87 }
88
89 static void destroy_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr)
90 {
91         mlx5_vdpa_destroy_mkey(mvdev, mr->mr);
92 }
93
94 static u64 map_start(struct vhost_iotlb_map *map, struct mlx5_vdpa_direct_mr *mr)
95 {
96         return max_t(u64, map->start, mr->start);
97 }
98
99 static u64 map_end(struct vhost_iotlb_map *map, struct mlx5_vdpa_direct_mr *mr)
100 {
101         return min_t(u64, map->last + 1, mr->end);
102 }
103
104 static u64 maplen(struct vhost_iotlb_map *map, struct mlx5_vdpa_direct_mr *mr)
105 {
106         return map_end(map, mr) - map_start(map, mr);
107 }
108
109 #define MLX5_VDPA_INVALID_START_ADDR ((u64)-1)
110 #define MLX5_VDPA_INVALID_LEN ((u64)-1)
111
112 static u64 indir_start_addr(struct mlx5_vdpa_mr *mkey)
113 {
114         struct mlx5_vdpa_direct_mr *s;
115
116         s = list_first_entry_or_null(&mkey->head, struct mlx5_vdpa_direct_mr, list);
117         if (!s)
118                 return MLX5_VDPA_INVALID_START_ADDR;
119
120         return s->start;
121 }
122
123 static u64 indir_len(struct mlx5_vdpa_mr *mkey)
124 {
125         struct mlx5_vdpa_direct_mr *s;
126         struct mlx5_vdpa_direct_mr *e;
127
128         s = list_first_entry_or_null(&mkey->head, struct mlx5_vdpa_direct_mr, list);
129         if (!s)
130                 return MLX5_VDPA_INVALID_LEN;
131
132         e = list_last_entry(&mkey->head, struct mlx5_vdpa_direct_mr, list);
133
134         return e->end - s->start;
135 }
136
137 #define LOG_MAX_KLM_SIZE 30
138 #define MAX_KLM_SIZE BIT(LOG_MAX_KLM_SIZE)
139
140 static u32 klm_bcount(u64 size)
141 {
142         return (u32)size;
143 }
144
145 static void fill_indir(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mkey, void *in)
146 {
147         struct mlx5_vdpa_direct_mr *dmr;
148         struct mlx5_klm *klmarr;
149         struct mlx5_klm *klm;
150         bool first = true;
151         u64 preve;
152         int i;
153
154         klmarr = MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
155         i = 0;
156         list_for_each_entry(dmr, &mkey->head, list) {
157 again:
158                 klm = &klmarr[i++];
159                 if (first) {
160                         preve = dmr->start;
161                         first = false;
162                 }
163
164                 if (preve == dmr->start) {
165                         klm->key = cpu_to_be32(dmr->mr);
166                         klm->bcount = cpu_to_be32(klm_bcount(dmr->end - dmr->start));
167                         preve = dmr->end;
168                 } else {
169                         klm->key = cpu_to_be32(mvdev->res.null_mkey);
170                         klm->bcount = cpu_to_be32(klm_bcount(dmr->start - preve));
171                         preve = dmr->start;
172                         goto again;
173                 }
174         }
175 }
176
177 static int klm_byte_size(int nklms)
178 {
179         return 16 * ALIGN(nklms, 4);
180 }
181
182 static int create_indirect_key(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
183 {
184         int inlen;
185         void *mkc;
186         void *in;
187         int err;
188         u64 start;
189         u64 len;
190
191         start = indir_start_addr(mr);
192         len = indir_len(mr);
193         if (start == MLX5_VDPA_INVALID_START_ADDR || len == MLX5_VDPA_INVALID_LEN)
194                 return -EINVAL;
195
196         inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + klm_byte_size(mr->num_klms);
197         in = kzalloc(inlen, GFP_KERNEL);
198         if (!in)
199                 return -ENOMEM;
200
201         MLX5_SET(create_mkey_in, in, uid, mvdev->res.uid);
202         mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
203         MLX5_SET(mkc, mkc, lw, 1);
204         MLX5_SET(mkc, mkc, lr, 1);
205         mlx5_set_access_mode(mkc, MLX5_MKC_ACCESS_MODE_KLMS);
206         MLX5_SET(mkc, mkc, qpn, 0xffffff);
207         MLX5_SET(mkc, mkc, pd, mvdev->res.pdn);
208         MLX5_SET64(mkc, mkc, start_addr, start);
209         MLX5_SET64(mkc, mkc, len, len);
210         MLX5_SET(mkc, mkc, translations_octword_size, klm_byte_size(mr->num_klms) / 16);
211         MLX5_SET(create_mkey_in, in, translations_octword_actual_size, mr->num_klms);
212         fill_indir(mvdev, mr, in);
213         err = mlx5_vdpa_create_mkey(mvdev, &mr->mkey, in, inlen);
214         kfree(in);
215         return err;
216 }
217
218 static void destroy_indirect_key(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mkey)
219 {
220         mlx5_vdpa_destroy_mkey(mvdev, mkey->mkey);
221 }
222
223 static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr,
224                          struct vhost_iotlb *iotlb)
225 {
226         struct vhost_iotlb_map *map;
227         unsigned long lgcd = 0;
228         int log_entity_size;
229         unsigned long size;
230         u64 start = 0;
231         int err;
232         struct page *pg;
233         unsigned int nsg;
234         int sglen;
235         u64 pa;
236         u64 paend;
237         struct scatterlist *sg;
238         struct device *dma = mvdev->vdev.dma_dev;
239
240         for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1);
241              map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) {
242                 size = maplen(map, mr);
243                 lgcd = gcd(lgcd, size);
244                 start += size;
245         }
246         log_entity_size = ilog2(lgcd);
247
248         sglen = 1 << log_entity_size;
249         nsg = MLX5_DIV_ROUND_UP_POW2(mr->end - mr->start, log_entity_size);
250
251         err = sg_alloc_table(&mr->sg_head, nsg, GFP_KERNEL);
252         if (err)
253                 return err;
254
255         sg = mr->sg_head.sgl;
256         for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1);
257              map; map = vhost_iotlb_itree_next(map, mr->start, mr->end - 1)) {
258                 paend = map->addr + maplen(map, mr);
259                 for (pa = map->addr; pa < paend; pa += sglen) {
260                         pg = pfn_to_page(__phys_to_pfn(pa));
261                         if (!sg) {
262                                 mlx5_vdpa_warn(mvdev, "sg null. start 0x%llx, end 0x%llx\n",
263                                                map->start, map->last + 1);
264                                 err = -ENOMEM;
265                                 goto err_map;
266                         }
267                         sg_set_page(sg, pg, sglen, 0);
268                         sg = sg_next(sg);
269                         if (!sg)
270                                 goto done;
271                 }
272         }
273 done:
274         mr->log_size = log_entity_size;
275         mr->nsg = nsg;
276         mr->nent = dma_map_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
277         if (!mr->nent) {
278                 err = -ENOMEM;
279                 goto err_map;
280         }
281
282         err = create_direct_mr(mvdev, mr);
283         if (err)
284                 goto err_direct;
285
286         return 0;
287
288 err_direct:
289         dma_unmap_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
290 err_map:
291         sg_free_table(&mr->sg_head);
292         return err;
293 }
294
295 static void unmap_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr)
296 {
297         struct device *dma = mvdev->vdev.dma_dev;
298
299         destroy_direct_mr(mvdev, mr);
300         dma_unmap_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0);
301         sg_free_table(&mr->sg_head);
302 }
303
304 static int add_direct_chain(struct mlx5_vdpa_dev *mvdev,
305                             struct mlx5_vdpa_mr *mr,
306                             u64 start,
307                             u64 size,
308                             u8 perm,
309                             struct vhost_iotlb *iotlb)
310 {
311         struct mlx5_vdpa_direct_mr *dmr;
312         struct mlx5_vdpa_direct_mr *n;
313         LIST_HEAD(tmp);
314         u64 st;
315         u64 sz;
316         int err;
317
318         st = start;
319         while (size) {
320                 sz = (u32)min_t(u64, MAX_KLM_SIZE, size);
321                 dmr = kzalloc(sizeof(*dmr), GFP_KERNEL);
322                 if (!dmr) {
323                         err = -ENOMEM;
324                         goto err_alloc;
325                 }
326
327                 dmr->start = st;
328                 dmr->end = st + sz;
329                 dmr->perm = perm;
330                 err = map_direct_mr(mvdev, dmr, iotlb);
331                 if (err) {
332                         kfree(dmr);
333                         goto err_alloc;
334                 }
335
336                 list_add_tail(&dmr->list, &tmp);
337                 size -= sz;
338                 mr->num_directs++;
339                 mr->num_klms++;
340                 st += sz;
341         }
342         list_splice_tail(&tmp, &mr->head);
343         return 0;
344
345 err_alloc:
346         list_for_each_entry_safe(dmr, n, &mr->head, list) {
347                 list_del_init(&dmr->list);
348                 unmap_direct_mr(mvdev, dmr);
349                 kfree(dmr);
350         }
351         return err;
352 }
353
354 /* The iotlb pointer contains a list of maps. Go over the maps, possibly
355  * merging mergeable maps, and create direct memory keys that provide the
356  * device access to memory. The direct mkeys are then referred to by the
357  * indirect memory key that provides access to the enitre address space given
358  * by iotlb.
359  */
360 static int create_user_mr(struct mlx5_vdpa_dev *mvdev,
361                           struct mlx5_vdpa_mr *mr,
362                           struct vhost_iotlb *iotlb)
363 {
364         struct mlx5_vdpa_direct_mr *dmr;
365         struct mlx5_vdpa_direct_mr *n;
366         struct vhost_iotlb_map *map;
367         u32 pperm = U16_MAX;
368         u64 last = U64_MAX;
369         u64 ps = U64_MAX;
370         u64 pe = U64_MAX;
371         u64 start = 0;
372         int err = 0;
373         int nnuls;
374
375         INIT_LIST_HEAD(&mr->head);
376         for (map = vhost_iotlb_itree_first(iotlb, start, last); map;
377              map = vhost_iotlb_itree_next(map, start, last)) {
378                 start = map->start;
379                 if (pe == map->start && pperm == map->perm) {
380                         pe = map->last + 1;
381                 } else {
382                         if (ps != U64_MAX) {
383                                 if (pe < map->start) {
384                                         /* We have a hole in the map. Check how
385                                          * many null keys are required to fill it.
386                                          */
387                                         nnuls = MLX5_DIV_ROUND_UP_POW2(map->start - pe,
388                                                                        LOG_MAX_KLM_SIZE);
389                                         mr->num_klms += nnuls;
390                                 }
391                                 err = add_direct_chain(mvdev, mr, ps, pe - ps, pperm, iotlb);
392                                 if (err)
393                                         goto err_chain;
394                         }
395                         ps = map->start;
396                         pe = map->last + 1;
397                         pperm = map->perm;
398                 }
399         }
400         err = add_direct_chain(mvdev, mr, ps, pe - ps, pperm, iotlb);
401         if (err)
402                 goto err_chain;
403
404         /* Create the memory key that defines the guests's address space. This
405          * memory key refers to the direct keys that contain the MTT
406          * translations
407          */
408         err = create_indirect_key(mvdev, mr);
409         if (err)
410                 goto err_chain;
411
412         mr->user_mr = true;
413         return 0;
414
415 err_chain:
416         list_for_each_entry_safe_reverse(dmr, n, &mr->head, list) {
417                 list_del_init(&dmr->list);
418                 unmap_direct_mr(mvdev, dmr);
419                 kfree(dmr);
420         }
421         return err;
422 }
423
424 static int create_dma_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
425 {
426         int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
427         void *mkc;
428         u32 *in;
429         int err;
430
431         in = kzalloc(inlen, GFP_KERNEL);
432         if (!in)
433                 return -ENOMEM;
434
435         mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
436
437         MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);
438         MLX5_SET(mkc, mkc, length64, 1);
439         MLX5_SET(mkc, mkc, lw, 1);
440         MLX5_SET(mkc, mkc, lr, 1);
441         MLX5_SET(mkc, mkc, pd, mvdev->res.pdn);
442         MLX5_SET(mkc, mkc, qpn, 0xffffff);
443
444         err = mlx5_vdpa_create_mkey(mvdev, &mr->mkey, in, inlen);
445         if (!err)
446                 mr->user_mr = false;
447
448         kfree(in);
449         return err;
450 }
451
452 static void destroy_dma_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
453 {
454         mlx5_vdpa_destroy_mkey(mvdev, mr->mkey);
455 }
456
457 static int dup_iotlb(struct vhost_iotlb *dst, struct vhost_iotlb *src)
458 {
459         struct vhost_iotlb_map *map;
460         u64 start = 0, last = ULLONG_MAX;
461         int err;
462
463         if (dst == src)
464                 return -EINVAL;
465
466         if (!src) {
467                 err = vhost_iotlb_add_range(dst, start, last, start, VHOST_ACCESS_RW);
468                 return err;
469         }
470
471         for (map = vhost_iotlb_itree_first(src, start, last); map;
472                 map = vhost_iotlb_itree_next(map, start, last)) {
473                 err = vhost_iotlb_add_range(dst, map->start, map->last,
474                                             map->addr, map->perm);
475                 if (err)
476                         return err;
477         }
478         return 0;
479 }
480
481 static void prune_iotlb(struct vhost_iotlb *iotlb)
482 {
483         vhost_iotlb_del_range(iotlb, 0, ULLONG_MAX);
484 }
485
486 static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
487 {
488         struct mlx5_vdpa_direct_mr *dmr;
489         struct mlx5_vdpa_direct_mr *n;
490
491         destroy_indirect_key(mvdev, mr);
492         list_for_each_entry_safe_reverse(dmr, n, &mr->head, list) {
493                 list_del_init(&dmr->list);
494                 unmap_direct_mr(mvdev, dmr);
495                 kfree(dmr);
496         }
497 }
498
499 static void _mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
500 {
501         if (WARN_ON(!mr))
502                 return;
503
504         if (mr->user_mr)
505                 destroy_user_mr(mvdev, mr);
506         else
507                 destroy_dma_mr(mvdev, mr);
508
509         vhost_iotlb_free(mr->iotlb);
510
511         list_del(&mr->mr_list);
512
513         kfree(mr);
514 }
515
516 static void _mlx5_vdpa_put_mr(struct mlx5_vdpa_dev *mvdev,
517                               struct mlx5_vdpa_mr *mr)
518 {
519         if (!mr)
520                 return;
521
522         if (refcount_dec_and_test(&mr->refcount))
523                 _mlx5_vdpa_destroy_mr(mvdev, mr);
524 }
525
526 void mlx5_vdpa_put_mr(struct mlx5_vdpa_dev *mvdev,
527                       struct mlx5_vdpa_mr *mr)
528 {
529         mutex_lock(&mvdev->mr_mtx);
530         _mlx5_vdpa_put_mr(mvdev, mr);
531         mutex_unlock(&mvdev->mr_mtx);
532 }
533
534 static void _mlx5_vdpa_get_mr(struct mlx5_vdpa_dev *mvdev,
535                               struct mlx5_vdpa_mr *mr)
536 {
537         if (!mr)
538                 return;
539
540         refcount_inc(&mr->refcount);
541 }
542
543 void mlx5_vdpa_get_mr(struct mlx5_vdpa_dev *mvdev,
544                       struct mlx5_vdpa_mr *mr)
545 {
546         mutex_lock(&mvdev->mr_mtx);
547         _mlx5_vdpa_get_mr(mvdev, mr);
548         mutex_unlock(&mvdev->mr_mtx);
549 }
550
551 void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev,
552                          struct mlx5_vdpa_mr *new_mr,
553                          unsigned int asid)
554 {
555         struct mlx5_vdpa_mr *old_mr = mvdev->mr[asid];
556
557         mutex_lock(&mvdev->mr_mtx);
558
559         _mlx5_vdpa_put_mr(mvdev, old_mr);
560         mvdev->mr[asid] = new_mr;
561
562         mutex_unlock(&mvdev->mr_mtx);
563 }
564
565 static void mlx5_vdpa_show_mr_leaks(struct mlx5_vdpa_dev *mvdev)
566 {
567         struct mlx5_vdpa_mr *mr;
568
569         mutex_lock(&mvdev->mr_mtx);
570
571         list_for_each_entry(mr, &mvdev->mr_list_head, mr_list) {
572
573                 mlx5_vdpa_warn(mvdev, "mkey still alive after resource delete: "
574                                       "mr: %p, mkey: 0x%x, refcount: %u\n",
575                                        mr, mr->mkey, refcount_read(&mr->refcount));
576         }
577
578         mutex_unlock(&mvdev->mr_mtx);
579
580 }
581
582 void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev)
583 {
584         for (int i = 0; i < MLX5_VDPA_NUM_AS; i++)
585                 mlx5_vdpa_update_mr(mvdev, NULL, i);
586
587         prune_iotlb(mvdev->cvq.iotlb);
588
589         mlx5_vdpa_show_mr_leaks(mvdev);
590 }
591
592 static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
593                                 struct mlx5_vdpa_mr *mr,
594                                 struct vhost_iotlb *iotlb)
595 {
596         int err;
597
598         if (iotlb)
599                 err = create_user_mr(mvdev, mr, iotlb);
600         else
601                 err = create_dma_mr(mvdev, mr);
602
603         if (err)
604                 return err;
605
606         mr->iotlb = vhost_iotlb_alloc(0, 0);
607         if (!mr->iotlb) {
608                 err = -ENOMEM;
609                 goto err_mr;
610         }
611
612         err = dup_iotlb(mr->iotlb, iotlb);
613         if (err)
614                 goto err_iotlb;
615
616         list_add_tail(&mr->mr_list, &mvdev->mr_list_head);
617
618         return 0;
619
620 err_iotlb:
621         vhost_iotlb_free(mr->iotlb);
622
623 err_mr:
624         if (iotlb)
625                 destroy_user_mr(mvdev, mr);
626         else
627                 destroy_dma_mr(mvdev, mr);
628
629         return err;
630 }
631
632 struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
633                                          struct vhost_iotlb *iotlb)
634 {
635         struct mlx5_vdpa_mr *mr;
636         int err;
637
638         mr = kzalloc(sizeof(*mr), GFP_KERNEL);
639         if (!mr)
640                 return ERR_PTR(-ENOMEM);
641
642         mutex_lock(&mvdev->mr_mtx);
643         err = _mlx5_vdpa_create_mr(mvdev, mr, iotlb);
644         mutex_unlock(&mvdev->mr_mtx);
645
646         if (err)
647                 goto out_err;
648
649         refcount_set(&mr->refcount, 1);
650
651         return mr;
652
653 out_err:
654         kfree(mr);
655         return ERR_PTR(err);
656 }
657
658 int mlx5_vdpa_update_cvq_iotlb(struct mlx5_vdpa_dev *mvdev,
659                                 struct vhost_iotlb *iotlb,
660                                 unsigned int asid)
661 {
662         int err;
663
664         if (mvdev->group2asid[MLX5_VDPA_CVQ_GROUP] != asid)
665                 return 0;
666
667         spin_lock(&mvdev->cvq.iommu_lock);
668
669         prune_iotlb(mvdev->cvq.iotlb);
670         err = dup_iotlb(mvdev->cvq.iotlb, iotlb);
671
672         spin_unlock(&mvdev->cvq.iommu_lock);
673
674         return err;
675 }
676
677 int mlx5_vdpa_create_dma_mr(struct mlx5_vdpa_dev *mvdev)
678 {
679         struct mlx5_vdpa_mr *mr;
680
681         mr = mlx5_vdpa_create_mr(mvdev, NULL);
682         if (IS_ERR(mr))
683                 return PTR_ERR(mr);
684
685         mlx5_vdpa_update_mr(mvdev, mr, 0);
686
687         return mlx5_vdpa_update_cvq_iotlb(mvdev, NULL, 0);
688 }
689
690 int mlx5_vdpa_reset_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
691 {
692         if (asid >= MLX5_VDPA_NUM_AS)
693                 return -EINVAL;
694
695         mlx5_vdpa_update_mr(mvdev, NULL, asid);
696
697         if (asid == 0 && MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) {
698                 if (mlx5_vdpa_create_dma_mr(mvdev))
699                         mlx5_vdpa_warn(mvdev, "create DMA MR failed\n");
700         } else {
701                 mlx5_vdpa_update_cvq_iotlb(mvdev, NULL, asid);
702         }
703
704         return 0;
705 }