diff options
author | Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> | 2018-07-20 05:01:47 -0400 |
---|---|---|
committer | Boris Ostrovsky <boris.ostrovsky@oracle.com> | 2018-07-26 23:05:14 -0400 |
commit | 1d314567553883d9f606cc59e8e66f465a4b6ccd (patch) | |
tree | 9ee9d40f11d02b35ca422ac32a18a3fbacab37b6 /drivers/xen/gntdev.c | |
parent | 975ef7ff81bb000af6e6c8e63e81f89f3468dcf7 (diff) |
xen/gntdev: Make private routines/structures accessible
This is in preparation for adding support of DMA buffer
functionality: make map/unmap related code and structures, used
privately by gntdev, ready for dma-buf extension, which will re-use
these. Rename corresponding structures as those become non-private
to gntdev now.
Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r-- | drivers/xen/gntdev.c | 134 |
1 files changed, 43 insertions, 91 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 173332f439d8..e03f50052f3e 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright (c) 2006-2007, D G Murray. | 7 | * Copyright (c) 2006-2007, D G Murray. |
8 | * (c) 2009 Gerd Hoffmann <kraxel@redhat.com> | 8 | * (c) 2009 Gerd Hoffmann <kraxel@redhat.com> |
9 | * (c) 2018 Oleksandr Andrushchenko, EPAM Systems Inc. | ||
9 | * | 10 | * |
10 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
@@ -26,10 +27,6 @@ | |||
26 | #include <linux/init.h> | 27 | #include <linux/init.h> |
27 | #include <linux/miscdevice.h> | 28 | #include <linux/miscdevice.h> |
28 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
29 | #include <linux/mm.h> | ||
30 | #include <linux/mman.h> | ||
31 | #include <linux/mmu_notifier.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
34 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
35 | #include <linux/sched/mm.h> | 32 | #include <linux/sched/mm.h> |
@@ -50,6 +47,8 @@ | |||
50 | #include <asm/xen/hypervisor.h> | 47 | #include <asm/xen/hypervisor.h> |
51 | #include <asm/xen/hypercall.h> | 48 | #include <asm/xen/hypercall.h> |
52 | 49 | ||
50 | #include "gntdev-common.h" | ||
51 | |||
53 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
54 | MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, " | 53 | MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, " |
55 | "Gerd Hoffmann <kraxel@redhat.com>"); | 54 | "Gerd Hoffmann <kraxel@redhat.com>"); |
@@ -65,73 +64,23 @@ static atomic_t pages_mapped = ATOMIC_INIT(0); | |||
65 | static int use_ptemod; | 64 | static int use_ptemod; |
66 | #define populate_freeable_maps use_ptemod | 65 | #define populate_freeable_maps use_ptemod |
67 | 66 | ||
68 | struct gntdev_priv { | 67 | static int unmap_grant_pages(struct gntdev_grant_map *map, |
69 | /* maps with visible offsets in the file descriptor */ | 68 | int offset, int pages); |
70 | struct list_head maps; | ||
71 | /* maps that are not visible; will be freed on munmap. | ||
72 | * Only populated if populate_freeable_maps == 1 */ | ||
73 | struct list_head freeable_maps; | ||
74 | /* lock protects maps and freeable_maps */ | ||
75 | struct mutex lock; | ||
76 | struct mm_struct *mm; | ||
77 | struct mmu_notifier mn; | ||
78 | |||
79 | #ifdef CONFIG_XEN_GRANT_DMA_ALLOC | ||
80 | /* Device for which DMA memory is allocated. */ | ||
81 | struct device *dma_dev; | ||
82 | #endif | ||
83 | }; | ||
84 | |||
85 | struct unmap_notify { | ||
86 | int flags; | ||
87 | /* Address relative to the start of the grant_map */ | ||
88 | int addr; | ||
89 | int event; | ||
90 | }; | ||
91 | |||
92 | struct grant_map { | ||
93 | struct list_head next; | ||
94 | struct vm_area_struct *vma; | ||
95 | int index; | ||
96 | int count; | ||
97 | int flags; | ||
98 | refcount_t users; | ||
99 | struct unmap_notify notify; | ||
100 | struct ioctl_gntdev_grant_ref *grants; | ||
101 | struct gnttab_map_grant_ref *map_ops; | ||
102 | struct gnttab_unmap_grant_ref *unmap_ops; | ||
103 | struct gnttab_map_grant_ref *kmap_ops; | ||
104 | struct gnttab_unmap_grant_ref *kunmap_ops; | ||
105 | struct page **pages; | ||
106 | unsigned long pages_vm_start; | ||
107 | |||
108 | #ifdef CONFIG_XEN_GRANT_DMA_ALLOC | ||
109 | /* | ||
110 | * If dmabuf_vaddr is not NULL then this mapping is backed by DMA | ||
111 | * capable memory. | ||
112 | */ | ||
113 | |||
114 | struct device *dma_dev; | ||
115 | /* Flags used to create this DMA buffer: GNTDEV_DMA_FLAG_XXX. */ | ||
116 | int dma_flags; | ||
117 | void *dma_vaddr; | ||
118 | dma_addr_t dma_bus_addr; | ||
119 | /* Needed to avoid allocation in gnttab_dma_free_pages(). */ | ||
120 | xen_pfn_t *frames; | ||
121 | #endif | ||
122 | }; | ||
123 | |||
124 | static int unmap_grant_pages(struct grant_map *map, int offset, int pages); | ||
125 | 69 | ||
126 | static struct miscdevice gntdev_miscdev; | 70 | static struct miscdevice gntdev_miscdev; |
127 | 71 | ||
128 | /* ------------------------------------------------------------------ */ | 72 | /* ------------------------------------------------------------------ */ |
129 | 73 | ||
74 | bool gntdev_account_mapped_pages(int count) | ||
75 | { | ||
76 | return atomic_add_return(count, &pages_mapped) > limit; | ||
77 | } | ||
78 | |||
130 | static void gntdev_print_maps(struct gntdev_priv *priv, | 79 | static void gntdev_print_maps(struct gntdev_priv *priv, |
131 | char *text, int text_index) | 80 | char *text, int text_index) |
132 | { | 81 | { |
133 | #ifdef DEBUG | 82 | #ifdef DEBUG |
134 | struct grant_map *map; | 83 | struct gntdev_grant_map *map; |
135 | 84 | ||
136 | pr_debug("%s: maps list (priv %p)\n", __func__, priv); | 85 | pr_debug("%s: maps list (priv %p)\n", __func__, priv); |
137 | list_for_each_entry(map, &priv->maps, next) | 86 | list_for_each_entry(map, &priv->maps, next) |
@@ -141,7 +90,7 @@ static void gntdev_print_maps(struct gntdev_priv *priv, | |||
141 | #endif | 90 | #endif |
142 | } | 91 | } |
143 | 92 | ||
144 | static void gntdev_free_map(struct grant_map *map) | 93 | static void gntdev_free_map(struct gntdev_grant_map *map) |
145 | { | 94 | { |
146 | if (map == NULL) | 95 | if (map == NULL) |
147 | return; | 96 | return; |
@@ -176,13 +125,13 @@ static void gntdev_free_map(struct grant_map *map) | |||
176 | kfree(map); | 125 | kfree(map); |
177 | } | 126 | } |
178 | 127 | ||
179 | static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, | 128 | struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, |
180 | int dma_flags) | 129 | int dma_flags) |
181 | { | 130 | { |
182 | struct grant_map *add; | 131 | struct gntdev_grant_map *add; |
183 | int i; | 132 | int i; |
184 | 133 | ||
185 | add = kzalloc(sizeof(struct grant_map), GFP_KERNEL); | 134 | add = kzalloc(sizeof(*add), GFP_KERNEL); |
186 | if (NULL == add) | 135 | if (NULL == add) |
187 | return NULL; | 136 | return NULL; |
188 | 137 | ||
@@ -252,9 +201,9 @@ err: | |||
252 | return NULL; | 201 | return NULL; |
253 | } | 202 | } |
254 | 203 | ||
255 | static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add) | 204 | void gntdev_add_map(struct gntdev_priv *priv, struct gntdev_grant_map *add) |
256 | { | 205 | { |
257 | struct grant_map *map; | 206 | struct gntdev_grant_map *map; |
258 | 207 | ||
259 | list_for_each_entry(map, &priv->maps, next) { | 208 | list_for_each_entry(map, &priv->maps, next) { |
260 | if (add->index + add->count < map->index) { | 209 | if (add->index + add->count < map->index) { |
@@ -269,10 +218,10 @@ done: | |||
269 | gntdev_print_maps(priv, "[new]", add->index); | 218 | gntdev_print_maps(priv, "[new]", add->index); |
270 | } | 219 | } |
271 | 220 | ||
272 | static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, | 221 | static struct gntdev_grant_map *gntdev_find_map_index(struct gntdev_priv *priv, |
273 | int index, int count) | 222 | int index, int count) |
274 | { | 223 | { |
275 | struct grant_map *map; | 224 | struct gntdev_grant_map *map; |
276 | 225 | ||
277 | list_for_each_entry(map, &priv->maps, next) { | 226 | list_for_each_entry(map, &priv->maps, next) { |
278 | if (map->index != index) | 227 | if (map->index != index) |
@@ -284,7 +233,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, | |||
284 | return NULL; | 233 | return NULL; |
285 | } | 234 | } |
286 | 235 | ||
287 | static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) | 236 | void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map) |
288 | { | 237 | { |
289 | if (!map) | 238 | if (!map) |
290 | return; | 239 | return; |
@@ -315,7 +264,7 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) | |||
315 | static int find_grant_ptes(pte_t *pte, pgtable_t token, | 264 | static int find_grant_ptes(pte_t *pte, pgtable_t token, |
316 | unsigned long addr, void *data) | 265 | unsigned long addr, void *data) |
317 | { | 266 | { |
318 | struct grant_map *map = data; | 267 | struct gntdev_grant_map *map = data; |
319 | unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; | 268 | unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; |
320 | int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte; | 269 | int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte; |
321 | u64 pte_maddr; | 270 | u64 pte_maddr; |
@@ -348,7 +297,7 @@ static int set_grant_ptes_as_special(pte_t *pte, pgtable_t token, | |||
348 | } | 297 | } |
349 | #endif | 298 | #endif |
350 | 299 | ||
351 | static int map_grant_pages(struct grant_map *map) | 300 | int gntdev_map_grant_pages(struct gntdev_grant_map *map) |
352 | { | 301 | { |
353 | int i, err = 0; | 302 | int i, err = 0; |
354 | 303 | ||
@@ -413,7 +362,8 @@ static int map_grant_pages(struct grant_map *map) | |||
413 | return err; | 362 | return err; |
414 | } | 363 | } |
415 | 364 | ||
416 | static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) | 365 | static int __unmap_grant_pages(struct gntdev_grant_map *map, int offset, |
366 | int pages) | ||
417 | { | 367 | { |
418 | int i, err = 0; | 368 | int i, err = 0; |
419 | struct gntab_unmap_queue_data unmap_data; | 369 | struct gntab_unmap_queue_data unmap_data; |
@@ -448,7 +398,8 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
448 | return err; | 398 | return err; |
449 | } | 399 | } |
450 | 400 | ||
451 | static int unmap_grant_pages(struct grant_map *map, int offset, int pages) | 401 | static int unmap_grant_pages(struct gntdev_grant_map *map, int offset, |
402 | int pages) | ||
452 | { | 403 | { |
453 | int range, err = 0; | 404 | int range, err = 0; |
454 | 405 | ||
@@ -480,7 +431,7 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
480 | 431 | ||
481 | static void gntdev_vma_open(struct vm_area_struct *vma) | 432 | static void gntdev_vma_open(struct vm_area_struct *vma) |
482 | { | 433 | { |
483 | struct grant_map *map = vma->vm_private_data; | 434 | struct gntdev_grant_map *map = vma->vm_private_data; |
484 | 435 | ||
485 | pr_debug("gntdev_vma_open %p\n", vma); | 436 | pr_debug("gntdev_vma_open %p\n", vma); |
486 | refcount_inc(&map->users); | 437 | refcount_inc(&map->users); |
@@ -488,7 +439,7 @@ static void gntdev_vma_open(struct vm_area_struct *vma) | |||
488 | 439 | ||
489 | static void gntdev_vma_close(struct vm_area_struct *vma) | 440 | static void gntdev_vma_close(struct vm_area_struct *vma) |
490 | { | 441 | { |
491 | struct grant_map *map = vma->vm_private_data; | 442 | struct gntdev_grant_map *map = vma->vm_private_data; |
492 | struct file *file = vma->vm_file; | 443 | struct file *file = vma->vm_file; |
493 | struct gntdev_priv *priv = file->private_data; | 444 | struct gntdev_priv *priv = file->private_data; |
494 | 445 | ||
@@ -512,7 +463,7 @@ static void gntdev_vma_close(struct vm_area_struct *vma) | |||
512 | static struct page *gntdev_vma_find_special_page(struct vm_area_struct *vma, | 463 | static struct page *gntdev_vma_find_special_page(struct vm_area_struct *vma, |
513 | unsigned long addr) | 464 | unsigned long addr) |
514 | { | 465 | { |
515 | struct grant_map *map = vma->vm_private_data; | 466 | struct gntdev_grant_map *map = vma->vm_private_data; |
516 | 467 | ||
517 | return map->pages[(addr - map->pages_vm_start) >> PAGE_SHIFT]; | 468 | return map->pages[(addr - map->pages_vm_start) >> PAGE_SHIFT]; |
518 | } | 469 | } |
@@ -525,7 +476,7 @@ static const struct vm_operations_struct gntdev_vmops = { | |||
525 | 476 | ||
526 | /* ------------------------------------------------------------------ */ | 477 | /* ------------------------------------------------------------------ */ |
527 | 478 | ||
528 | static void unmap_if_in_range(struct grant_map *map, | 479 | static void unmap_if_in_range(struct gntdev_grant_map *map, |
529 | unsigned long start, unsigned long end) | 480 | unsigned long start, unsigned long end) |
530 | { | 481 | { |
531 | unsigned long mstart, mend; | 482 | unsigned long mstart, mend; |
@@ -554,7 +505,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn, | |||
554 | unsigned long start, unsigned long end) | 505 | unsigned long start, unsigned long end) |
555 | { | 506 | { |
556 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); | 507 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); |
557 | struct grant_map *map; | 508 | struct gntdev_grant_map *map; |
558 | 509 | ||
559 | mutex_lock(&priv->lock); | 510 | mutex_lock(&priv->lock); |
560 | list_for_each_entry(map, &priv->maps, next) { | 511 | list_for_each_entry(map, &priv->maps, next) { |
@@ -570,7 +521,7 @@ static void mn_release(struct mmu_notifier *mn, | |||
570 | struct mm_struct *mm) | 521 | struct mm_struct *mm) |
571 | { | 522 | { |
572 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); | 523 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); |
573 | struct grant_map *map; | 524 | struct gntdev_grant_map *map; |
574 | int err; | 525 | int err; |
575 | 526 | ||
576 | mutex_lock(&priv->lock); | 527 | mutex_lock(&priv->lock); |
@@ -651,13 +602,14 @@ static int gntdev_open(struct inode *inode, struct file *flip) | |||
651 | static int gntdev_release(struct inode *inode, struct file *flip) | 602 | static int gntdev_release(struct inode *inode, struct file *flip) |
652 | { | 603 | { |
653 | struct gntdev_priv *priv = flip->private_data; | 604 | struct gntdev_priv *priv = flip->private_data; |
654 | struct grant_map *map; | 605 | struct gntdev_grant_map *map; |
655 | 606 | ||
656 | pr_debug("priv %p\n", priv); | 607 | pr_debug("priv %p\n", priv); |
657 | 608 | ||
658 | mutex_lock(&priv->lock); | 609 | mutex_lock(&priv->lock); |
659 | while (!list_empty(&priv->maps)) { | 610 | while (!list_empty(&priv->maps)) { |
660 | map = list_entry(priv->maps.next, struct grant_map, next); | 611 | map = list_entry(priv->maps.next, |
612 | struct gntdev_grant_map, next); | ||
661 | list_del(&map->next); | 613 | list_del(&map->next); |
662 | gntdev_put_map(NULL /* already removed */, map); | 614 | gntdev_put_map(NULL /* already removed */, map); |
663 | } | 615 | } |
@@ -674,7 +626,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, | |||
674 | struct ioctl_gntdev_map_grant_ref __user *u) | 626 | struct ioctl_gntdev_map_grant_ref __user *u) |
675 | { | 627 | { |
676 | struct ioctl_gntdev_map_grant_ref op; | 628 | struct ioctl_gntdev_map_grant_ref op; |
677 | struct grant_map *map; | 629 | struct gntdev_grant_map *map; |
678 | int err; | 630 | int err; |
679 | 631 | ||
680 | if (copy_from_user(&op, u, sizeof(op)) != 0) | 632 | if (copy_from_user(&op, u, sizeof(op)) != 0) |
@@ -688,7 +640,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, | |||
688 | if (!map) | 640 | if (!map) |
689 | return err; | 641 | return err; |
690 | 642 | ||
691 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { | 643 | if (unlikely(gntdev_account_mapped_pages(op.count))) { |
692 | pr_debug("can't map: over limit\n"); | 644 | pr_debug("can't map: over limit\n"); |
693 | gntdev_put_map(NULL, map); | 645 | gntdev_put_map(NULL, map); |
694 | return err; | 646 | return err; |
@@ -715,7 +667,7 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, | |||
715 | struct ioctl_gntdev_unmap_grant_ref __user *u) | 667 | struct ioctl_gntdev_unmap_grant_ref __user *u) |
716 | { | 668 | { |
717 | struct ioctl_gntdev_unmap_grant_ref op; | 669 | struct ioctl_gntdev_unmap_grant_ref op; |
718 | struct grant_map *map; | 670 | struct gntdev_grant_map *map; |
719 | int err = -ENOENT; | 671 | int err = -ENOENT; |
720 | 672 | ||
721 | if (copy_from_user(&op, u, sizeof(op)) != 0) | 673 | if (copy_from_user(&op, u, sizeof(op)) != 0) |
@@ -741,7 +693,7 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, | |||
741 | { | 693 | { |
742 | struct ioctl_gntdev_get_offset_for_vaddr op; | 694 | struct ioctl_gntdev_get_offset_for_vaddr op; |
743 | struct vm_area_struct *vma; | 695 | struct vm_area_struct *vma; |
744 | struct grant_map *map; | 696 | struct gntdev_grant_map *map; |
745 | int rv = -EINVAL; | 697 | int rv = -EINVAL; |
746 | 698 | ||
747 | if (copy_from_user(&op, u, sizeof(op)) != 0) | 699 | if (copy_from_user(&op, u, sizeof(op)) != 0) |
@@ -772,7 +724,7 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, | |||
772 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) | 724 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) |
773 | { | 725 | { |
774 | struct ioctl_gntdev_unmap_notify op; | 726 | struct ioctl_gntdev_unmap_notify op; |
775 | struct grant_map *map; | 727 | struct gntdev_grant_map *map; |
776 | int rc; | 728 | int rc; |
777 | int out_flags; | 729 | int out_flags; |
778 | unsigned int out_event; | 730 | unsigned int out_event; |
@@ -1070,7 +1022,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) | |||
1070 | struct gntdev_priv *priv = flip->private_data; | 1022 | struct gntdev_priv *priv = flip->private_data; |
1071 | int index = vma->vm_pgoff; | 1023 | int index = vma->vm_pgoff; |
1072 | int count = vma_pages(vma); | 1024 | int count = vma_pages(vma); |
1073 | struct grant_map *map; | 1025 | struct gntdev_grant_map *map; |
1074 | int i, err = -EINVAL; | 1026 | int i, err = -EINVAL; |
1075 | 1027 | ||
1076 | if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) | 1028 | if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) |
@@ -1127,7 +1079,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) | |||
1127 | } | 1079 | } |
1128 | } | 1080 | } |
1129 | 1081 | ||
1130 | err = map_grant_pages(map); | 1082 | err = gntdev_map_grant_pages(map); |
1131 | if (err) | 1083 | if (err) |
1132 | goto out_put_map; | 1084 | goto out_put_map; |
1133 | 1085 | ||