Module Name:    src
Committed By:   riastradh
Date:           Sun Dec 19 12:44:58 UTC 2021

Modified Files:
        src/sys/arch/arm/ti: ti_fb.c ti_lcdc.c ti_lcdc.h

Log Message:
drm: Do the attach task dance for ti lcdc drm.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/ti/ti_fb.c \
    src/sys/arch/arm/ti/ti_lcdc.h
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/ti/ti_lcdc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/ti/ti_fb.c
diff -u src/sys/arch/arm/ti/ti_fb.c:1.2 src/sys/arch/arm/ti/ti_fb.c:1.3
--- src/sys/arch/arm/ti/ti_fb.c:1.2	Sun Dec 19 12:44:25 2021
+++ src/sys/arch/arm/ti/ti_fb.c	Sun Dec 19 12:44:57 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_fb.c,v 1.2 2021/12/19 12:44:25 riastradh Exp $ */
+/* $NetBSD: ti_fb.c,v 1.3 2021/12/19 12:44:57 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2015-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "opt_wsdisplay_compat.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ti_fb.c,v 1.2 2021/12/19 12:44:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ti_fb.c,v 1.3 2021/12/19 12:44:57 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -46,6 +46,8 @@ __KERNEL_RCSID(0, "$NetBSD: ti_fb.c,v 1.
 static int	ti_fb_match(device_t, cfdata_t, void *);
 static void	ti_fb_attach(device_t, device_t, void *);
 
+static void	tilcdc_fb_init(struct tilcdc_drm_task *);
+
 static bool	ti_fb_shutdown(device_t, int);
 
 struct ti_fb_softc {
@@ -53,6 +55,7 @@ struct ti_fb_softc {
 	device_t		sc_dev;
 	struct tilcdc_framebuffer *sc_fb;
 	struct tilcdcfb_attach_args sc_tfa;
+	struct tilcdc_drm_task	sc_attach_task;
 };
 
 static paddr_t	ti_fb_mmapfb(struct drmfb_softc *, off_t, int);
@@ -78,7 +81,6 @@ ti_fb_attach(device_t parent, device_t s
 {
 	struct ti_fb_softc * const sc = device_private(self);
 	struct tilcdcfb_attach_args * const tfa = aux;
-	int error;
 
 	sc->sc_dev = self;
 	sc->sc_tfa = *tfa;
@@ -87,6 +89,18 @@ ti_fb_attach(device_t parent, device_t s
 	aprint_naive("\n");
 	aprint_normal("\n");
 
+	tilcdc_task_init(&sc->sc_attach_task, &tilcdc_fb_init);
+	tilcdc_task_schedule(parent, &sc->sc_attach_task);
+}
+
+static void
+tilcdc_fb_init(struct tilcdc_drm_task *task)
+{
+	struct ti_fb_softc *sc = container_of(task, struct ti_fb_softc,
+	    sc_attach_task);
+	device_t self = sc->sc_dev;
+	struct tilcdcfb_attach_args * const tfa = &sc->sc_tfa;
+
 #ifdef WSDISPLAY_MULTICONS
 	prop_dictionary_t dict = device_properties(self);
 	const bool is_console = true;
@@ -101,6 +115,7 @@ ti_fb_attach(device_t parent, device_t s
 		.da_fb_linebytes = tfa->tfa_fb_linebytes,
 		.da_params = &tifb_drmfb_params,
 	};
+	int error;
 
 	error = drmfb_attach(&sc->sc_drmfb, &da);
 	if (error) {
Index: src/sys/arch/arm/ti/ti_lcdc.h
diff -u src/sys/arch/arm/ti/ti_lcdc.h:1.2 src/sys/arch/arm/ti/ti_lcdc.h:1.3
--- src/sys/arch/arm/ti/ti_lcdc.h:1.2	Sun Dec 19 12:44:25 2021
+++ src/sys/arch/arm/ti/ti_lcdc.h	Sun Dec 19 12:44:57 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_lcdc.h,v 1.2 2021/12/19 12:44:25 riastradh Exp $ */
+/* $NetBSD: ti_lcdc.h,v 1.3 2021/12/19 12:44:57 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcne...@invisible.ca>
@@ -29,6 +29,8 @@
 #ifndef _ARM_TI_TI_LCDC_H
 #define _ARM_TI_TI_LCDC_H
 
+#include <sys/workqueue.h>
+
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
@@ -74,6 +76,12 @@ struct tilcdc_softc {
 	struct clk		*sc_clk;
 	int			sc_phandle;
 
+	struct lwp			*sc_task_thread;
+	SIMPLEQ_HEAD(, tilcdc_drm_task)	sc_tasks;
+	struct workqueue		*sc_task_wq;
+
+	bool			sc_dev_registered;
+
 	struct tilcdc_crtc	sc_crtc;
 	struct tilcdc_encoder	sc_encoder;
 	struct tilcdc_vblank	sc_vbl;
@@ -99,6 +107,14 @@ struct tilcdcfb_attach_args {
 	uint32_t		tfa_fb_linebytes;
 };
 
+struct tilcdc_drm_task {
+	union {
+		SIMPLEQ_ENTRY(tilcdc_drm_task)	queue;
+		struct work			work;
+	}		tdt_u;
+	void		(*tdt_fn)(struct tilcdc_drm_task *);
+};
+
 #define tilcdc_private(ddev)		(ddev)->dev_private
 #define	to_tilcdc_framebuffer(x)	container_of(x, struct tilcdc_framebuffer, base)
 #define	to_tilcdc_crtc(x)		container_of(x, struct tilcdc_crtc, base)
@@ -108,4 +124,8 @@ struct tilcdcfb_attach_args {
 #define	WR4(sc, reg, val)		\
 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
 
+void	tilcdc_task_init(struct tilcdc_drm_task *,
+	    void (*)(struct tilcdc_drm_task *));
+void	tilcdc_task_schedule(device_t, struct tilcdc_drm_task *);
+
 #endif /* _ARM_TI_TI_LCDC_H */

Index: src/sys/arch/arm/ti/ti_lcdc.c
diff -u src/sys/arch/arm/ti/ti_lcdc.c:1.9 src/sys/arch/arm/ti/ti_lcdc.c:1.10
--- src/sys/arch/arm/ti/ti_lcdc.c:1.9	Sun Dec 19 12:44:25 2021
+++ src/sys/arch/arm/ti/ti_lcdc.c	Sun Dec 19 12:44:57 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_lcdc.c,v 1.9 2021/12/19 12:44:25 riastradh Exp $ */
+/* $NetBSD: ti_lcdc.c,v 1.10 2021/12/19 12:44:57 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ti_lcdc.c,v 1.9 2021/12/19 12:44:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ti_lcdc.c,v 1.10 2021/12/19 12:44:57 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -70,6 +70,8 @@ static void	tilcdc_attach(device_t, devi
 static int	tilcdc_load(struct drm_device *, unsigned long);
 static void	tilcdc_unload(struct drm_device *);
 
+static void	tilcdc_drm_task_work(struct work *, void *);
+
 static struct drm_driver tilcdc_driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM,
 	.dev_priv_size = 0,
@@ -415,6 +417,15 @@ tilcdc_attach(device_t parent, device_t 
 	sc->sc_ports.dp_ep_get_data = tilcdc_ep_get_data;
 	fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_ENCODER);
 
+	sc->sc_task_thread = NULL;
+	SIMPLEQ_INIT(&sc->sc_tasks);
+	if (workqueue_create(&sc->sc_task_wq, "tilcdcdrm",
+	    &tilcdc_drm_task_work, NULL, PRI_NONE, IPL_NONE, WQ_MPSAFE)) {
+		aprint_error_dev(self, "unable to create workqueue\n");
+		sc->sc_task_wq = NULL;
+		return;
+	}
+
 	sc->sc_ddev = drm_dev_alloc(driver, sc->sc_dev);
 	if (IS_ERR(sc->sc_ddev)) {
 		aprint_error_dev(self, "couldn't allocate DRM device\n");
@@ -426,17 +437,43 @@ tilcdc_attach(device_t parent, device_t 
 	sc->sc_ddev->dmat = sc->sc_ddev->bus_dmat;
 	sc->sc_ddev->dmat_subregion_p = false;
 
+	/*
+	 * Cause any tasks issued synchronously during attach to be
+	 * processed at the end of this function.
+	 */
+	sc->sc_task_thread = curlwp;
+
 	error = -drm_dev_register(sc->sc_ddev, 0);
 	if (error) {
 		drm_dev_put(sc->sc_ddev);
+		sc->sc_ddev = NULL;
 		aprint_error_dev(self, "couldn't register DRM device: %d\n",
 		    error);
-		return;
+		goto out;
 	}
+	sc->sc_dev_registered = true;
 
 	aprint_normal_dev(self, "initialized %s %d.%d.%d %s on minor %d\n",
 	    driver->name, driver->major, driver->minor, driver->patchlevel,
 	    driver->date, sc->sc_ddev->primary->index);
+
+	/*
+	 * Process asynchronous tasks queued synchronously during
+	 * attach.  This will be for display detection to attach a
+	 * framebuffer, so we have the opportunity for a console device
+	 * to attach before autoconf has completed, in time for init(8)
+	 * to find that console without panicking.
+	 */
+	while (!SIMPLEQ_EMPTY(&sc->sc_tasks)) {
+		struct tilcdc_drm_task *const task =
+		    SIMPLEQ_FIRST(&sc->sc_tasks);
+
+		SIMPLEQ_REMOVE_HEAD(&sc->sc_tasks, tdt_u.queue);
+		(*task->tdt_fn)(task);
+	}
+
+out:	/* Cause any subesquent tasks to be processed by the workqueue.  */
+	atomic_store_relaxed(&sc->sc_task_thread, NULL);
 }
 
 static int
@@ -630,3 +667,31 @@ tilcdc_unload(struct drm_device *ddev)
 
 	drm_mode_config_cleanup(ddev);
 }
+
+static void
+tilcdc_drm_task_work(struct work *work, void *cookie)
+{
+	struct tilcdc_drm_task *task = container_of(work,
+	    struct tilcdc_drm_task, tdt_u.work);
+
+	(*task->tdt_fn)(task);
+}
+
+void
+tilcdc_task_init(struct tilcdc_drm_task *task,
+    void (*fn)(struct tilcdc_drm_task *))
+{
+
+	task->tdt_fn = fn;
+}
+
+void
+tilcdc_task_schedule(device_t self, struct tilcdc_drm_task *task)
+{
+	struct tilcdc_softc *sc = device_private(self);
+
+	if (atomic_load_relaxed(&sc->sc_task_thread) == curlwp)
+		SIMPLEQ_INSERT_TAIL(&sc->sc_tasks, task, tdt_u.queue);
+	else
+		workqueue_enqueue(sc->sc_task_wq, &task->tdt_u.work, NULL);
+}

Reply via email to