summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2021-05-17 00:17:27 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2021-05-17 00:17:27 +0000
commit4f439bc370e9c3aae03cdd731f6f7e8700db4501 (patch)
tree1e12aa2d403ed8b22a93a4dab447df00c4f8e05c /sys/dev/pci
parent274991700c5f6c93939fded8d93e1480a10ff658 (diff)
return early if work is cancelled before being scheduled
cheloha@ noticed that task_del(9) was being called with a NULL taskq from inteldrm(4), which was not noticed as the function returns early from testing a flag in the task. This situation occurs when work is cancelled before it is scheduled. ok kettenis@ cheloha@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/drm/include/linux/workqueue.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/dev/pci/drm/include/linux/workqueue.h b/sys/dev/pci/drm/include/linux/workqueue.h
index 703d2f06b9c..a0c7134c88e 100644
--- a/sys/dev/pci/drm/include/linux/workqueue.h
+++ b/sys/dev/pci/drm/include/linux/workqueue.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: workqueue.h,v 1.4 2021/02/14 03:42:55 jsg Exp $ */
+/* $OpenBSD: workqueue.h,v 1.5 2021/05/17 00:17:26 jsg Exp $ */
/*
* Copyright (c) 2015 Mark Kettenis
*
@@ -95,7 +95,8 @@ queue_work(struct workqueue_struct *wq, struct work_struct *work)
static inline void
cancel_work_sync(struct work_struct *work)
{
- task_del(work->tq, &work->task);
+ if (work->tq != NULL)
+ task_del(work->tq, &work->task);
}
#define work_pending(work) task_pending(&(work)->task)
@@ -169,6 +170,8 @@ mod_delayed_work(struct workqueue_struct *wq,
static inline bool
cancel_delayed_work(struct delayed_work *dwork)
{
+ if (dwork->tq == NULL)
+ return false;
if (timeout_del(&dwork->to))
return true;
return task_del(dwork->tq, &dwork->work.task);
@@ -177,6 +180,8 @@ cancel_delayed_work(struct delayed_work *dwork)
static inline bool
cancel_delayed_work_sync(struct delayed_work *dwork)
{
+ if (dwork->tq == NULL)
+ return false;
if (timeout_del(&dwork->to))
return true;
return task_del(dwork->tq, &dwork->work.task);