summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/drm_linux.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2021-08-07 06:23:35 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2021-08-07 06:23:35 +0000
commitcec6d9780bee39ac5fc7720064aa807937fbd9bf (patch)
tree749f3d3062a4baee5018e8035aeaa6453cccf8dd /sys/dev/pci/drm/drm_linux.c
parent42c3116e048bd7addc6fbcc435b1e9a0106abe86 (diff)
use taskq_del_barrier() instead of taskq_barrier() when flushing work
prompted by jcs@ reporting a protection fault trap in drm_mode_rmfb_work_fn() while playing a youtube video in firefox on a kaby lake machine. He later saw the same trace on tiger lake. The arguments to drm_mode_rmfb_work_fn() are on the stack in drm_mode_rmfb() with flush_work() called before return. taskq_barrier() is only a barrier for running not queued tasks. I suspect the linux functions expect any previously queued work to complete not just any currently running work. I'm not sure if the difference matters in practice.
Diffstat (limited to 'sys/dev/pci/drm/drm_linux.c')
-rw-r--r--sys/dev/pci/drm/drm_linux.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c
index 72c53210f6f..5cc7459a583 100644
--- a/sys/dev/pci/drm/drm_linux.c
+++ b/sys/dev/pci/drm/drm_linux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_linux.c,v 1.82 2021/07/28 13:28:04 kettenis Exp $ */
+/* $OpenBSD: drm_linux.c,v 1.83 2021/08/07 06:23:34 jsg Exp $ */
/*
* Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
* Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -171,7 +171,7 @@ flush_work(struct work_struct *work)
return false;
if (work->tq)
- taskq_barrier(work->tq);
+ taskq_del_barrier(work->tq, &work->task);
return false;
}
@@ -189,7 +189,7 @@ flush_delayed_work(struct delayed_work *dwork)
}
if (dwork->tq)
- taskq_barrier(dwork->tq);
+ taskq_del_barrier(dwork->tq, &dwork->work.task);
return ret;
}
@@ -288,7 +288,7 @@ kthread_flush_work(struct kthread_work *work)
return;
if (work->tq)
- taskq_barrier(work->tq);
+ taskq_del_barrier(work->tq, &work->task);
}
void