drm/nouveau: assign fence_chan->name correctly
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Mon, 29 Sep 2014 08:06:18 +0000 (10:06 +0200)
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>
Tue, 30 Sep 2014 12:04:00 +0000 (14:04 +0200)
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>
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/nouveau/nv04_fence.c
drivers/gpu/drm/nouveau/nv10_fence.c
drivers/gpu/drm/nouveau/nv84_fence.c

index dfd0b9e..dba1f7e 100644 (file)
@@ -100,6 +100,18 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
        spin_unlock_irq(&fctx->lock);
 }
 
+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)
 {
@@ -141,6 +153,7 @@ void
 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 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
        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 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
        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 @@ static bool nouveau_fence_no_signaling(struct fence *f)
        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)
index a7dc537..943b0b1 100644 (file)
@@ -30,6 +30,8 @@ int  nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool excl
 
 struct nouveau_fence_chan {
        spinlock_t lock;
+       struct kref fence_ref;
+
        struct list_head pending;
        struct list_head flip;
 
@@ -42,7 +44,7 @@ struct nouveau_fence_chan {
 
        u32 sequence;
        u32 context;
-       char name[24];
+       char name[32];
 
        struct nvif_notify notify;
        int notify_ref;
@@ -63,6 +65,7 @@ struct nouveau_fence_priv {
 
 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);
index 4484131..f9859de 100644 (file)
@@ -67,7 +67,7 @@ nv04_fence_context_del(struct nouveau_channel *chan)
        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
index 737d066..5e1ea1c 100644 (file)
@@ -63,7 +63,7 @@ nv10_fence_context_del(struct nouveau_channel *chan)
                nvif_object_fini(&fctx->head[i]);
        nvif_object_fini(&fctx->sema);
        chan->fence = NULL;
-       kfree(fctx);
+       nouveau_fence_context_free(&fctx->base);
 }
 
 int
index 1e5017f..41cd1a2 100644 (file)
@@ -125,7 +125,7 @@ nv84_fence_context_del(struct nouveau_channel *chan)
        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