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