Lines Matching +full:node +full:- +full:version

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2015-2018 Etnaviv Project
6 #include <linux/dma-mapping.h>
29 unmapped_page = context->global->ops->unmap(context, iova, in etnaviv_context_unmap()
51 return -EINVAL; in etnaviv_context_map()
55 ret = context->global->ops->map(context, iova, paddr, pgsize, in etnaviv_context_map()
62 size -= pgsize; in etnaviv_context_map()
67 etnaviv_context_unmap(context, orig_iova, orig_size - size); in etnaviv_context_map()
80 return -EINVAL; in etnaviv_iommu_map()
83 phys_addr_t pa = sg_dma_address(sg) - sg->offset; in etnaviv_iommu_map()
84 size_t bytes = sg_dma_len(sg) + sg->offset; in etnaviv_iommu_map()
95 context->flush_seq++; in etnaviv_iommu_map()
100 etnaviv_context_unmap(context, iova, da - iova); in etnaviv_iommu_map()
112 size_t bytes = sg_dma_len(sg) + sg->offset; in etnaviv_iommu_unmap()
123 context->flush_seq++; in etnaviv_iommu_unmap()
129 struct etnaviv_gem_object *etnaviv_obj = mapping->object; in etnaviv_iommu_remove_mapping()
131 lockdep_assert_held(&context->lock); in etnaviv_iommu_remove_mapping()
133 etnaviv_iommu_unmap(context, mapping->vram_node.start, in etnaviv_iommu_remove_mapping()
134 etnaviv_obj->sgt, etnaviv_obj->base.size); in etnaviv_iommu_remove_mapping()
135 drm_mm_remove_node(&mapping->vram_node); in etnaviv_iommu_remove_mapping()
140 struct etnaviv_iommu_context *context = mapping->context; in etnaviv_iommu_reap_mapping()
142 lockdep_assert_held(&context->lock); in etnaviv_iommu_reap_mapping()
143 WARN_ON(mapping->use); in etnaviv_iommu_reap_mapping()
146 etnaviv_iommu_context_put(mapping->context); in etnaviv_iommu_reap_mapping()
147 mapping->context = NULL; in etnaviv_iommu_reap_mapping()
148 list_del_init(&mapping->mmu_node); in etnaviv_iommu_reap_mapping()
152 struct drm_mm_node *node, size_t size) in etnaviv_iommu_find_iova() argument
158 lockdep_assert_held(&context->lock); in etnaviv_iommu_find_iova()
166 ret = drm_mm_insert_node_in_range(&context->mm, node, in etnaviv_iommu_find_iova()
168 if (ret != -ENOSPC) in etnaviv_iommu_find_iova()
172 drm_mm_scan_init(&scan, &context->mm, size, 0, 0, mode); in etnaviv_iommu_find_iova()
176 list_for_each_entry(free, &context->mappings, mmu_node) { in etnaviv_iommu_find_iova()
177 /* If this vram node has not been used, skip this. */ in etnaviv_iommu_find_iova()
178 if (!free->vram_node.mm) in etnaviv_iommu_find_iova()
182 * If the iova is pinned, then it's in-use, in etnaviv_iommu_find_iova()
185 if (free->use) in etnaviv_iommu_find_iova()
188 list_add(&free->scan_node, &list); in etnaviv_iommu_find_iova()
189 if (drm_mm_scan_add_block(&scan, &free->vram_node)) { in etnaviv_iommu_find_iova()
198 BUG_ON(drm_mm_scan_remove_block(&scan, &m->vram_node)); in etnaviv_iommu_find_iova()
209 if (!drm_mm_scan_remove_block(&scan, &m->vram_node)) in etnaviv_iommu_find_iova()
210 list_del_init(&m->scan_node); in etnaviv_iommu_find_iova()
219 list_del_init(&m->scan_node); in etnaviv_iommu_find_iova()
234 struct drm_mm_node *node, size_t size, u64 va) in etnaviv_iommu_insert_exact() argument
241 lockdep_assert_held(&context->lock); in etnaviv_iommu_insert_exact()
243 ret = drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va, in etnaviv_iommu_insert_exact()
245 if (ret != -ENOSPC) in etnaviv_iommu_insert_exact()
249 * When we can't insert the node, due to a existing mapping blocking in etnaviv_iommu_insert_exact()
259 drm_mm_for_each_node_in_range(scan_node, &context->mm, va, va + size) { in etnaviv_iommu_insert_exact()
263 if (m->use) in etnaviv_iommu_insert_exact()
264 return -ENOSPC; in etnaviv_iommu_insert_exact()
266 list_add(&m->scan_node, &scan_list); in etnaviv_iommu_insert_exact()
271 list_del_init(&m->scan_node); in etnaviv_iommu_insert_exact()
274 return drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va, in etnaviv_iommu_insert_exact()
282 struct sg_table *sgt = etnaviv_obj->sgt; in etnaviv_iommu_map_gem()
283 struct drm_mm_node *node; in etnaviv_iommu_map_gem() local
286 lockdep_assert_held(&etnaviv_obj->lock); in etnaviv_iommu_map_gem()
288 mutex_lock(&context->lock); in etnaviv_iommu_map_gem()
291 if (context->global->version == ETNAVIV_IOMMU_V1 && in etnaviv_iommu_map_gem()
292 sgt->nents == 1 && !(etnaviv_obj->flags & ETNA_BO_FORCE_MMU)) { in etnaviv_iommu_map_gem()
295 iova = sg_dma_address(sgt->sgl) - memory_base; in etnaviv_iommu_map_gem()
296 if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) { in etnaviv_iommu_map_gem()
297 mapping->iova = iova; in etnaviv_iommu_map_gem()
298 mapping->context = etnaviv_iommu_context_get(context); in etnaviv_iommu_map_gem()
299 list_add_tail(&mapping->mmu_node, &context->mappings); in etnaviv_iommu_map_gem()
305 node = &mapping->vram_node; in etnaviv_iommu_map_gem()
308 ret = etnaviv_iommu_insert_exact(context, node, in etnaviv_iommu_map_gem()
309 etnaviv_obj->base.size, va); in etnaviv_iommu_map_gem()
311 ret = etnaviv_iommu_find_iova(context, node, in etnaviv_iommu_map_gem()
312 etnaviv_obj->base.size); in etnaviv_iommu_map_gem()
316 mapping->iova = node->start; in etnaviv_iommu_map_gem()
317 ret = etnaviv_iommu_map(context, node->start, sgt, etnaviv_obj->base.size, in etnaviv_iommu_map_gem()
321 drm_mm_remove_node(node); in etnaviv_iommu_map_gem()
325 mapping->context = etnaviv_iommu_context_get(context); in etnaviv_iommu_map_gem()
326 list_add_tail(&mapping->mmu_node, &context->mappings); in etnaviv_iommu_map_gem()
328 mutex_unlock(&context->lock); in etnaviv_iommu_map_gem()
336 WARN_ON(mapping->use); in etnaviv_iommu_unmap_gem()
338 mutex_lock(&context->lock); in etnaviv_iommu_unmap_gem()
341 if (!mapping->context) { in etnaviv_iommu_unmap_gem()
342 mutex_unlock(&context->lock); in etnaviv_iommu_unmap_gem()
346 /* If the vram node is on the mm, unmap and remove the node */ in etnaviv_iommu_unmap_gem()
347 if (mapping->vram_node.mm == &context->mm) in etnaviv_iommu_unmap_gem()
350 list_del(&mapping->mmu_node); in etnaviv_iommu_unmap_gem()
351 mutex_unlock(&context->lock); in etnaviv_iommu_unmap_gem()
360 etnaviv_cmdbuf_suballoc_unmap(context, &context->cmdbuf_mapping); in etnaviv_iommu_context_free()
362 context->global->ops->free(context); in etnaviv_iommu_context_free()
366 kref_put(&context->refcount, etnaviv_iommu_context_free); in etnaviv_iommu_context_put()
376 if (global->version == ETNAVIV_IOMMU_V1) in etnaviv_iommu_context_init()
384 ret = etnaviv_cmdbuf_suballoc_map(suballoc, ctx, &ctx->cmdbuf_mapping, in etnaviv_iommu_context_init()
385 global->memory_base); in etnaviv_iommu_context_init()
389 if (global->version == ETNAVIV_IOMMU_V1 && in etnaviv_iommu_context_init()
390 ctx->cmdbuf_mapping.iova > 0x80000000) { in etnaviv_iommu_context_init()
391 dev_err(global->dev, in etnaviv_iommu_context_init()
399 etnaviv_cmdbuf_suballoc_unmap(ctx, &ctx->cmdbuf_mapping); in etnaviv_iommu_context_init()
401 global->ops->free(ctx); in etnaviv_iommu_context_init()
408 context->global->ops->restore(gpu, context); in etnaviv_iommu_restore()
416 mutex_lock(&context->lock); in etnaviv_iommu_get_suballoc_va()
418 if (mapping->use > 0) { in etnaviv_iommu_get_suballoc_va()
419 mapping->use++; in etnaviv_iommu_get_suballoc_va()
420 mutex_unlock(&context->lock); in etnaviv_iommu_get_suballoc_va()
430 if (context->global->version == ETNAVIV_IOMMU_V1) { in etnaviv_iommu_get_suballoc_va()
431 mapping->iova = paddr - memory_base; in etnaviv_iommu_get_suballoc_va()
433 struct drm_mm_node *node = &mapping->vram_node; in etnaviv_iommu_get_suballoc_va() local
436 ret = etnaviv_iommu_find_iova(context, node, size); in etnaviv_iommu_get_suballoc_va()
438 mutex_unlock(&context->lock); in etnaviv_iommu_get_suballoc_va()
442 mapping->iova = node->start; in etnaviv_iommu_get_suballoc_va()
443 ret = etnaviv_context_map(context, node->start, paddr, size, in etnaviv_iommu_get_suballoc_va()
446 drm_mm_remove_node(node); in etnaviv_iommu_get_suballoc_va()
447 mutex_unlock(&context->lock); in etnaviv_iommu_get_suballoc_va()
451 context->flush_seq++; in etnaviv_iommu_get_suballoc_va()
454 list_add_tail(&mapping->mmu_node, &context->mappings); in etnaviv_iommu_get_suballoc_va()
455 mapping->use = 1; in etnaviv_iommu_get_suballoc_va()
457 mutex_unlock(&context->lock); in etnaviv_iommu_get_suballoc_va()
465 struct drm_mm_node *node = &mapping->vram_node; in etnaviv_iommu_put_suballoc_va() local
467 mutex_lock(&context->lock); in etnaviv_iommu_put_suballoc_va()
468 mapping->use--; in etnaviv_iommu_put_suballoc_va()
470 if (mapping->use > 0 || context->global->version == ETNAVIV_IOMMU_V1) { in etnaviv_iommu_put_suballoc_va()
471 mutex_unlock(&context->lock); in etnaviv_iommu_put_suballoc_va()
475 etnaviv_context_unmap(context, node->start, node->size); in etnaviv_iommu_put_suballoc_va()
476 drm_mm_remove_node(node); in etnaviv_iommu_put_suballoc_va()
477 mutex_unlock(&context->lock); in etnaviv_iommu_put_suballoc_va()
482 return context->global->ops->dump_size(context); in etnaviv_iommu_dump_size()
487 context->global->ops->dump(context, buf); in etnaviv_iommu_dump()
492 enum etnaviv_iommu_version version = ETNAVIV_IOMMU_V1; in etnaviv_iommu_global_init() local
493 struct etnaviv_drm_private *priv = gpu->drm->dev_private; in etnaviv_iommu_global_init()
495 struct device *dev = gpu->drm->dev; in etnaviv_iommu_global_init()
497 if (gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION) in etnaviv_iommu_global_init()
498 version = ETNAVIV_IOMMU_V2; in etnaviv_iommu_global_init()
500 if (priv->mmu_global) { in etnaviv_iommu_global_init()
501 if (priv->mmu_global->version != version) { in etnaviv_iommu_global_init()
502 dev_err(gpu->dev, in etnaviv_iommu_global_init()
503 "MMU version doesn't match global version\n"); in etnaviv_iommu_global_init()
504 return -ENXIO; in etnaviv_iommu_global_init()
507 priv->mmu_global->use++; in etnaviv_iommu_global_init()
513 return -ENOMEM; in etnaviv_iommu_global_init()
515 global->bad_page_cpu = dma_alloc_wc(dev, SZ_4K, &global->bad_page_dma, in etnaviv_iommu_global_init()
517 if (!global->bad_page_cpu) in etnaviv_iommu_global_init()
520 memset32(global->bad_page_cpu, 0xdead55aa, SZ_4K / sizeof(u32)); in etnaviv_iommu_global_init()
522 if (version == ETNAVIV_IOMMU_V2) { in etnaviv_iommu_global_init()
523 global->v2.pta_cpu = dma_alloc_wc(dev, ETNAVIV_PTA_SIZE, in etnaviv_iommu_global_init()
524 &global->v2.pta_dma, GFP_KERNEL); in etnaviv_iommu_global_init()
525 if (!global->v2.pta_cpu) in etnaviv_iommu_global_init()
529 global->dev = dev; in etnaviv_iommu_global_init()
530 global->version = version; in etnaviv_iommu_global_init()
531 global->use = 1; in etnaviv_iommu_global_init()
532 mutex_init(&global->lock); in etnaviv_iommu_global_init()
534 if (version == ETNAVIV_IOMMU_V1) in etnaviv_iommu_global_init()
535 global->ops = &etnaviv_iommuv1_ops; in etnaviv_iommu_global_init()
537 global->ops = &etnaviv_iommuv2_ops; in etnaviv_iommu_global_init()
539 priv->mmu_global = global; in etnaviv_iommu_global_init()
544 dma_free_wc(dev, SZ_4K, global->bad_page_cpu, global->bad_page_dma); in etnaviv_iommu_global_init()
548 return -ENOMEM; in etnaviv_iommu_global_init()
553 struct etnaviv_drm_private *priv = gpu->drm->dev_private; in etnaviv_iommu_global_fini()
554 struct etnaviv_iommu_global *global = priv->mmu_global; in etnaviv_iommu_global_fini()
559 if (--global->use > 0) in etnaviv_iommu_global_fini()
562 if (global->v2.pta_cpu) in etnaviv_iommu_global_fini()
563 dma_free_wc(global->dev, ETNAVIV_PTA_SIZE, in etnaviv_iommu_global_fini()
564 global->v2.pta_cpu, global->v2.pta_dma); in etnaviv_iommu_global_fini()
566 if (global->bad_page_cpu) in etnaviv_iommu_global_fini()
567 dma_free_wc(global->dev, SZ_4K, in etnaviv_iommu_global_fini()
568 global->bad_page_cpu, global->bad_page_dma); in etnaviv_iommu_global_fini()
570 mutex_destroy(&global->lock); in etnaviv_iommu_global_fini()
573 priv->mmu_global = NULL; in etnaviv_iommu_global_fini()