diff options
author | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2014-09-29 04:06:18 -0400 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2014-09-30 08:04:00 -0400 |
commit | 15a996bbb6978ae21c497aeadfe20deca6ddd07a (patch) | |
tree | 208bcce51bf6bfa6b1d831a15ced5a32a0c9e5b0 /drivers/gpu/drm/nouveau | |
parent | e3be4c230dfadf79567a245505a47a90db97f968 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-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) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | static void | 103 | static void |
104 | nouveau_fence_context_put(struct kref *fence_ref) | ||
105 | { | ||
106 | kfree(container_of(fence_ref, struct nouveau_fence_chan, fence_ref)); | ||
107 | } | ||
108 | |||
109 | void | ||
110 | nouveau_fence_context_free(struct nouveau_fence_chan *fctx) | ||
111 | { | ||
112 | kref_put(&fctx->fence_ref, nouveau_fence_context_put); | ||
113 | } | ||
114 | |||
115 | static void | ||
104 | nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) | 116 | nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) |
105 | { | 117 | { |
106 | struct nouveau_fence *fence; | 118 | struct nouveau_fence *fence; |
@@ -141,6 +153,7 @@ void | |||
141 | nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) | 153 | nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) |
142 | { | 154 | { |
143 | struct nouveau_fence_priv *priv = (void*)chan->drm->fence; | 155 | struct nouveau_fence_priv *priv = (void*)chan->drm->fence; |
156 | struct nouveau_cli *cli = (void *)nvif_client(chan->object); | ||
144 | int ret; | 157 | int ret; |
145 | 158 | ||
146 | INIT_LIST_HEAD(&fctx->flip); | 159 | INIT_LIST_HEAD(&fctx->flip); |
@@ -148,6 +161,14 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha | |||
148 | spin_lock_init(&fctx->lock); | 161 | spin_lock_init(&fctx->lock); |
149 | fctx->context = priv->context_base + chan->chid; | 162 | fctx->context = priv->context_base + chan->chid; |
150 | 163 | ||
164 | if (chan == chan->drm->cechan) | ||
165 | strcpy(fctx->name, "copy engine channel"); | ||
166 | else if (chan == chan->drm->channel) | ||
167 | strcpy(fctx->name, "generic kernel channel"); | ||
168 | else | ||
169 | strcpy(fctx->name, nvkm_client(&cli->base)->name); | ||
170 | |||
171 | kref_init(&fctx->fence_ref); | ||
151 | if (!priv->uevent) | 172 | if (!priv->uevent) |
152 | return; | 173 | return; |
153 | 174 | ||
@@ -230,6 +251,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) | |||
230 | else | 251 | else |
231 | fence_init(&fence->base, &nouveau_fence_ops_legacy, | 252 | fence_init(&fence->base, &nouveau_fence_ops_legacy, |
232 | &fctx->lock, fctx->context, ++fctx->sequence); | 253 | &fctx->lock, fctx->context, ++fctx->sequence); |
254 | kref_get(&fctx->fence_ref); | ||
233 | 255 | ||
234 | trace_fence_emit(&fence->base); | 256 | trace_fence_emit(&fence->base); |
235 | ret = fctx->emit(fence); | 257 | ret = fctx->emit(fence); |
@@ -480,13 +502,22 @@ static bool nouveau_fence_no_signaling(struct fence *f) | |||
480 | return true; | 502 | return true; |
481 | } | 503 | } |
482 | 504 | ||
505 | static void nouveau_fence_release(struct fence *f) | ||
506 | { | ||
507 | struct nouveau_fence *fence = from_fence(f); | ||
508 | struct nouveau_fence_chan *fctx = nouveau_fctx(fence); | ||
509 | |||
510 | kref_put(&fctx->fence_ref, nouveau_fence_context_put); | ||
511 | fence_free(&fence->base); | ||
512 | } | ||
513 | |||
483 | static const struct fence_ops nouveau_fence_ops_legacy = { | 514 | static const struct fence_ops nouveau_fence_ops_legacy = { |
484 | .get_driver_name = nouveau_fence_get_get_driver_name, | 515 | .get_driver_name = nouveau_fence_get_get_driver_name, |
485 | .get_timeline_name = nouveau_fence_get_timeline_name, | 516 | .get_timeline_name = nouveau_fence_get_timeline_name, |
486 | .enable_signaling = nouveau_fence_no_signaling, | 517 | .enable_signaling = nouveau_fence_no_signaling, |
487 | .signaled = nouveau_fence_is_signaled, | 518 | .signaled = nouveau_fence_is_signaled, |
488 | .wait = nouveau_fence_wait_legacy, | 519 | .wait = nouveau_fence_wait_legacy, |
489 | .release = NULL | 520 | .release = nouveau_fence_release |
490 | }; | 521 | }; |
491 | 522 | ||
492 | static bool nouveau_fence_enable_signaling(struct fence *f) | 523 | 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 | |||
30 | 30 | ||
31 | struct nouveau_fence_chan { | 31 | struct nouveau_fence_chan { |
32 | spinlock_t lock; | 32 | spinlock_t lock; |
33 | struct kref fence_ref; | ||
34 | |||
33 | struct list_head pending; | 35 | struct list_head pending; |
34 | struct list_head flip; | 36 | struct list_head flip; |
35 | 37 | ||
@@ -42,7 +44,7 @@ struct nouveau_fence_chan { | |||
42 | 44 | ||
43 | u32 sequence; | 45 | u32 sequence; |
44 | u32 context; | 46 | u32 context; |
45 | char name[24]; | 47 | char name[32]; |
46 | 48 | ||
47 | struct nvif_notify notify; | 49 | struct nvif_notify notify; |
48 | int notify_ref; | 50 | int notify_ref; |
@@ -63,6 +65,7 @@ struct nouveau_fence_priv { | |||
63 | 65 | ||
64 | void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *); | 66 | void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *); |
65 | void nouveau_fence_context_del(struct nouveau_fence_chan *); | 67 | void nouveau_fence_context_del(struct nouveau_fence_chan *); |
68 | void nouveau_fence_context_free(struct nouveau_fence_chan *); | ||
66 | 69 | ||
67 | int nv04_fence_create(struct nouveau_drm *); | 70 | int nv04_fence_create(struct nouveau_drm *); |
68 | int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32); | 71 | 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) | |||
67 | struct nv04_fence_chan *fctx = chan->fence; | 67 | struct nv04_fence_chan *fctx = chan->fence; |
68 | nouveau_fence_context_del(&fctx->base); | 68 | nouveau_fence_context_del(&fctx->base); |
69 | chan->fence = NULL; | 69 | chan->fence = NULL; |
70 | kfree(fctx); | 70 | nouveau_fence_context_free(&fctx->base); |
71 | } | 71 | } |
72 | 72 | ||
73 | static int | 73 | 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) | |||
63 | nvif_object_fini(&fctx->head[i]); | 63 | nvif_object_fini(&fctx->head[i]); |
64 | nvif_object_fini(&fctx->sema); | 64 | nvif_object_fini(&fctx->sema); |
65 | chan->fence = NULL; | 65 | chan->fence = NULL; |
66 | kfree(fctx); | 66 | nouveau_fence_context_free(&fctx->base); |
67 | } | 67 | } |
68 | 68 | ||
69 | int | 69 | 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) | |||
125 | nouveau_bo_vma_del(priv->bo, &fctx->vma); | 125 | nouveau_bo_vma_del(priv->bo, &fctx->vma); |
126 | nouveau_fence_context_del(&fctx->base); | 126 | nouveau_fence_context_del(&fctx->base); |
127 | chan->fence = NULL; | 127 | chan->fence = NULL; |
128 | kfree(fctx); | 128 | nouveau_fence_context_free(&fctx->base); |
129 | } | 129 | } |
130 | 130 | ||
131 | int | 131 | int |