git: d7af180a301b - stable/13 - vt: Use a taskqueue to clear splash_cpu logos

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Fri, 28 Jan 2022 15:30:23 UTC
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=d7af180a301bd3d16b4f64860d22dacc0d32dc39

commit d7af180a301bd3d16b4f64860d22dacc0d32dc39
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-01-19 14:48:31 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-01-28 15:28:30 +0000

    vt: Use a taskqueue to clear splash_cpu logos
    
    vt_fini_logos() calls vtbuf_grow(), which reallocates the console
    window's buffer using malloc(M_WAITOK).  Because vt_fini_logos() is
    called via a callout, we end up panicking if INVARIANTS is enabled.
    
    Fix the problem simply by clearing the logos using a timed taskqueue.
    taskqueue_thread is formally allowed to sleep; of course, if we actually
    end up sleeping to satisfy the allocation, then we have bigger problems.
    
    PR:             260896
    Reviewed by:    emaste
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 6c7e4d72b1c964e4147831b45e0b312f6ed97cd2)
---
 sys/dev/vt/vt_cpulogos.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/sys/dev/vt/vt_cpulogos.c b/sys/dev/vt/vt_cpulogos.c
index 720e64585e16..c62b13a9097a 100644
--- a/sys/dev/vt/vt_cpulogos.c
+++ b/sys/dev/vt/vt_cpulogos.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/smp.h>
 #include <sys/systm.h>
+#include <sys/taskqueue.h>
 #include <sys/terminal.h>
 
 #include <dev/vt/vt.h>
@@ -43,7 +44,7 @@ extern const unsigned char vt_beastie_vga16[];
 extern const unsigned char vt_beastie2_vga16[];
 extern const unsigned char vt_orb_vga16[];
 
-static struct callout vt_splash_cpu_callout;
+static struct timeout_task vt_splash_cpu_fini_task;
 
 static inline unsigned char
 vt_vga2bsd(unsigned char vga)
@@ -149,7 +150,7 @@ vtterm_draw_cpu_logos(struct vt_device *vd)
 }
 
 static void
-vt_fini_logos(void *dummy __unused)
+vt_fini_logos(void *dummy __unused, int pending __unused)
 {
 	struct vt_device *vd;
 	struct vt_window *vw;
@@ -260,11 +261,12 @@ vt_init_logos(void *dummy)
 		vt_resume_flush_timer(vw, 0);
 	}
 
-	callout_init(&vt_splash_cpu_callout, 1);
-	callout_reset(&vt_splash_cpu_callout, vt_splash_cpu_duration * hz,
+	TIMEOUT_TASK_INIT(taskqueue_thread, &vt_splash_cpu_fini_task, 0,
 	    vt_fini_logos, NULL);
+	taskqueue_enqueue_timeout(taskqueue_thread, &vt_splash_cpu_fini_task,
+	    vt_splash_cpu_duration * hz);
 
 out:
 	VT_UNLOCK(vd);
 }
-SYSINIT(vt_logos, SI_SUB_CPU + 1, SI_ORDER_ANY, vt_init_logos, NULL);
+SYSINIT(vt_logos, SI_SUB_TASKQ, SI_ORDER_ANY, vt_init_logos, NULL);