Skip to content

Commit 806e229

Browse files
agxmerge
authored andcommitted
drm: etnaviv: Unmap gems on gem_close
So far the unmap from gpu address space only happened when dropping the last ref in gem_free_object_unlocked, however that is skipped if there's still multiple handles to the same GEM object. Since userspace (here mesa) in the case of softpin hands back the memory region to the pool of available GPU virtual memory closing the handle via DRM_IOCTL_GEM_CLOSE this can lead to etnaviv_iommu_insert_exact failing later since userspace thinks the vaddr is available while the kernel thinks it isn't making the submit fail like [E] submit failed: -14 (No space left on device) (etna_cmd_stream_flush:244) Fix this by unmapping the memory via the .gem_close_object callback. Signed-off-by: Guido Günther <[email protected]>
1 parent b8d3487 commit 806e229

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

drivers/gpu/drm/etnaviv/etnaviv_gem.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,38 @@ static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
512512
.mmap = etnaviv_gem_mmap_obj,
513513
};
514514

515+
void etnaviv_gem_close_object(struct drm_gem_object *obj, struct drm_file *unused)
516+
{
517+
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
518+
struct etnaviv_vram_mapping *mapping, *tmp;
519+
520+
/* Handle this via etnaviv_gem_free_object */
521+
if (obj->handle_count == 1)
522+
return;
523+
524+
WARN_ON(is_active(etnaviv_obj));
525+
526+
/*
527+
* userspace wants to release the handle so we need to remove
528+
* the mapping from the gpu's virtual address space to stay
529+
* in sync.
530+
*/
531+
list_for_each_entry_safe(mapping, tmp, &etnaviv_obj->vram_list,
532+
obj_node) {
533+
struct etnaviv_iommu_context *context = mapping->context;
534+
535+
WARN_ON(mapping->use);
536+
537+
if (context) {
538+
etnaviv_iommu_unmap_gem(context, mapping);
539+
etnaviv_iommu_context_put(context);
540+
}
541+
542+
list_del(&mapping->obj_node);
543+
kfree(mapping);
544+
}
545+
}
546+
515547
void etnaviv_gem_free_object(struct drm_gem_object *obj)
516548
{
517549
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
@@ -570,6 +602,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
570602
.get_sg_table = etnaviv_gem_prime_get_sg_table,
571603
.vmap = etnaviv_gem_prime_vmap,
572604
.vm_ops = &vm_ops,
605+
.close = etnaviv_gem_close_object,
573606
};
574607

575608
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,

0 commit comments

Comments
 (0)