Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi sunxi/drm: Use an explicit task queue to ...



details:   https://anonhg.NetBSD.org/src/rev/179677b71283
branches:  trunk
changeset: 1028915:179677b71283
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Dec 19 12:28:20 2021 +0000

description:
sunxi/drm: Use an explicit task queue to avoid config_defer pitfalls.

Same as the other drm drivers.

diffstat:

 sys/arch/arm/sunxi/sunxi_drm.c |  69 ++++++++++++++++++++++++++++++++++++++++-
 sys/arch/arm/sunxi/sunxi_drm.h |  23 +++++++++++++-
 sys/arch/arm/sunxi/sunxi_fb.c  |  16 ++++++---
 3 files changed, 98 insertions(+), 10 deletions(-)

diffs (227 lines):

diff -r f93cb7aa355f -r 179677b71283 sys/arch/arm/sunxi/sunxi_drm.c
--- a/sys/arch/arm/sunxi/sunxi_drm.c    Sun Dec 19 12:28:12 2021 +0000
+++ b/sys/arch/arm/sunxi/sunxi_drm.c    Sun Dec 19 12:28:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_drm.c,v 1.21 2021/12/19 11:25:48 riastradh Exp $ */
+/* $NetBSD: sunxi_drm.c,v 1.22 2021/12/19 12:28:20 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_drm.c,v 1.21 2021/12/19 11:25:48 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_drm.c,v 1.22 2021/12/19 12:28:20 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -91,6 +91,8 @@
 static int     sunxi_drm_load(struct drm_device *, unsigned long);
 static void    sunxi_drm_unload(struct drm_device *);
 
+static void    sunxi_drm_task_work(struct work *, void *);
+
 static struct drm_driver sunxi_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .dev_priv_size = 0,
@@ -140,6 +142,14 @@
        sc->sc_dmat = faa->faa_dmat;
        sc->sc_bst = faa->faa_bst;
        sc->sc_phandle = faa->faa_phandle;
+       sc->sc_task_thread = NULL;
+       SIMPLEQ_INIT(&sc->sc_tasks);
+       if (workqueue_create(&sc->sc_task_wq, "sunxidrm",
+               &sunxi_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;
+       }
 
        aprint_naive("\n");
 
@@ -173,16 +183,41 @@
        struct drm_driver * const driver = &sunxi_drm_driver;
        int error;
 
+       /*
+        * 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) {
                aprint_error_dev(dev, "couldn't register DRM device: %d\n",
                    error);
-               return;
+               goto out;
        }
+       sc->sc_dev_registered = true;
 
        aprint_normal_dev(dev, "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 sunxi_drm_task *const task =
+                   SIMPLEQ_FIRST(&sc->sc_tasks);
+
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_tasks, sdt_u.queue);
+               (*task->sdt_fn)(task);
+       }
+
+out:   /* Cause any subesquent tasks to be processed by the workqueue.  */
+       atomic_store_relaxed(&sc->sc_task_thread, NULL);
 }
 
 static vmem_t *
@@ -532,3 +567,31 @@
 
        return NULL;
 }
+
+static void
+sunxi_drm_task_work(struct work *work, void *cookie)
+{
+       struct sunxi_drm_task *task = container_of(work, struct sunxi_drm_task,
+           sdt_u.work);
+
+       (*task->sdt_fn)(task);
+}
+
+void
+sunxi_task_init(struct sunxi_drm_task *task,
+    void (*fn)(struct sunxi_drm_task *))
+{
+
+       task->sdt_fn = fn;
+}
+
+void
+sunxi_task_schedule(device_t self, struct sunxi_drm_task *task)
+{
+       struct sunxi_drm_softc *sc = device_private(self);
+
+       if (atomic_load_relaxed(&sc->sc_task_thread) == curlwp)
+               SIMPLEQ_INSERT_TAIL(&sc->sc_tasks, task, sdt_u.queue);
+       else
+               workqueue_enqueue(sc->sc_task_wq, &task->sdt_u.work, NULL);
+}
diff -r f93cb7aa355f -r 179677b71283 sys/arch/arm/sunxi/sunxi_drm.h
--- a/sys/arch/arm/sunxi/sunxi_drm.h    Sun Dec 19 12:28:12 2021 +0000
+++ b/sys/arch/arm/sunxi/sunxi_drm.h    Sun Dec 19 12:28:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_drm.h,v 1.2 2019/02/04 12:10:13 jmcneill Exp $ */
+/* $NetBSD: sunxi_drm.h,v 1.3 2021/12/19 12:28:20 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,6 +29,9 @@
 #ifndef _ARM_SUNXI_DRM_H
 #define _ARM_SUNXI_DRM_H
 
+#include <sys/queue.h>
+#include <sys/workqueue.h>
+
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
@@ -62,6 +65,12 @@
 
        int                     sc_phandle;
 
+       struct lwp                      *sc_task_thread;
+       SIMPLEQ_HEAD(, sunxi_drm_task)  sc_tasks;
+       struct workqueue                *sc_task_wq;
+
+       bool                    sc_dev_registered;
+
        struct sunxi_drm_vblank sc_vbl[SUNXI_DRM_MAX_CRTC];
 };
 
@@ -90,10 +99,22 @@
        uint32_t                sfa_fb_linebytes;
 };
 
+struct sunxi_drm_task {
+       union {
+               SIMPLEQ_ENTRY(sunxi_drm_task)   queue;
+               struct work                     work;
+       }               sdt_u;
+       void            (*sdt_fn)(struct sunxi_drm_task *);
+};
+
 #define sunxi_drm_private(ddev)                (ddev)->dev_private
 #define        to_sunxi_drm_framebuffer(x)     container_of(x, struct sunxi_drm_framebuffer, base)
 
 int    sunxi_drm_register_endpoint(int, struct fdt_endpoint *);
 struct drm_device *sunxi_drm_endpoint_device(struct fdt_endpoint *);
 
+void   sunxi_task_init(struct sunxi_drm_task *,
+           void (*)(struct sunxi_drm_task *));
+void   sunxi_task_schedule(device_t, struct sunxi_drm_task *);
+
 #endif /* _ARM_SUNXI_DRM_H */
diff -r f93cb7aa355f -r 179677b71283 sys/arch/arm/sunxi/sunxi_fb.c
--- a/sys/arch/arm/sunxi/sunxi_fb.c     Sun Dec 19 12:28:12 2021 +0000
+++ b/sys/arch/arm/sunxi/sunxi_fb.c     Sun Dec 19 12:28:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_fb.c,v 1.6 2021/12/19 11:25:25 riastradh Exp $ */
+/* $NetBSD: sunxi_fb.c,v 1.7 2021/12/19 12:28:20 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2015-2019 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_wsdisplay_compat.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_fb.c,v 1.6 2021/12/19 11:25:25 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_fb.c,v 1.7 2021/12/19 12:28:20 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,7 +45,7 @@
 static int     sunxi_fb_match(device_t, cfdata_t, void *);
 static void    sunxi_fb_attach(device_t, device_t, void *);
 
-static void    sunxi_fb_init(device_t);
+static void    sunxi_fb_init(struct sunxi_drm_task *);
 
 static bool    sunxi_fb_shutdown(device_t, int);
 
@@ -55,6 +55,7 @@
        struct sunxi_drm_softc  *sc_drm;
        struct sunxi_drm_framebuffer *sc_fb;
        struct sunxi_drmfb_attach_args sc_sfa;
+       struct sunxi_drm_task   sc_attach_task;
 };
 
 static paddr_t sunxi_fb_mmapfb(struct drmfb_softc *, off_t, int);
@@ -96,13 +97,16 @@
        const bool is_console = true;
        prop_dictionary_set_bool(dict, "is_console", is_console);
 #endif
-       config_defer(self, sunxi_fb_init);
+       sunxi_task_init(&sc->sc_attach_task, &sunxi_fb_init);
+       sunxi_task_schedule(parent, &sc->sc_attach_task);
 }
 
 static void
-sunxi_fb_init(device_t dev)
+sunxi_fb_init(struct sunxi_drm_task *task)
 {
-       struct sunxi_fb_softc * const sc = device_private(dev);
+       struct sunxi_fb_softc * const sc =
+           container_of(task, struct sunxi_fb_softc, sc_attach_task);
+       device_t dev = sc->sc_dev;
        struct sunxi_drmfb_attach_args * const sfa = &sc->sc_sfa;
        int error;
 



Home | Main Index | Thread Index | Old Index