summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-07-31 15:32:07 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-10-10 11:01:04 -0400
commit3c37701377459fbea2b460e1b9c65a863dfb04b2 (patch)
tree60a57a260dc8bcbd81089af8e9e966074e3bc881 /drivers/gpu/nvgpu/gk20a/mm_gk20a.c
parentb61306795b53647e8d1d4279417df1e1fe0f4b86 (diff)
gpu: nvgpu: Split VIDMEM support from mm_gk20a.c
Split VIDMEM support into its own code files organized as such: common/mm/vidmem.c - Base vidmem support common/linux/vidmem.c - Linux specific user-space interaction include/nvgpu/vidmem.h - Vidmem API definitions Also use the config to enable/disable VIDMEM support in the makefile and remove as many CONFIG_GK20A_VIDMEM preprocessor checks as possible from the source code. And lastly update a while-loop that iterated over an SGT to use the new for_each construct for iterating over SGTs. Currently this organization is not perfectly adhered to. More patches will fix that. JIRA NVGPU-30 JIRA NVGPU-138 Change-Id: Ic0f4d2cf38b65849c7dc350a69b175421477069c Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1540705 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.c541
1 files changed, 1 insertions, 540 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
index 795f7bda..c6ea2587 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
@@ -27,7 +27,6 @@
27#include <linux/dma-mapping.h> 27#include <linux/dma-mapping.h>
28#include <linux/dma-attrs.h> 28#include <linux/dma-attrs.h>
29#include <linux/lcm.h> 29#include <linux/lcm.h>
30#include <linux/platform/tegra/tegra_fd.h>
31#include <uapi/linux/nvgpu.h> 30#include <uapi/linux/nvgpu.h>
32#include <trace/events/gk20a.h> 31#include <trace/events/gk20a.h>
33 32
@@ -46,6 +45,7 @@
46#include <nvgpu/bug.h> 45#include <nvgpu/bug.h>
47#include <nvgpu/log2.h> 46#include <nvgpu/log2.h>
48#include <nvgpu/enabled.h> 47#include <nvgpu/enabled.h>
48#include <nvgpu/vidmem.h>
49 49
50#include <nvgpu/linux/dma.h> 50#include <nvgpu/linux/dma.h>
51 51
@@ -71,35 +71,6 @@
71 */ 71 */
72#include "common/linux/vm_priv.h" 72#include "common/linux/vm_priv.h"
73 73
74#if defined(CONFIG_GK20A_VIDMEM)
75static void gk20a_vidmem_clear_mem_worker(struct work_struct *work);
76#endif
77
78void set_vidmem_page_alloc(struct scatterlist *sgl, u64 addr)
79{
80 /* set bit 0 to indicate vidmem allocation */
81 sg_dma_address(sgl) = (addr | 1ULL);
82}
83
84bool is_vidmem_page_alloc(u64 addr)
85{
86 return !!(addr & 1ULL);
87}
88
89struct nvgpu_page_alloc *get_vidmem_page_alloc(struct scatterlist *sgl)
90{
91 u64 addr;
92
93 addr = sg_dma_address(sgl);
94
95 if (is_vidmem_page_alloc(addr))
96 addr = addr & ~1ULL;
97 else
98 WARN_ON(1);
99
100 return (struct nvgpu_page_alloc *)(uintptr_t)addr;
101}
102
103/* 74/*
104 * GPU mapping life cycle 75 * GPU mapping life cycle
105 * ====================== 76 * ======================
@@ -137,8 +108,6 @@ static int __must_check gk20a_init_hwpm(struct mm_gk20a *mm);
137static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm); 108static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm);
138static int __must_check gk20a_init_ce_vm(struct mm_gk20a *mm); 109static int __must_check gk20a_init_ce_vm(struct mm_gk20a *mm);
139 110
140static struct gk20a *gk20a_vidmem_buf_owner(struct dma_buf *dmabuf);
141
142struct gk20a_dmabuf_priv { 111struct gk20a_dmabuf_priv {
143 struct nvgpu_mutex lock; 112 struct nvgpu_mutex lock;
144 113
@@ -157,14 +126,6 @@ struct gk20a_dmabuf_priv {
157 u64 buffer_id; 126 u64 buffer_id;
158}; 127};
159 128
160struct gk20a_vidmem_buf {
161 struct gk20a *g;
162 struct nvgpu_mem *mem;
163 struct dma_buf *dmabuf;
164 void *dmabuf_priv;
165 void (*dmabuf_priv_delete)(void *);
166};
167
168static int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator, 129static int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator,
169 u32 *offset, u32 len) 130 u32 *offset, u32 len)
170{ 131{
@@ -331,9 +292,6 @@ int gk20a_alloc_comptags(struct gk20a *g,
331 return 0; 292 return 0;
332} 293}
333 294
334
335
336
337static int gk20a_init_mm_reset_enable_hw(struct gk20a *g) 295static int gk20a_init_mm_reset_enable_hw(struct gk20a *g)
338{ 296{
339 gk20a_dbg_fn(""); 297 gk20a_dbg_fn("");
@@ -359,14 +317,6 @@ static int gk20a_init_mm_reset_enable_hw(struct gk20a *g)
359 return 0; 317 return 0;
360} 318}
361 319
362static void gk20a_vidmem_destroy(struct gk20a *g)
363{
364#if defined(CONFIG_GK20A_VIDMEM)
365 if (nvgpu_alloc_initialized(&g->mm.vidmem.allocator))
366 nvgpu_alloc_destroy(&g->mm.vidmem.allocator);
367#endif
368}
369
370static void gk20a_remove_mm_ce_support(struct mm_gk20a *mm) 320static void gk20a_remove_mm_ce_support(struct mm_gk20a *mm)
371{ 321{
372 struct gk20a *g = gk20a_from_mm(mm); 322 struct gk20a *g = gk20a_from_mm(mm);
@@ -409,143 +359,6 @@ static int gk20a_alloc_sysmem_flush(struct gk20a *g)
409 return nvgpu_dma_alloc_sys(g, SZ_4K, &g->mm.sysmem_flush); 359 return nvgpu_dma_alloc_sys(g, SZ_4K, &g->mm.sysmem_flush);
410} 360}
411 361
412#if defined(CONFIG_GK20A_VIDMEM)
413static int gk20a_vidmem_clear_all(struct gk20a *g)
414{
415 struct mm_gk20a *mm = &g->mm;
416 struct gk20a_fence *gk20a_fence_out = NULL;
417 u64 region2_base = 0;
418 int err = 0;
419
420 if (mm->vidmem.ce_ctx_id == (u32)~0)
421 return -EINVAL;
422
423 err = gk20a_ce_execute_ops(g,
424 mm->vidmem.ce_ctx_id,
425 0,
426 mm->vidmem.base,
427 mm->vidmem.bootstrap_base - mm->vidmem.base,
428 0x00000000,
429 NVGPU_CE_DST_LOCATION_LOCAL_FB,
430 NVGPU_CE_MEMSET,
431 NULL,
432 0,
433 NULL);
434 if (err) {
435 nvgpu_err(g,
436 "Failed to clear vidmem region 1 : %d", err);
437 return err;
438 }
439
440 region2_base = mm->vidmem.bootstrap_base + mm->vidmem.bootstrap_size;
441
442 err = gk20a_ce_execute_ops(g,
443 mm->vidmem.ce_ctx_id,
444 0,
445 region2_base,
446 mm->vidmem.size - region2_base,
447 0x00000000,
448 NVGPU_CE_DST_LOCATION_LOCAL_FB,
449 NVGPU_CE_MEMSET,
450 NULL,
451 0,
452 &gk20a_fence_out);
453 if (err) {
454 nvgpu_err(g,
455 "Failed to clear vidmem region 2 : %d", err);
456 return err;
457 }
458
459 if (gk20a_fence_out) {
460 struct nvgpu_timeout timeout;
461
462 nvgpu_timeout_init(g, &timeout,
463 gk20a_get_gr_idle_timeout(g),
464 NVGPU_TIMER_CPU_TIMER);
465
466 do {
467 err = gk20a_fence_wait(g, gk20a_fence_out,
468 gk20a_get_gr_idle_timeout(g));
469 } while (err == -ERESTARTSYS &&
470 !nvgpu_timeout_expired(&timeout));
471
472 gk20a_fence_put(gk20a_fence_out);
473 if (err) {
474 nvgpu_err(g,
475 "fence wait failed for CE execute ops");
476 return err;
477 }
478 }
479
480 mm->vidmem.cleared = true;
481
482 return 0;
483}
484#endif
485
486static int gk20a_init_vidmem(struct mm_gk20a *mm)
487{
488#if defined(CONFIG_GK20A_VIDMEM)
489 struct gk20a *g = mm->g;
490 size_t size = g->ops.mm.get_vidmem_size ?
491 g->ops.mm.get_vidmem_size(g) : 0;
492 u64 bootstrap_base, bootstrap_size, base;
493 u64 default_page_size = SZ_64K;
494 int err;
495
496 static struct nvgpu_alloc_carveout wpr_co =
497 NVGPU_CARVEOUT("wpr-region", 0, SZ_16M);
498
499 if (!size)
500 return 0;
501
502 wpr_co.base = size - SZ_256M;
503 bootstrap_base = wpr_co.base;
504 bootstrap_size = SZ_16M;
505 base = default_page_size;
506
507 /*
508 * Bootstrap allocator for use before the CE is initialized (CE
509 * initialization requires vidmem but we want to use the CE to zero
510 * out vidmem before allocating it...
511 */
512 err = nvgpu_page_allocator_init(g, &g->mm.vidmem.bootstrap_allocator,
513 "vidmem-bootstrap",
514 bootstrap_base, bootstrap_size,
515 SZ_4K, 0);
516
517 err = nvgpu_page_allocator_init(g, &g->mm.vidmem.allocator,
518 "vidmem",
519 base, size - base,
520 default_page_size,
521 GPU_ALLOC_4K_VIDMEM_PAGES);
522 if (err) {
523 nvgpu_err(g, "Failed to register vidmem for size %zu: %d",
524 size, err);
525 return err;
526 }
527
528 /* Reserve bootstrap region in vidmem allocator */
529 nvgpu_alloc_reserve_carveout(&g->mm.vidmem.allocator, &wpr_co);
530
531 mm->vidmem.base = base;
532 mm->vidmem.size = size - base;
533 mm->vidmem.bootstrap_base = bootstrap_base;
534 mm->vidmem.bootstrap_size = bootstrap_size;
535
536 nvgpu_mutex_init(&mm->vidmem.first_clear_mutex);
537
538 INIT_WORK(&mm->vidmem.clear_mem_worker, gk20a_vidmem_clear_mem_worker);
539 nvgpu_atomic64_set(&mm->vidmem.bytes_pending, 0);
540 nvgpu_init_list_node(&mm->vidmem.clear_list_head);
541 nvgpu_mutex_init(&mm->vidmem.clear_list_mutex);
542
543 gk20a_dbg_info("registered vidmem: %zu MB", size / SZ_1M);
544
545#endif
546 return 0;
547}
548
549int gk20a_init_mm_setup_sw(struct gk20a *g) 362int gk20a_init_mm_setup_sw(struct gk20a *g)
550{ 363{
551 struct mm_gk20a *mm = &g->mm; 364 struct mm_gk20a *mm = &g->mm;
@@ -904,358 +717,6 @@ int setup_buffer_kind_and_compression(struct vm_gk20a *vm,
904 return 0; 717 return 0;
905} 718}
906 719
907enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g,
908 struct dma_buf *dmabuf)
909{
910 struct gk20a *buf_owner = gk20a_vidmem_buf_owner(dmabuf);
911 bool unified_memory = nvgpu_is_enabled(g, NVGPU_MM_UNIFIED_MEMORY);
912
913 if (buf_owner == NULL) {
914 /* Not nvgpu-allocated, assume system memory */
915 return APERTURE_SYSMEM;
916 } else if (WARN_ON(buf_owner == g && unified_memory)) {
917 /* Looks like our video memory, but this gpu doesn't support
918 * it. Warn about a bug and bail out */
919 nvgpu_warn(g,
920 "dmabuf is our vidmem but we don't have local vidmem");
921 return APERTURE_INVALID;
922 } else if (buf_owner != g) {
923 /* Someone else's vidmem */
924 return APERTURE_INVALID;
925 } else {
926 /* Yay, buf_owner == g */
927 return APERTURE_VIDMEM;
928 }
929}
930
931#if defined(CONFIG_GK20A_VIDMEM)
932static struct sg_table *gk20a_vidbuf_map_dma_buf(
933 struct dma_buf_attachment *attach, enum dma_data_direction dir)
934{
935 struct gk20a_vidmem_buf *buf = attach->dmabuf->priv;
936
937 return buf->mem->priv.sgt;
938}
939
940static void gk20a_vidbuf_unmap_dma_buf(struct dma_buf_attachment *attach,
941 struct sg_table *sgt,
942 enum dma_data_direction dir)
943{
944}
945
946static void gk20a_vidbuf_release(struct dma_buf *dmabuf)
947{
948 struct gk20a_vidmem_buf *buf = dmabuf->priv;
949
950 gk20a_dbg_fn("");
951
952 if (buf->dmabuf_priv)
953 buf->dmabuf_priv_delete(buf->dmabuf_priv);
954
955 nvgpu_dma_free(buf->g, buf->mem);
956 nvgpu_kfree(buf->g, buf);
957}
958
959static void *gk20a_vidbuf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
960{
961 WARN_ON("Not supported");
962 return NULL;
963}
964
965static void *gk20a_vidbuf_kmap_atomic(struct dma_buf *dmabuf,
966 unsigned long page_num)
967{
968 WARN_ON("Not supported");
969 return NULL;
970}
971
972static int gk20a_vidbuf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
973{
974 return -EINVAL;
975}
976
977static int gk20a_vidbuf_set_private(struct dma_buf *dmabuf,
978 struct device *dev, void *priv, void (*delete)(void *priv))
979{
980 struct gk20a_vidmem_buf *buf = dmabuf->priv;
981
982 buf->dmabuf_priv = priv;
983 buf->dmabuf_priv_delete = delete;
984
985 return 0;
986}
987
988static void *gk20a_vidbuf_get_private(struct dma_buf *dmabuf,
989 struct device *dev)
990{
991 struct gk20a_vidmem_buf *buf = dmabuf->priv;
992
993 return buf->dmabuf_priv;
994}
995
996static const struct dma_buf_ops gk20a_vidbuf_ops = {
997 .map_dma_buf = gk20a_vidbuf_map_dma_buf,
998 .unmap_dma_buf = gk20a_vidbuf_unmap_dma_buf,
999 .release = gk20a_vidbuf_release,
1000 .kmap_atomic = gk20a_vidbuf_kmap_atomic,
1001 .kmap = gk20a_vidbuf_kmap,
1002 .mmap = gk20a_vidbuf_mmap,
1003 .set_drvdata = gk20a_vidbuf_set_private,
1004 .get_drvdata = gk20a_vidbuf_get_private,
1005};
1006
1007static struct dma_buf *gk20a_vidbuf_export(struct gk20a_vidmem_buf *buf)
1008{
1009 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
1010
1011 exp_info.priv = buf;
1012 exp_info.ops = &gk20a_vidbuf_ops;
1013 exp_info.size = buf->mem->size;
1014 exp_info.flags = O_RDWR;
1015
1016 return dma_buf_export(&exp_info);
1017}
1018#endif
1019
1020static struct gk20a *gk20a_vidmem_buf_owner(struct dma_buf *dmabuf)
1021{
1022#if defined(CONFIG_GK20A_VIDMEM)
1023 struct gk20a_vidmem_buf *buf = dmabuf->priv;
1024
1025 if (dmabuf->ops != &gk20a_vidbuf_ops)
1026 return NULL;
1027
1028 return buf->g;
1029#else
1030 return NULL;
1031#endif
1032}
1033
1034int gk20a_vidmem_buf_alloc(struct gk20a *g, size_t bytes)
1035{
1036#if defined(CONFIG_GK20A_VIDMEM)
1037 struct gk20a_vidmem_buf *buf;
1038 int err = 0, fd;
1039
1040 gk20a_dbg_fn("");
1041
1042 buf = nvgpu_kzalloc(g, sizeof(*buf));
1043 if (!buf)
1044 return -ENOMEM;
1045
1046 buf->g = g;
1047
1048 if (!g->mm.vidmem.cleared) {
1049 nvgpu_mutex_acquire(&g->mm.vidmem.first_clear_mutex);
1050 if (!g->mm.vidmem.cleared) {
1051 err = gk20a_vidmem_clear_all(g);
1052 if (err) {
1053 nvgpu_err(g,
1054 "failed to clear whole vidmem");
1055 goto err_kfree;
1056 }
1057 }
1058 nvgpu_mutex_release(&g->mm.vidmem.first_clear_mutex);
1059 }
1060
1061 buf->mem = nvgpu_kzalloc(g, sizeof(struct nvgpu_mem));
1062 if (!buf->mem)
1063 goto err_kfree;
1064
1065 buf->mem->mem_flags |= NVGPU_MEM_FLAG_USER_MEM;
1066
1067 err = nvgpu_dma_alloc_vid(g, bytes, buf->mem);
1068 if (err)
1069 goto err_memfree;
1070
1071 buf->dmabuf = gk20a_vidbuf_export(buf);
1072 if (IS_ERR(buf->dmabuf)) {
1073 err = PTR_ERR(buf->dmabuf);
1074 goto err_bfree;
1075 }
1076
1077 fd = tegra_alloc_fd(current->files, 1024, O_RDWR);
1078 if (fd < 0) {
1079 /* ->release frees what we have done */
1080 dma_buf_put(buf->dmabuf);
1081 return fd;
1082 }
1083
1084 /* fclose() on this drops one ref, freeing the dma buf */
1085 fd_install(fd, buf->dmabuf->file);
1086
1087 return fd;
1088
1089err_bfree:
1090 nvgpu_dma_free(g, buf->mem);
1091err_memfree:
1092 nvgpu_kfree(g, buf->mem);
1093err_kfree:
1094 nvgpu_kfree(g, buf);
1095 return err;
1096#else
1097 return -ENOSYS;
1098#endif
1099}
1100
1101int gk20a_vidmem_get_space(struct gk20a *g, u64 *space)
1102{
1103#if defined(CONFIG_GK20A_VIDMEM)
1104 struct nvgpu_allocator *allocator = &g->mm.vidmem.allocator;
1105
1106 gk20a_dbg_fn("");
1107
1108 if (!nvgpu_alloc_initialized(allocator))
1109 return -ENOSYS;
1110
1111 nvgpu_mutex_acquire(&g->mm.vidmem.clear_list_mutex);
1112 *space = nvgpu_alloc_space(allocator) +
1113 nvgpu_atomic64_read(&g->mm.vidmem.bytes_pending);
1114 nvgpu_mutex_release(&g->mm.vidmem.clear_list_mutex);
1115 return 0;
1116#else
1117 return -ENOSYS;
1118#endif
1119}
1120
1121int gk20a_vidbuf_access_memory(struct gk20a *g, struct dma_buf *dmabuf,
1122 void *buffer, u64 offset, u64 size, u32 cmd)
1123{
1124#if defined(CONFIG_GK20A_VIDMEM)
1125 struct gk20a_vidmem_buf *vidmem_buf;
1126 struct nvgpu_mem *mem;
1127 int err = 0;
1128
1129 if (gk20a_dmabuf_aperture(g, dmabuf) != APERTURE_VIDMEM)
1130 return -EINVAL;
1131
1132 vidmem_buf = dmabuf->priv;
1133 mem = vidmem_buf->mem;
1134
1135 switch (cmd) {
1136 case NVGPU_DBG_GPU_IOCTL_ACCESS_FB_MEMORY_CMD_READ:
1137 nvgpu_mem_rd_n(g, mem, offset, buffer, size);
1138 break;
1139
1140 case NVGPU_DBG_GPU_IOCTL_ACCESS_FB_MEMORY_CMD_WRITE:
1141 nvgpu_mem_wr_n(g, mem, offset, buffer, size);
1142 break;
1143
1144 default:
1145 err = -EINVAL;
1146 }
1147
1148 return err;
1149#else
1150 return -ENOSYS;
1151#endif
1152}
1153
1154#if defined(CONFIG_GK20A_VIDMEM)
1155static int gk20a_gmmu_clear_vidmem_mem(struct gk20a *g, struct nvgpu_mem *mem)
1156{
1157 struct gk20a_fence *gk20a_fence_out = NULL;
1158 struct gk20a_fence *gk20a_last_fence = NULL;
1159 struct nvgpu_page_alloc *alloc = NULL;
1160 struct nvgpu_sgt *sgt = NULL;
1161 void *sgl = NULL;
1162 int err = 0;
1163
1164 if (g->mm.vidmem.ce_ctx_id == (u32)~0)
1165 return -EINVAL;
1166
1167 alloc = get_vidmem_page_alloc(mem->priv.sgt->sgl);
1168
1169 sgt = &alloc->sgt;
1170 sgl = sgt->sgl;
1171 while (sgl) {
1172 if (gk20a_last_fence)
1173 gk20a_fence_put(gk20a_last_fence);
1174
1175 err = gk20a_ce_execute_ops(g,
1176 g->mm.vidmem.ce_ctx_id,
1177 0,
1178 nvgpu_sgt_get_phys(sgt, sgl),
1179 nvgpu_sgt_get_length(sgt, sgl),
1180 0x00000000,
1181 NVGPU_CE_DST_LOCATION_LOCAL_FB,
1182 NVGPU_CE_MEMSET,
1183 NULL,
1184 0,
1185 &gk20a_fence_out);
1186
1187 if (err) {
1188 nvgpu_err(g,
1189 "Failed gk20a_ce_execute_ops[%d]", err);
1190 return err;
1191 }
1192
1193 gk20a_last_fence = gk20a_fence_out;
1194 sgl = nvgpu_sgt_get_next(sgt, sgl);
1195 }
1196
1197 if (gk20a_last_fence) {
1198 struct nvgpu_timeout timeout;
1199
1200 nvgpu_timeout_init(g, &timeout,
1201 gk20a_get_gr_idle_timeout(g),
1202 NVGPU_TIMER_CPU_TIMER);
1203
1204 do {
1205 err = gk20a_fence_wait(g, gk20a_last_fence,
1206 gk20a_get_gr_idle_timeout(g));
1207 } while (err == -ERESTARTSYS &&
1208 !nvgpu_timeout_expired(&timeout));
1209
1210 gk20a_fence_put(gk20a_last_fence);
1211 if (err)
1212 nvgpu_err(g,
1213 "fence wait failed for CE execute ops");
1214 }
1215
1216 return err;
1217}
1218#endif
1219
1220#if defined(CONFIG_GK20A_VIDMEM)
1221static struct nvgpu_mem *get_pending_mem_desc(struct mm_gk20a *mm)
1222{
1223 struct nvgpu_mem *mem = NULL;
1224
1225 nvgpu_mutex_acquire(&mm->vidmem.clear_list_mutex);
1226 if (!nvgpu_list_empty(&mm->vidmem.clear_list_head)) {
1227 mem = nvgpu_list_first_entry(&mm->vidmem.clear_list_head,
1228 nvgpu_mem, clear_list_entry);
1229 nvgpu_list_del(&mem->clear_list_entry);
1230 }
1231 nvgpu_mutex_release(&mm->vidmem.clear_list_mutex);
1232
1233 return mem;
1234}
1235
1236static void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
1237{
1238 struct mm_gk20a *mm = container_of(work, struct mm_gk20a,
1239 vidmem.clear_mem_worker);
1240 struct gk20a *g = mm->g;
1241 struct nvgpu_mem *mem;
1242
1243 while ((mem = get_pending_mem_desc(mm)) != NULL) {
1244 gk20a_gmmu_clear_vidmem_mem(g, mem);
1245 nvgpu_free(mem->allocator,
1246 (u64)get_vidmem_page_alloc(mem->priv.sgt->sgl));
1247 nvgpu_free_sgtable(g, &mem->priv.sgt);
1248
1249 WARN_ON(nvgpu_atomic64_sub_return(mem->aligned_size,
1250 &g->mm.vidmem.bytes_pending) < 0);
1251 mem->size = 0;
1252 mem->aperture = APERTURE_INVALID;
1253
1254 nvgpu_kfree(g, mem);
1255 }
1256}
1257#endif
1258
1259dma_addr_t gk20a_mm_gpuva_to_iova_base(struct vm_gk20a *vm, u64 gpu_vaddr) 720dma_addr_t gk20a_mm_gpuva_to_iova_base(struct vm_gk20a *vm, u64 gpu_vaddr)
1260{ 721{
1261 struct nvgpu_mapped_buf *buffer; 722 struct nvgpu_mapped_buf *buffer;