diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-08-07 06:23:35 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-08-07 06:23:35 +0000 |
commit | cec6d9780bee39ac5fc7720064aa807937fbd9bf (patch) | |
tree | 749f3d3062a4baee5018e8035aeaa6453cccf8dd /sys/dev/pci/drm/drm_linux.c | |
parent | 42c3116e048bd7addc6fbcc435b1e9a0106abe86 (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.c | 8 |
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 |