summaryrefslogtreecommitdiff
path: root/sys
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
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')
-rw-r--r--sys/dev/pci/drm/drm_linux.c8
-rw-r--r--sys/dev/pci/drm/include/linux/irq_work.h4
2 files changed, 6 insertions, 6 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
diff --git a/sys/dev/pci/drm/include/linux/irq_work.h b/sys/dev/pci/drm/include/linux/irq_work.h
index f9df2099cd9..30daa6f6b39 100644
--- a/sys/dev/pci/drm/include/linux/irq_work.h
+++ b/sys/dev/pci/drm/include/linux/irq_work.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: irq_work.h,v 1.3 2021/07/07 02:38:36 jsg Exp $ */
+/* $OpenBSD: irq_work.h,v 1.4 2021/08/07 06:23:34 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -49,7 +49,7 @@ irq_work_queue(struct irq_work *work)
static inline void
irq_work_sync(struct irq_work *work)
{
- taskq_barrier(work->tq);
+ taskq_del_barrier(work->tq, &work->task);
}
#endif