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); +}