From 15e28df90169d92731a148fca7d948f804296fe6 Mon Sep 17 00:00:00 2001 From: jsg Date: Sun, 14 Feb 2021 03:42:55 +0000 Subject: [PATCH] correct drm work flush behaviour Don't set taskq to system_wq in INIT_WORK(). Test if taskq pointer is non-NULL before calling taskq_barrier() in flush functions. fixes a black screen on boot problem with 5.10.y drm using nano x1 bisected by jcs@ to 'drm/i915: Always flush the active worker before returning from the wait' --- sys/dev/pci/drm/drm_linux.c | 11 +++++++---- sys/dev/pci/drm/include/linux/workqueue.h | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c index d400d72ebc9..1fc4db15c86 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.77 2021/02/08 08:18:45 mpi Exp $ */ +/* $OpenBSD: drm_linux.c,v 1.78 2021/02/14 03:42:55 jsg Exp $ */ /* * Copyright (c) 2013 Jonathan Gray * Copyright (c) 2015, 2016 Mark Kettenis @@ -158,7 +158,8 @@ flush_workqueue(struct workqueue_struct *wq) if (cold) return; - taskq_barrier((struct taskq *)wq); + if (wq) + taskq_barrier((struct taskq *)wq); } bool @@ -167,7 +168,8 @@ flush_work(struct work_struct *work) if (cold) return false; - taskq_barrier(work->tq); + if (work->tq) + taskq_barrier(work->tq); return false; } @@ -184,7 +186,8 @@ flush_delayed_work(struct delayed_work *dwork) ret = true; } - taskq_barrier(dwork->tq ? dwork->tq : (struct taskq *)system_wq); + if (dwork->tq) + taskq_barrier(dwork->tq); return ret; } diff --git a/sys/dev/pci/drm/include/linux/workqueue.h b/sys/dev/pci/drm/include/linux/workqueue.h index e2a877d2ab3..703d2f06b9c 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.3 2020/06/08 04:48:15 jsg Exp $ */ +/* $OpenBSD: workqueue.h,v 1.4 2021/02/14 03:42:55 jsg Exp $ */ /* * Copyright (c) 2015 Mark Kettenis * @@ -79,7 +79,7 @@ typedef void (*work_func_t)(struct work_struct *); static inline void INIT_WORK(struct work_struct *work, work_func_t func) { - work->tq = (struct taskq *)system_wq; + work->tq = NULL; task_set(&work->task, (void (*)(void *))func, work); } @@ -139,6 +139,7 @@ INIT_DELAYED_WORK_ONSTACK(struct delayed_work *dwork, work_func_t func) static inline bool schedule_work(struct work_struct *work) { + work->tq = (struct taskq *)system_wq; return task_add(work->tq, &work->task); } -- 2.20.1