Skip to content

Commit 39126ab

Browse files
committed
nouveau: offload fence uevents work to workqueue
This should break the deadlock between the fctx lock and the irq lock. This offloads the processing off the work from the irq into a workqueue. Cc: linux-stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/576237/
1 parent b5e69be commit 39126ab

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

drivers/gpu/drm/nouveau/nouveau_fence.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error)
103103
void
104104
nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
105105
{
106+
cancel_work_sync(&fctx->uevent_work);
106107
nouveau_fence_context_kill(fctx, 0);
107108
nvif_event_dtor(&fctx->event);
108109
fctx->dead = 1;
@@ -145,12 +146,13 @@ nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fc
145146
return drop;
146147
}
147148

148-
static int
149-
nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc)
149+
static void
150+
nouveau_fence_uevent_work(struct work_struct *work)
150151
{
151-
struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event);
152+
struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan,
153+
uevent_work);
152154
unsigned long flags;
153-
int ret = NVIF_EVENT_KEEP;
155+
int drop = 0;
154156

155157
spin_lock_irqsave(&fctx->lock, flags);
156158
if (!list_empty(&fctx->pending)) {
@@ -160,11 +162,20 @@ nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc
160162
fence = list_entry(fctx->pending.next, typeof(*fence), head);
161163
chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
162164
if (nouveau_fence_update(chan, fctx))
163-
ret = NVIF_EVENT_DROP;
165+
drop = 1;
164166
}
167+
if (drop)
168+
nvif_event_block(&fctx->event);
169+
165170
spin_unlock_irqrestore(&fctx->lock, flags);
171+
}
166172

167-
return ret;
173+
static int
174+
nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc)
175+
{
176+
struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event);
177+
schedule_work(&fctx->uevent_work);
178+
return NVIF_EVENT_KEEP;
168179
}
169180

170181
void
@@ -178,6 +189,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
178189
} args;
179190
int ret;
180191

192+
INIT_WORK(&fctx->uevent_work, nouveau_fence_uevent_work);
181193
INIT_LIST_HEAD(&fctx->flip);
182194
INIT_LIST_HEAD(&fctx->pending);
183195
spin_lock_init(&fctx->lock);

drivers/gpu/drm/nouveau/nouveau_fence.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct nouveau_fence_chan {
4444
u32 context;
4545
char name[32];
4646

47+
struct work_struct uevent_work;
4748
struct nvif_event event;
4849
int notify_ref, dead, killed;
4950
};

0 commit comments

Comments
 (0)