Skip to content

Commit

Permalink
drm/nouveau: queue delayed unmapping of VMAs on client workqueue
Browse files Browse the repository at this point in the history
VMAs are about to not take references on the VMM they belong to, which
means more care is required when handling delayed unmapping.

Queuing it on the client workqueue ensures all pending VMA unmaps will
have completed before the VMM is destroyed.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Nov 2, 2017
1 parent 814a232 commit 00d041d
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions drivers/gpu/drm/nouveau/nouveau_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,33 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
return ret;
}

struct nouveau_gem_object_unmap {
struct nouveau_cli_work work;
struct nouveau_vma *vma;
};

static void
nouveau_gem_object_delete(void *data)
nouveau_gem_object_delete(struct nouveau_vma *vma)
{
struct nouveau_vma *vma = data;
nouveau_vma_del(&vma);
}

static void
nouveau_gem_object_delete_work(struct nouveau_cli_work *w)
{
struct nouveau_gem_object_unmap *work =
container_of(w, typeof(*work), work);
nouveau_gem_object_delete(work->vma);
kfree(work);
}

static void
nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
{
const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM;
struct reservation_object *resv = nvbo->bo.resv;
struct reservation_object_list *fobj;
struct nouveau_gem_object_unmap *work;
struct dma_fence *fence = NULL;

fobj = reservation_object_get_list(resv);
Expand All @@ -117,10 +131,20 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
else
fence = reservation_object_get_excl(nvbo->bo.resv);

if (fence && mapped)
nouveau_fence_work(fence, nouveau_gem_object_delete, vma);
else
nouveau_vma_del(&vma);
if (!fence || !mapped) {
nouveau_gem_object_delete(vma);
return;
}

if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) {
WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0);
nouveau_gem_object_delete(vma);
return;
}

work->work.func = nouveau_gem_object_delete_work;
work->vma = vma;
nouveau_cli_work_queue(vma->vmm->cli, fence, &work->work);
}

void
Expand Down

0 comments on commit 00d041d

Please sign in to comment.