summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/vm.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-10-17 20:12:28 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-11-01 22:06:30 -0400
commit88ee812d56333375f7ae44e28b483c1a161d75da (patch)
tree00b4ff8d2c0aa21721a9e8756df7dd9b1aad95ed /drivers/gpu/nvgpu/common/linux/vm.c
parenta8bd154f7907c7054f8668c5995c1b5a7f748edc (diff)
gpu: nvgpu: Remove buffer_attrs struct
Remove the buffer_attrs struct and replace it with a more streamlined nvgpu_ctag_buffer_info struct. This struct allows several different fields to all be passed by pointer to the various kind/compression functions in the VM map process. This path also moves several comptag/kind related functions to the core vm.c code since these functions can be reused by other OSes. Change-Id: I2a0f0a1c4b554ce4c8f2acdbe3161392e717d3bf Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1583984 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/vm.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm.c226
1 files changed, 49 insertions, 177 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
118static 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
150static 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
196int nvgpu_vm_find_buf(struct vm_gk20a *vm, u64 gpu_va, 118int 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
282static 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
316u64 nvgpu_vm_map_linux(struct vm_gk20a *vm, 204u64 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,
557clean_up: 429clean_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);