diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2022-05-24 21:16:30 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2022-05-24 21:16:30 -0400 |
| commit | 2c076a01e5bd0949032ef81cd0e2d37bdecafba5 (patch) | |
| tree | 12cc1d66b55a6a72ecdd40a416a86b117f04641a /drivers/video/tegra/nvmap/nvmap_alloc.c | |
| parent | 70c252977fc080c829b195fece6f46f73586f1e4 (diff) | |
gpu-paging: Functions to support initial working versionrtss22-aegpu-paging
- Buffer deallocation (+IOCTL)
- Buffer reallocation
- Private dmabuf user list and accessor
Diffstat (limited to 'drivers/video/tegra/nvmap/nvmap_alloc.c')
| -rw-r--r-- | drivers/video/tegra/nvmap/nvmap_alloc.c | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_alloc.c b/drivers/video/tegra/nvmap/nvmap_alloc.c index 74c9e4b90..ea648b8bf 100644 --- a/drivers/video/tegra/nvmap/nvmap_alloc.c +++ b/drivers/video/tegra/nvmap/nvmap_alloc.c | |||
| @@ -775,6 +775,7 @@ int nvmap_alloc_handle(struct nvmap_client *client, | |||
| 775 | nvmap_stats_read(NS_TOTAL), | 775 | nvmap_stats_read(NS_TOTAL), |
| 776 | nvmap_stats_read(NS_ALLOC)); | 776 | nvmap_stats_read(NS_ALLOC)); |
| 777 | h->userflags = flags; | 777 | h->userflags = flags; |
| 778 | h->userheap_mask = heap_mask; | ||
| 778 | nr_page = ((h->size + PAGE_SIZE - 1) >> PAGE_SHIFT); | 779 | nr_page = ((h->size + PAGE_SIZE - 1) >> PAGE_SHIFT); |
| 779 | /* Force mapping to uncached for VPR memory. */ | 780 | /* Force mapping to uncached for VPR memory. */ |
| 780 | if (heap_mask & (NVMAP_HEAP_CARVEOUT_VPR | ~nvmap_dev->cpu_access_mask)) | 781 | if (heap_mask & (NVMAP_HEAP_CARVEOUT_VPR | ~nvmap_dev->cpu_access_mask)) |
| @@ -911,20 +912,9 @@ int nvmap_alloc_handle_from_va(struct nvmap_client *client, | |||
| 911 | return err; | 912 | return err; |
| 912 | } | 913 | } |
| 913 | 914 | ||
| 914 | void _nvmap_handle_free(struct nvmap_handle *h) | 915 | void __nvmap_handle_free(struct nvmap_handle *h) |
| 915 | { | 916 | { |
| 916 | unsigned int i, nr_page, page_index = 0; | 917 | unsigned int i, nr_page, page_index = 0; |
| 917 | struct nvmap_handle_dmabuf_priv *curr, *next; | ||
| 918 | |||
| 919 | list_for_each_entry_safe(curr, next, &h->dmabuf_priv, list) { | ||
| 920 | curr->priv_release(curr->priv); | ||
| 921 | list_del(&curr->list); | ||
| 922 | kzfree(curr); | ||
| 923 | } | ||
| 924 | |||
| 925 | if (nvmap_handle_remove(nvmap_dev, h) != 0) | ||
| 926 | return; | ||
| 927 | |||
| 928 | if (!h->alloc) | 918 | if (!h->alloc) |
| 929 | goto out; | 919 | goto out; |
| 930 | 920 | ||
| @@ -980,8 +970,24 @@ void _nvmap_handle_free(struct nvmap_handle *h) | |||
| 980 | } | 970 | } |
| 981 | 971 | ||
| 982 | nvmap_altfree(h->pgalloc.pages, nr_page * sizeof(struct page *)); | 972 | nvmap_altfree(h->pgalloc.pages, nr_page * sizeof(struct page *)); |
| 983 | |||
| 984 | out: | 973 | out: |
| 974 | h->alloc = false; | ||
| 975 | } | ||
| 976 | |||
| 977 | void _nvmap_handle_free(struct nvmap_handle *h) | ||
| 978 | { | ||
| 979 | struct nvmap_handle_dmabuf_priv *curr, *next; | ||
| 980 | |||
| 981 | list_for_each_entry_safe(curr, next, &h->dmabuf_priv, list) { | ||
| 982 | curr->priv_release(curr->priv); | ||
| 983 | list_del(&curr->list); | ||
| 984 | kzfree(curr); | ||
| 985 | } | ||
| 986 | |||
| 987 | if (nvmap_handle_remove(nvmap_dev, h) != 0) | ||
| 988 | return; | ||
| 989 | __nvmap_handle_free(h); | ||
| 990 | // Next two calls were originally in the `out` clause | ||
| 985 | NVMAP_TAG_TRACE(trace_nvmap_destroy_handle, | 991 | NVMAP_TAG_TRACE(trace_nvmap_destroy_handle, |
| 986 | NULL, get_current()->pid, 0, NVMAP_TP_ARGS_H(h)); | 992 | NULL, get_current()->pid, 0, NVMAP_TP_ARGS_H(h)); |
| 987 | kfree(h); | 993 | kfree(h); |
| @@ -1041,3 +1047,57 @@ void nvmap_free_handle_fd(struct nvmap_client *client, | |||
| 1041 | nvmap_handle_put(handle); | 1047 | nvmap_handle_put(handle); |
| 1042 | } | 1048 | } |
| 1043 | } | 1049 | } |
| 1050 | |||
| 1051 | // Frees backing pages. Handle remains valid. | ||
| 1052 | void nvmap_dealloc_fd(struct nvmap_client *client, int fd) | ||
| 1053 | { | ||
| 1054 | struct nvmap_handle *handle = nvmap_handle_get_from_fd(fd); | ||
| 1055 | if (handle) | ||
| 1056 | __nvmap_handle_free(handle); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | // For deallocations from elsewhere in the kernel. | ||
| 1060 | // (Userspace should use NVMAP_IOC_DEALLOC ioctl.) | ||
| 1061 | int nvmap_dealloc_dmabuf(struct dma_buf *dmabuf) { | ||
| 1062 | struct nvmap_handle_info *info; | ||
| 1063 | |||
| 1064 | if (!dmabuf_is_nvmap(dmabuf)) | ||
| 1065 | return -EINVAL; | ||
| 1066 | info = dmabuf->priv; | ||
| 1067 | // Fail if mapped into kernelspace | ||
| 1068 | // (Unclear if this is necessary, but no handles have been observed with this | ||
| 1069 | // set, and so testing has not been possible.) | ||
| 1070 | if (atomic_read(&info->handle->kmap_count)) | ||
| 1071 | goto out_busy; | ||
| 1072 | // Buffer cannot currently be mapped into userspace (via mmap) | ||
| 1073 | if (atomic_read(&info->handle->umap_count)) | ||
| 1074 | goto out_busy; | ||
| 1075 | // Other devices should not still have this pinned into DMA memory | ||
| 1076 | if (atomic_read(&info->handle->pin)) | ||
| 1077 | goto out_busy; | ||
| 1078 | __nvmap_handle_free(info->handle); | ||
| 1079 | return 0; | ||
| 1080 | out_busy: | ||
| 1081 | printk(KERN_WARNING "nvmap: Unmap requested on FD that is currently in-use! (%d h->pin, %d h->kmap_count, %d h->umap_count)\n", | ||
| 1082 | atomic_read(&info->handle->pin), | ||
| 1083 | atomic_read(&info->handle->kmap_count), | ||
| 1084 | atomic_read(&info->handle->umap_count)); | ||
| 1085 | return -EBUSY; | ||
| 1086 | } | ||
| 1087 | EXPORT_SYMBOL(nvmap_dealloc_dmabuf); | ||
| 1088 | |||
| 1089 | // For reallocations from elsewhere in the kernel. | ||
| 1090 | // (Userspace should use NVMAP_IOC_ALLOC ioctl.) | ||
| 1091 | int nvmap_realloc_dmabuf(struct dma_buf *dmabuf) { | ||
| 1092 | struct nvmap_handle_info *info; | ||
| 1093 | struct nvmap_handle *h; | ||
| 1094 | |||
| 1095 | if (!dmabuf_is_nvmap(dmabuf)) | ||
| 1096 | return -EINVAL; | ||
| 1097 | info = dmabuf->priv; | ||
| 1098 | h = info->handle; | ||
| 1099 | return nvmap_alloc_handle(h->owner, h, h->userheap_mask, | ||
| 1100 | h->align, 0, h->userflags, | ||
| 1101 | NVMAP_IVM_INVALID_PEER); | ||
| 1102 | } | ||
| 1103 | EXPORT_SYMBOL(nvmap_realloc_dmabuf); | ||
