diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/vm.c | 226 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/mm/vm.c | 122 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/linux/vm.h | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/vm.h | 18 |
4 files changed, 189 insertions, 196 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c index 40e3d6ea..bb337d97 100644 --- a/drivers/gpu/nvgpu/common/linux/vm.c +++ b/drivers/gpu/nvgpu/common/linux/vm.c | |||
@@ -115,84 +115,6 @@ static u64 nvgpu_get_buffer_alignment(struct gk20a *g, struct scatterlist *sgl, | |||
115 | return align; | 115 | return align; |
116 | } | 116 | } |
117 | 117 | ||
118 | static int setup_kind_legacy(struct vm_gk20a *vm, struct buffer_attrs *bfr, | ||
119 | bool *pkind_compressible) | ||
120 | { | ||
121 | struct gk20a *g = gk20a_from_vm(vm); | ||
122 | bool kind_compressible; | ||
123 | |||
124 | if (unlikely(bfr->kind_v == g->ops.mm.get_kind_invalid())) | ||
125 | bfr->kind_v = g->ops.mm.get_kind_pitch(); | ||
126 | |||
127 | if (unlikely(!gk20a_kind_is_supported(bfr->kind_v))) { | ||
128 | nvgpu_err(g, "kind 0x%x not supported", bfr->kind_v); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | bfr->uc_kind_v = g->ops.mm.get_kind_invalid(); | ||
133 | /* find a suitable incompressible kind if it becomes necessary later */ | ||
134 | kind_compressible = gk20a_kind_is_compressible(bfr->kind_v); | ||
135 | if (kind_compressible) { | ||
136 | bfr->uc_kind_v = gk20a_get_uncompressed_kind(bfr->kind_v); | ||
137 | if (unlikely(bfr->uc_kind_v == g->ops.mm.get_kind_invalid())) { | ||
138 | /* shouldn't happen, but it is worth cross-checking */ | ||
139 | nvgpu_err(g, "comptag kind 0x%x can't be" | ||
140 | " downgraded to uncompressed kind", | ||
141 | bfr->kind_v); | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | *pkind_compressible = kind_compressible; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int setup_buffer_kind_and_compression(struct vm_gk20a *vm, | ||
151 | u32 flags, | ||
152 | struct buffer_attrs *bfr, | ||
153 | enum gmmu_pgsz_gk20a pgsz_idx) | ||
154 | { | ||
155 | bool kind_compressible; | ||
156 | struct gk20a *g = gk20a_from_vm(vm); | ||
157 | int ctag_granularity = g->ops.fb.compression_page_size(g); | ||
158 | |||
159 | if (!bfr->use_kind_v) | ||
160 | bfr->kind_v = g->ops.mm.get_kind_invalid(); | ||
161 | if (!bfr->use_uc_kind_v) | ||
162 | bfr->uc_kind_v = g->ops.mm.get_kind_invalid(); | ||
163 | |||
164 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | ||
165 | kind_compressible = (bfr->kind_v != | ||
166 | g->ops.mm.get_kind_invalid()); | ||
167 | if (!kind_compressible) | ||
168 | bfr->kind_v = bfr->uc_kind_v; | ||
169 | } else { | ||
170 | int err = setup_kind_legacy(vm, bfr, &kind_compressible); | ||
171 | |||
172 | if (err) | ||
173 | return err; | ||
174 | } | ||
175 | |||
176 | /* comptags only supported for suitable kinds, 128KB pagesize */ | ||
177 | if (kind_compressible && | ||
178 | vm->gmmu_page_sizes[pgsz_idx] < | ||
179 | g->ops.fb.compressible_page_size(g)) { | ||
180 | /* it is safe to fall back to uncompressed as | ||
181 | functionality is not harmed */ | ||
182 | bfr->kind_v = bfr->uc_kind_v; | ||
183 | kind_compressible = false; | ||
184 | } | ||
185 | if (kind_compressible) | ||
186 | bfr->ctag_lines = DIV_ROUND_UP_ULL(bfr->size, ctag_granularity); | ||
187 | else | ||
188 | bfr->ctag_lines = 0; | ||
189 | |||
190 | bfr->use_kind_v = (bfr->kind_v != g->ops.mm.get_kind_invalid()); | ||
191 | bfr->use_uc_kind_v = (bfr->uc_kind_v != g->ops.mm.get_kind_invalid()); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, | 118 | int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, |
197 | struct dma_buf **dmabuf, | 119 | struct dma_buf **dmabuf, |
198 | u64 *offset) | 120 | u64 *offset) |
@@ -279,40 +201,6 @@ static u64 __nvgpu_vm_find_mapping(struct vm_gk20a *vm, | |||
279 | return mapped_buffer->addr; | 201 | return mapped_buffer->addr; |
280 | } | 202 | } |
281 | 203 | ||
282 | static int setup_bfr_kind_fields(struct buffer_attrs *bfr, s16 compr_kind, | ||
283 | s16 incompr_kind, u32 flags) | ||
284 | { | ||
285 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | ||
286 | /* were we supplied with a kind in either parameter? */ | ||
287 | if ((compr_kind < 0 || compr_kind >= NV_KIND_ATTR_SIZE) && | ||
288 | (incompr_kind < 0 || incompr_kind >= NV_KIND_ATTR_SIZE)) | ||
289 | return -EINVAL; | ||
290 | |||
291 | if (compr_kind != NV_KIND_INVALID) { | ||
292 | bfr->use_kind_v = true; | ||
293 | bfr->kind_v = (u8)compr_kind; | ||
294 | } | ||
295 | |||
296 | if (incompr_kind != NV_KIND_INVALID) { | ||
297 | bfr->use_uc_kind_v = true; | ||
298 | bfr->uc_kind_v = (u8)incompr_kind; | ||
299 | } | ||
300 | } else { | ||
301 | if (compr_kind < 0 || compr_kind >= NV_KIND_ATTR_SIZE) | ||
302 | return -EINVAL; | ||
303 | |||
304 | bfr->use_kind_v = true; | ||
305 | bfr->kind_v = (u8)compr_kind; | ||
306 | |||
307 | /* | ||
308 | * Note: setup_buffer_kind_and_compression() will | ||
309 | * figure out uc_kind_v or return an error | ||
310 | */ | ||
311 | } | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | 204 | u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, |
317 | struct dma_buf *dmabuf, | 205 | struct dma_buf *dmabuf, |
318 | u64 offset_align, | 206 | u64 offset_align, |
@@ -326,19 +214,19 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
326 | { | 214 | { |
327 | struct gk20a *g = gk20a_from_vm(vm); | 215 | struct gk20a *g = gk20a_from_vm(vm); |
328 | struct device *dev = dev_from_gk20a(g); | 216 | struct device *dev = dev_from_gk20a(g); |
329 | struct gk20a_comptag_allocator *ctag_allocator = &g->gr.comp_tags; | 217 | struct nvgpu_ctag_buffer_info binfo = { 0 }; |
218 | struct gk20a_comptags comptags; | ||
219 | struct nvgpu_vm_area *vm_area = NULL; | ||
220 | struct nvgpu_sgt *nvgpu_sgt; | ||
221 | struct sg_table *sgt; | ||
330 | struct nvgpu_mapped_buf *mapped_buffer = NULL; | 222 | struct nvgpu_mapped_buf *mapped_buffer = NULL; |
223 | enum nvgpu_aperture aperture; | ||
331 | bool va_allocated = false; | 224 | bool va_allocated = false; |
332 | u64 map_offset = 0; | ||
333 | int err = 0; | ||
334 | struct buffer_attrs bfr = {NULL}; | ||
335 | struct gk20a_comptags comptags; | ||
336 | bool clear_ctags = false; | 225 | bool clear_ctags = false; |
337 | struct scatterlist *sgl; | 226 | u64 map_offset = 0; |
338 | struct nvgpu_vm_area *vm_area = NULL; | 227 | u64 align; |
339 | u32 ctag_offset; | 228 | u32 ctag_offset; |
340 | enum nvgpu_aperture aperture; | 229 | int err = 0; |
341 | struct nvgpu_sgt *nvgpu_sgt; | ||
342 | 230 | ||
343 | /* | 231 | /* |
344 | * The kind used as part of the key for map caching. HW may | 232 | * The kind used as part of the key for map caching. HW may |
@@ -347,6 +235,9 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
347 | */ | 235 | */ |
348 | s16 map_key_kind; | 236 | s16 map_key_kind; |
349 | 237 | ||
238 | binfo.flags = flags; | ||
239 | binfo.size = dmabuf->size; | ||
240 | |||
350 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | 241 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { |
351 | if (compr_kind != NV_KIND_INVALID) | 242 | if (compr_kind != NV_KIND_INVALID) |
352 | map_key_kind = compr_kind; | 243 | map_key_kind = compr_kind; |
@@ -376,28 +267,16 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
376 | } | 267 | } |
377 | } | 268 | } |
378 | 269 | ||
379 | /* pin buffer to get phys/iovmm addr */ | 270 | sgt = gk20a_mm_pin(dev, dmabuf); |
380 | bfr.sgt = gk20a_mm_pin(dev, dmabuf); | 271 | if (IS_ERR(sgt)) { |
381 | if (IS_ERR(bfr.sgt)) { | ||
382 | /* Falling back to physical is actually possible | ||
383 | * here in many cases if we use 4K phys pages in the | ||
384 | * gmmu. However we have some regions which require | ||
385 | * contig regions to work properly (either phys-contig | ||
386 | * or contig through smmu io_vaspace). Until we can | ||
387 | * track the difference between those two cases we have | ||
388 | * to fail the mapping when we run out of SMMU space. | ||
389 | */ | ||
390 | nvgpu_warn(g, "oom allocating tracking buffer"); | 272 | nvgpu_warn(g, "oom allocating tracking buffer"); |
391 | goto clean_up; | 273 | goto clean_up; |
392 | } | 274 | } |
393 | 275 | ||
394 | err = setup_bfr_kind_fields(&bfr, compr_kind, incompr_kind, flags); | 276 | err = nvgpu_vm_init_kind_info(&binfo, compr_kind, incompr_kind); |
395 | if (err) | 277 | if (err) |
396 | goto clean_up; | 278 | goto clean_up; |
397 | 279 | ||
398 | bfr.size = dmabuf->size; | ||
399 | sgl = bfr.sgt->sgl; | ||
400 | |||
401 | aperture = gk20a_dmabuf_aperture(g, dmabuf); | 280 | aperture = gk20a_dmabuf_aperture(g, dmabuf); |
402 | if (aperture == APERTURE_INVALID) { | 281 | if (aperture == APERTURE_INVALID) { |
403 | err = -EINVAL; | 282 | err = -EINVAL; |
@@ -407,60 +286,59 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
407 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) | 286 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) |
408 | map_offset = offset_align; | 287 | map_offset = offset_align; |
409 | 288 | ||
410 | bfr.align = nvgpu_get_buffer_alignment(g, sgl, aperture); | 289 | align = nvgpu_get_buffer_alignment(g, sgt->sgl, aperture); |
411 | if (g->mm.disable_bigpage) | 290 | if (g->mm.disable_bigpage) |
412 | bfr.pgsz_idx = gmmu_page_size_small; | 291 | binfo.pgsz_idx = gmmu_page_size_small; |
413 | else | 292 | else |
414 | bfr.pgsz_idx = __get_pte_size(vm, map_offset, | 293 | binfo.pgsz_idx = __get_pte_size(vm, map_offset, |
415 | min_t(u64, bfr.size, bfr.align)); | 294 | min_t(u64, binfo.size, align)); |
416 | mapping_size = mapping_size ? mapping_size : bfr.size; | 295 | mapping_size = mapping_size ? mapping_size : binfo.size; |
417 | mapping_size = ALIGN(mapping_size, SZ_4K); | 296 | mapping_size = ALIGN(mapping_size, SZ_4K); |
418 | 297 | ||
419 | if ((mapping_size > bfr.size) || | 298 | if ((mapping_size > binfo.size) || |
420 | (buffer_offset > (bfr.size - mapping_size))) { | 299 | (buffer_offset > (binfo.size - mapping_size))) { |
421 | err = -EINVAL; | 300 | err = -EINVAL; |
422 | goto clean_up; | 301 | goto clean_up; |
423 | } | 302 | } |
424 | 303 | ||
425 | /* Check if we should use a fixed offset for mapping this buffer */ | 304 | /* Check if we should use a fixed offset for mapping this buffer */ |
426 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) { | 305 | if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) { |
427 | err = nvgpu_vm_area_validate_buffer(vm, offset_align, mapping_size, | 306 | err = nvgpu_vm_area_validate_buffer(vm, |
428 | bfr.pgsz_idx, &vm_area); | 307 | offset_align, |
308 | mapping_size, | ||
309 | binfo.pgsz_idx, | ||
310 | &vm_area); | ||
429 | if (err) | 311 | if (err) |
430 | goto clean_up; | 312 | goto clean_up; |
431 | 313 | ||
432 | map_offset = offset_align; | 314 | map_offset = offset_align; |
433 | va_allocated = false; | 315 | va_allocated = false; |
434 | } else | 316 | } else { |
435 | va_allocated = true; | 317 | va_allocated = true; |
318 | } | ||
436 | 319 | ||
437 | err = setup_buffer_kind_and_compression(vm, flags, &bfr, bfr.pgsz_idx); | 320 | err = nvgpu_vm_compute_kind_and_compression(vm, &binfo); |
438 | if (unlikely(err)) { | 321 | if (err) { |
439 | nvgpu_err(g, "failure setting up kind and compression"); | 322 | nvgpu_err(g, "failure setting up kind and compression"); |
440 | goto clean_up; | 323 | goto clean_up; |
441 | } | 324 | } |
442 | 325 | ||
443 | /* bar1 and pmu vm don't need ctag */ | 326 | /* bar1 and pmu vm don't need ctag */ |
444 | if (!vm->enable_ctag) | 327 | if (!vm->enable_ctag) |
445 | bfr.ctag_lines = 0; | 328 | binfo.ctag_lines = 0; |
446 | 329 | ||
447 | gk20a_get_comptags(dev, dmabuf, &comptags); | 330 | gk20a_get_comptags(dev, dmabuf, &comptags); |
448 | 331 | ||
449 | /* ensure alignment to compression page size if compression enabled */ | 332 | if (binfo.ctag_lines && !comptags.lines) { |
450 | if (bfr.ctag_offset) | ||
451 | mapping_size = ALIGN(mapping_size, | ||
452 | g->ops.fb.compression_page_size(g)); | ||
453 | |||
454 | if (bfr.ctag_lines && !comptags.lines) { | ||
455 | /* allocate compression resources if needed */ | 333 | /* allocate compression resources if needed */ |
456 | err = gk20a_alloc_comptags(g, dev, dmabuf, | 334 | err = gk20a_alloc_comptags(g, dev, dmabuf, |
457 | ctag_allocator, | 335 | &g->gr.comp_tags, |
458 | bfr.ctag_lines); | 336 | binfo.ctag_lines); |
459 | if (unlikely(err)) { | 337 | if (err) { |
460 | /* TBD: we can partially alloc ctags as well... */ | 338 | /* TBD: we can partially alloc ctags as well... */ |
461 | if (bfr.use_uc_kind_v) { | 339 | if (binfo.use_uc_kind_v) { |
462 | /* no comptags, but fallback kind available */ | 340 | /* no comptags, but fallback kind available */ |
463 | bfr.kind_v = bfr.uc_kind_v; | 341 | binfo.kind_v = binfo.uc_kind_v; |
464 | } else { | 342 | } else { |
465 | nvgpu_err(g, "comptag alloc failed and no fallback kind specified"); | 343 | nvgpu_err(g, "comptag alloc failed and no fallback kind specified"); |
466 | goto clean_up; | 344 | goto clean_up; |
@@ -479,12 +357,6 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
479 | } | 357 | } |
480 | } | 358 | } |
481 | 359 | ||
482 | /* store the comptag info */ | ||
483 | bfr.ctag_offset = comptags.offset; | ||
484 | bfr.ctag_lines = comptags.lines; | ||
485 | bfr.ctag_allocated_lines = comptags.allocated_lines; | ||
486 | bfr.ctag_user_mappable = comptags.user_mappable; | ||
487 | |||
488 | /* | 360 | /* |
489 | * Calculate comptag index for this mapping. Differs in | 361 | * Calculate comptag index for this mapping. Differs in |
490 | * case of partial mapping. | 362 | * case of partial mapping. |
@@ -494,7 +366,7 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
494 | ctag_offset += buffer_offset >> | 366 | ctag_offset += buffer_offset >> |
495 | ilog2(g->ops.fb.compression_page_size(g)); | 367 | ilog2(g->ops.fb.compression_page_size(g)); |
496 | 368 | ||
497 | nvgpu_sgt = nvgpu_linux_sgt_create(g, bfr.sgt); | 369 | nvgpu_sgt = nvgpu_linux_sgt_create(g, sgt); |
498 | 370 | ||
499 | /* update gmmu ptes */ | 371 | /* update gmmu ptes */ |
500 | map_offset = g->ops.mm.gmmu_map(vm, | 372 | map_offset = g->ops.mm.gmmu_map(vm, |
@@ -502,8 +374,8 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
502 | nvgpu_sgt, | 374 | nvgpu_sgt, |
503 | buffer_offset, /* sg offset */ | 375 | buffer_offset, /* sg offset */ |
504 | mapping_size, | 376 | mapping_size, |
505 | bfr.pgsz_idx, | 377 | binfo.pgsz_idx, |
506 | bfr.kind_v, | 378 | binfo.kind_v, |
507 | ctag_offset, | 379 | ctag_offset, |
508 | flags, rw_flag, | 380 | flags, rw_flag, |
509 | clear_ctags, | 381 | clear_ctags, |
@@ -522,13 +394,13 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
522 | goto clean_up; | 394 | goto clean_up; |
523 | } | 395 | } |
524 | mapped_buffer->dmabuf = dmabuf; | 396 | mapped_buffer->dmabuf = dmabuf; |
525 | mapped_buffer->sgt = bfr.sgt; | 397 | mapped_buffer->sgt = sgt; |
526 | mapped_buffer->addr = map_offset; | 398 | mapped_buffer->addr = map_offset; |
527 | mapped_buffer->size = mapping_size; | 399 | mapped_buffer->size = mapping_size; |
528 | mapped_buffer->pgsz_idx = bfr.pgsz_idx; | 400 | mapped_buffer->pgsz_idx = binfo.pgsz_idx; |
529 | mapped_buffer->ctag_offset = bfr.ctag_offset; | 401 | mapped_buffer->ctag_offset = ctag_offset; |
530 | mapped_buffer->ctag_lines = bfr.ctag_lines; | 402 | mapped_buffer->ctag_lines = binfo.ctag_lines; |
531 | mapped_buffer->ctag_allocated_lines = bfr.ctag_allocated_lines; | 403 | mapped_buffer->ctag_allocated_lines = comptags.allocated_lines; |
532 | mapped_buffer->vm = vm; | 404 | mapped_buffer->vm = vm; |
533 | mapped_buffer->flags = flags; | 405 | mapped_buffer->flags = flags; |
534 | mapped_buffer->kind = map_key_kind; | 406 | mapped_buffer->kind = map_key_kind; |
@@ -557,9 +429,9 @@ u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | |||
557 | clean_up: | 429 | clean_up: |
558 | nvgpu_kfree(g, mapped_buffer); | 430 | nvgpu_kfree(g, mapped_buffer); |
559 | if (va_allocated) | 431 | if (va_allocated) |
560 | __nvgpu_vm_free_va(vm, map_offset, bfr.pgsz_idx); | 432 | __nvgpu_vm_free_va(vm, map_offset, binfo.pgsz_idx); |
561 | if (!IS_ERR(bfr.sgt)) | 433 | if (!IS_ERR(sgt)) |
562 | gk20a_mm_unpin(dev, dmabuf, bfr.sgt); | 434 | gk20a_mm_unpin(dev, dmabuf, sgt); |
563 | 435 | ||
564 | nvgpu_mutex_release(&vm->update_gmmu_lock); | 436 | nvgpu_mutex_release(&vm->update_gmmu_lock); |
565 | nvgpu_log_info(g, "err=%d", err); | 437 | nvgpu_log_info(g, "err=%d", err); |
diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c index 2ce62e75..64c9c217 100644 --- a/drivers/gpu/nvgpu/common/mm/vm.c +++ b/drivers/gpu/nvgpu/common/mm/vm.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include "gk20a/gk20a.h" | 36 | #include "gk20a/gk20a.h" |
37 | #include "gk20a/mm_gk20a.h" | 37 | #include "gk20a/mm_gk20a.h" |
38 | #include "gk20a/kind_gk20a.h" | ||
38 | 39 | ||
39 | static void __nvgpu_vm_unmap(struct nvgpu_mapped_buf *mapped_buffer, | 40 | static void __nvgpu_vm_unmap(struct nvgpu_mapped_buf *mapped_buffer, |
40 | struct vm_gk20a_mapping_batch *batch); | 41 | struct vm_gk20a_mapping_batch *batch); |
@@ -827,3 +828,124 @@ done: | |||
827 | nvgpu_mutex_release(&vm->update_gmmu_lock); | 828 | nvgpu_mutex_release(&vm->update_gmmu_lock); |
828 | return; | 829 | return; |
829 | } | 830 | } |
831 | |||
832 | int nvgpu_vm_init_kind_info(struct nvgpu_ctag_buffer_info *binfo, | ||
833 | s16 compr_kind, s16 incompr_kind) | ||
834 | { | ||
835 | if (binfo->flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | ||
836 | /* were we supplied with a kind in either parameter? */ | ||
837 | if ((compr_kind < 0 || compr_kind >= NV_KIND_ATTR_SIZE) && | ||
838 | (incompr_kind < 0 || incompr_kind >= NV_KIND_ATTR_SIZE)) | ||
839 | return -EINVAL; | ||
840 | |||
841 | if (compr_kind != NV_KIND_INVALID) { | ||
842 | binfo->use_kind_v = true; | ||
843 | binfo->kind_v = (u8)compr_kind; | ||
844 | } | ||
845 | |||
846 | if (incompr_kind != NV_KIND_INVALID) { | ||
847 | binfo->use_uc_kind_v = true; | ||
848 | binfo->uc_kind_v = (u8)incompr_kind; | ||
849 | } | ||
850 | } else { | ||
851 | if (compr_kind < 0 || compr_kind >= NV_KIND_ATTR_SIZE) | ||
852 | return -EINVAL; | ||
853 | |||
854 | binfo->use_kind_v = true; | ||
855 | binfo->kind_v = (u8)compr_kind; | ||
856 | |||
857 | /* | ||
858 | * Note: nvgpu_vm_kind_and_compression() will figure out | ||
859 | * uc_kind_v or return an error. | ||
860 | */ | ||
861 | } | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int nvgpu_vm_setup_kind_legacy(struct vm_gk20a *vm, | ||
867 | struct nvgpu_ctag_buffer_info *binfo, | ||
868 | bool *pkind_compressible) | ||
869 | { | ||
870 | struct gk20a *g = gk20a_from_vm(vm); | ||
871 | bool kind_compressible; | ||
872 | |||
873 | if (unlikely(binfo->kind_v == g->ops.mm.get_kind_invalid())) | ||
874 | binfo->kind_v = g->ops.mm.get_kind_pitch(); | ||
875 | |||
876 | if (unlikely(!gk20a_kind_is_supported(binfo->kind_v))) { | ||
877 | nvgpu_err(g, "kind 0x%x not supported", binfo->kind_v); | ||
878 | return -EINVAL; | ||
879 | } | ||
880 | |||
881 | binfo->uc_kind_v = g->ops.mm.get_kind_invalid(); | ||
882 | |||
883 | /* | ||
884 | * Find a suitable incompressible kind if it becomes necessary later. | ||
885 | */ | ||
886 | kind_compressible = gk20a_kind_is_compressible(binfo->kind_v); | ||
887 | if (kind_compressible) { | ||
888 | binfo->uc_kind_v = gk20a_get_uncompressed_kind(binfo->kind_v); | ||
889 | if (binfo->uc_kind_v == g->ops.mm.get_kind_invalid()) { | ||
890 | /* | ||
891 | * Shouldn't happen, but it is worth cross-checking. | ||
892 | */ | ||
893 | nvgpu_err(g, "comptag kind 0x%x can't be" | ||
894 | " downgraded to uncompressed kind", | ||
895 | binfo->kind_v); | ||
896 | return -EINVAL; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | *pkind_compressible = kind_compressible; | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | int nvgpu_vm_compute_kind_and_compression(struct vm_gk20a *vm, | ||
906 | struct nvgpu_ctag_buffer_info *binfo) | ||
907 | { | ||
908 | bool kind_compressible; | ||
909 | struct gk20a *g = gk20a_from_vm(vm); | ||
910 | int ctag_granularity = g->ops.fb.compression_page_size(g); | ||
911 | |||
912 | if (!binfo->use_kind_v) | ||
913 | binfo->kind_v = g->ops.mm.get_kind_invalid(); | ||
914 | if (!binfo->use_uc_kind_v) | ||
915 | binfo->uc_kind_v = g->ops.mm.get_kind_invalid(); | ||
916 | |||
917 | if (binfo->flags & NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL) { | ||
918 | kind_compressible = (binfo->kind_v != | ||
919 | g->ops.mm.get_kind_invalid()); | ||
920 | if (!kind_compressible) | ||
921 | binfo->kind_v = binfo->uc_kind_v; | ||
922 | } else { | ||
923 | int err = nvgpu_vm_setup_kind_legacy(vm, binfo, | ||
924 | &kind_compressible); | ||
925 | |||
926 | if (err) | ||
927 | return err; | ||
928 | } | ||
929 | |||
930 | /* comptags only supported for suitable kinds, 128KB pagesize */ | ||
931 | if (kind_compressible && | ||
932 | vm->gmmu_page_sizes[binfo->pgsz_idx] < | ||
933 | g->ops.fb.compressible_page_size(g)) { | ||
934 | /* it is safe to fall back to uncompressed as | ||
935 | functionality is not harmed */ | ||
936 | binfo->kind_v = binfo->uc_kind_v; | ||
937 | kind_compressible = false; | ||
938 | } | ||
939 | |||
940 | if (kind_compressible) | ||
941 | binfo->ctag_lines = DIV_ROUND_UP_ULL(binfo->size, | ||
942 | ctag_granularity); | ||
943 | else | ||
944 | binfo->ctag_lines = 0; | ||
945 | |||
946 | binfo->use_kind_v = (binfo->kind_v != g->ops.mm.get_kind_invalid()); | ||
947 | binfo->use_uc_kind_v = (binfo->uc_kind_v != | ||
948 | g->ops.mm.get_kind_invalid()); | ||
949 | |||
950 | return 0; | ||
951 | } | ||
diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h b/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h index 3794706c..596a3b62 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h | |||
@@ -38,21 +38,6 @@ struct vm_gk20a; | |||
38 | struct vm_gk20a_mapping_batch; | 38 | struct vm_gk20a_mapping_batch; |
39 | struct nvgpu_vm_area; | 39 | struct nvgpu_vm_area; |
40 | 40 | ||
41 | struct buffer_attrs { | ||
42 | struct sg_table *sgt; | ||
43 | u64 size; | ||
44 | u64 align; | ||
45 | u32 ctag_offset; | ||
46 | u32 ctag_lines; | ||
47 | u32 ctag_allocated_lines; | ||
48 | int pgsz_idx; | ||
49 | u8 kind_v; | ||
50 | bool use_kind_v; | ||
51 | u8 uc_kind_v; | ||
52 | bool use_uc_kind_v; | ||
53 | bool ctag_user_mappable; | ||
54 | }; | ||
55 | |||
56 | u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, | 41 | u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, |
57 | struct dma_buf *dmabuf, | 42 | struct dma_buf *dmabuf, |
58 | u64 offset_align, | 43 | u64 offset_align, |
@@ -104,9 +89,5 @@ int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, | |||
104 | 89 | ||
105 | enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g, | 90 | enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g, |
106 | struct dma_buf *dmabuf); | 91 | struct dma_buf *dmabuf); |
107 | int validate_fixed_buffer(struct vm_gk20a *vm, | ||
108 | struct buffer_attrs *bfr, | ||
109 | u64 map_offset, u64 map_size, | ||
110 | struct nvgpu_vm_area **pva_node); | ||
111 | 92 | ||
112 | #endif | 93 | #endif |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/vm.h b/drivers/gpu/nvgpu/include/nvgpu/vm.h index 7370a8e3..801fb8ed 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vm.h | |||
@@ -122,6 +122,19 @@ mapped_buffer_from_rbtree_node(struct nvgpu_rbtree_node *node) | |||
122 | ((uintptr_t)node - offsetof(struct nvgpu_mapped_buf, node)); | 122 | ((uintptr_t)node - offsetof(struct nvgpu_mapped_buf, node)); |
123 | } | 123 | } |
124 | 124 | ||
125 | struct nvgpu_ctag_buffer_info { | ||
126 | u64 size; | ||
127 | enum gmmu_pgsz_gk20a pgsz_idx; | ||
128 | u32 flags; | ||
129 | |||
130 | u8 kind_v; | ||
131 | u8 uc_kind_v; | ||
132 | bool use_kind_v; | ||
133 | bool use_uc_kind_v; | ||
134 | |||
135 | u32 ctag_lines; | ||
136 | }; | ||
137 | |||
125 | struct vm_gk20a { | 138 | struct vm_gk20a { |
126 | struct mm_gk20a *mm; | 139 | struct mm_gk20a *mm; |
127 | struct gk20a_as_share *as_share; /* as_share this represents */ | 140 | struct gk20a_as_share *as_share; /* as_share this represents */ |
@@ -189,6 +202,11 @@ void nvgpu_vm_put(struct vm_gk20a *vm); | |||
189 | int vm_aspace_id(struct vm_gk20a *vm); | 202 | int vm_aspace_id(struct vm_gk20a *vm); |
190 | int nvgpu_big_pages_possible(struct vm_gk20a *vm, u64 base, u64 size); | 203 | int nvgpu_big_pages_possible(struct vm_gk20a *vm, u64 base, u64 size); |
191 | 204 | ||
205 | int nvgpu_vm_init_kind_info(struct nvgpu_ctag_buffer_info *binfo, | ||
206 | s16 compr_kind, s16 incompr_kind); | ||
207 | int nvgpu_vm_compute_kind_and_compression(struct vm_gk20a *vm, | ||
208 | struct nvgpu_ctag_buffer_info *binfo); | ||
209 | |||
192 | /* batching eliminates redundant cache flushes and invalidates */ | 210 | /* batching eliminates redundant cache flushes and invalidates */ |
193 | void nvgpu_vm_mapping_batch_start(struct vm_gk20a_mapping_batch *batch); | 211 | void nvgpu_vm_mapping_batch_start(struct vm_gk20a_mapping_batch *batch); |
194 | void nvgpu_vm_mapping_batch_finish( | 212 | void nvgpu_vm_mapping_batch_finish( |