drm/nouveau: assign fence_chan->name correctly

Make nouveau_fence_chan refcounted, to make trace_fence_destroy
always return the correct name without a race condition.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index dfd0b9e..dba1f7e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -101,6 +101,18 @@
 }
 
 static void
+nouveau_fence_context_put(struct kref *fence_ref)
+{
+	kfree(container_of(fence_ref, struct nouveau_fence_chan, fence_ref));
+}
+
+void
+nouveau_fence_context_free(struct nouveau_fence_chan *fctx)
+{
+	kref_put(&fctx->fence_ref, nouveau_fence_context_put);
+}
+
+static void
 nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx)
 {
 	struct nouveau_fence *fence;
@@ -141,6 +153,7 @@
 nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx)
 {
 	struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
+	struct nouveau_cli *cli = (void *)nvif_client(chan->object);
 	int ret;
 
 	INIT_LIST_HEAD(&fctx->flip);
@@ -148,6 +161,14 @@
 	spin_lock_init(&fctx->lock);
 	fctx->context = priv->context_base + chan->chid;
 
+	if (chan == chan->drm->cechan)
+		strcpy(fctx->name, "copy engine channel");
+	else if (chan == chan->drm->channel)
+		strcpy(fctx->name, "generic kernel channel");
+	else
+		strcpy(fctx->name, nvkm_client(&cli->base)->name);
+
+	kref_init(&fctx->fence_ref);
 	if (!priv->uevent)
 		return;
 
@@ -230,6 +251,7 @@
 	else
 		fence_init(&fence->base, &nouveau_fence_ops_legacy,
 			   &fctx->lock, fctx->context, ++fctx->sequence);
+	kref_get(&fctx->fence_ref);
 
 	trace_fence_emit(&fence->base);
 	ret = fctx->emit(fence);
@@ -480,13 +502,22 @@
 	return true;
 }
 
+static void nouveau_fence_release(struct fence *f)
+{
+	struct nouveau_fence *fence = from_fence(f);
+	struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
+
+	kref_put(&fctx->fence_ref, nouveau_fence_context_put);
+	fence_free(&fence->base);
+}
+
 static const struct fence_ops nouveau_fence_ops_legacy = {
 	.get_driver_name = nouveau_fence_get_get_driver_name,
 	.get_timeline_name = nouveau_fence_get_timeline_name,
 	.enable_signaling = nouveau_fence_no_signaling,
 	.signaled = nouveau_fence_is_signaled,
 	.wait = nouveau_fence_wait_legacy,
-	.release = NULL
+	.release = nouveau_fence_release
 };
 
 static bool nouveau_fence_enable_signaling(struct fence *f)
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index a7dc537..943b0b1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -30,6 +30,8 @@
 
 struct nouveau_fence_chan {
 	spinlock_t lock;
+	struct kref fence_ref;
+
 	struct list_head pending;
 	struct list_head flip;
 
@@ -42,7 +44,7 @@
 
 	u32 sequence;
 	u32 context;
-	char name[24];
+	char name[32];
 
 	struct nvif_notify notify;
 	int notify_ref;
@@ -63,6 +65,7 @@
 
 void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *);
 void nouveau_fence_context_del(struct nouveau_fence_chan *);
+void nouveau_fence_context_free(struct nouveau_fence_chan *);
 
 int nv04_fence_create(struct nouveau_drm *);
 int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32);
diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c
index 4484131..f9859de 100644
--- a/drivers/gpu/drm/nouveau/nv04_fence.c
+++ b/drivers/gpu/drm/nouveau/nv04_fence.c
@@ -67,7 +67,7 @@
 	struct nv04_fence_chan *fctx = chan->fence;
 	nouveau_fence_context_del(&fctx->base);
 	chan->fence = NULL;
-	kfree(fctx);
+	nouveau_fence_context_free(&fctx->base);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c
index 737d066..5e1ea1c 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.c
+++ b/drivers/gpu/drm/nouveau/nv10_fence.c
@@ -63,7 +63,7 @@
 		nvif_object_fini(&fctx->head[i]);
 	nvif_object_fini(&fctx->sema);
 	chan->fence = NULL;
-	kfree(fctx);
+	nouveau_fence_context_free(&fctx->base);
 }
 
 int
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 1e5017f..41cd1a2 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -125,7 +125,7 @@
 	nouveau_bo_vma_del(priv->bo, &fctx->vma);
 	nouveau_fence_context_del(&fctx->base);
 	chan->fence = NULL;
-	kfree(fctx);
+	nouveau_fence_context_free(&fctx->base);
 }
 
 int