diff options
author | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2014-09-29 10:06:18 +0200 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2014-09-30 14:04:00 +0200 |
commit | 15a996bbb6978ae21c497aeadfe20deca6ddd07a (patch) | |
tree | 208bcce51bf6bfa6b1d831a15ced5a32a0c9e5b0 | |
parent | e3be4c230dfadf79567a245505a47a90db97f968 (diff) | |
download | linux-15a996bbb6978ae21c497aeadfe20deca6ddd07a.tar.bz2 |
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>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv10_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_fence.c | 2 |
5 files changed, 39 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index dfd0b9ed4195..dba1f7e15cb6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -101,6 +101,18 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) } 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 @@ 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) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index a7dc5375c320..943b0b17b1fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index 4484131d826a..f9859deb108a 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 737d066ffc60..5e1ea1cdce75 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 1e5017f905db..41cd1a28d89f 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -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 |