Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/nvidia drm: Do the attach task dance for tegra ...
details: https://anonhg.NetBSD.org/src/rev/a6a5b386c9f2
branches: trunk
changeset: 1029025:a6a5b386c9f2
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 12:44:50 2021 +0000
description:
drm: Do the attach task dance for tegra drm.
diffstat:
sys/arch/arm/nvidia/tegra_drm.c | 70 ++++++++++++++++++++++++++++++++++++++--
sys/arch/arm/nvidia/tegra_drm.h | 22 ++++++++++++-
sys/arch/arm/nvidia/tegra_fb.c | 20 +++++++++-
3 files changed, 104 insertions(+), 8 deletions(-)
diffs (244 lines):
diff -r 564d411b5f73 -r a6a5b386c9f2 sys/arch/arm/nvidia/tegra_drm.c
--- a/sys/arch/arm/nvidia/tegra_drm.c Sun Dec 19 12:44:43 2021 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.c Sun Dec 19 12:44:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.c,v 1.13 2021/12/19 12:44:14 riastradh Exp $ */
+/* $NetBSD: tegra_drm.c,v 1.14 2021/12/19 12:44:50 riastradh Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.13 2021/12/19 12:44:14 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.14 2021/12/19 12:44:50 riastradh Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -55,6 +55,8 @@
static int tegra_drm_load(struct drm_device *, unsigned long);
static void tegra_drm_unload(struct drm_device *);
+static void tegra_drm_task_work(struct work *, void *);
+
static struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM,
.dev_priv_size = 0,
@@ -123,6 +125,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, "tegradrm",
+ &tegra_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");
aprint_normal("\n");
@@ -204,19 +214,43 @@
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);
- return;
+ /*
+ * 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 tegra_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
@@ -246,3 +280,31 @@
drm_mode_config_cleanup(ddev);
}
+
+static void
+tegra_drm_task_work(struct work *work, void *cookie)
+{
+ struct tegra_drm_task *task = container_of(work, struct tegra_drm_task,
+ tdt_u.work);
+
+ (*task->tdt_fn)(task);
+}
+
+void
+tegra_task_init(struct tegra_drm_task *task,
+ void (*fn)(struct tegra_drm_task *))
+{
+
+ task->tdt_fn = fn;
+}
+
+void
+tegra_task_schedule(device_t self, struct tegra_drm_task *task)
+{
+ struct tegra_drm_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);
+}
diff -r 564d411b5f73 -r a6a5b386c9f2 sys/arch/arm/nvidia/tegra_drm.h
--- a/sys/arch/arm/nvidia/tegra_drm.h Sun Dec 19 12:44:43 2021 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.h Sun Dec 19 12:44:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.h,v 1.10 2021/12/19 12:44:14 riastradh Exp $ */
+/* $NetBSD: tegra_drm.h,v 1.11 2021/12/19 12:44:50 riastradh Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,6 +29,8 @@
#ifndef _ARM_TEGRA_DRM_H
#define _ARM_TEGRA_DRM_H
+#include <sys/workqueue.h>
+
#include <drm/drm_encoder.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
@@ -54,6 +56,12 @@
int sc_phandle;
+ struct lwp *sc_task_thread;
+ SIMPLEQ_HEAD(, tegra_drm_task) sc_tasks;
+ struct workqueue *sc_task_wq;
+
+ bool sc_dev_registered;
+
struct clk *sc_clk_host1x;
struct fdtbus_reset *sc_rst_host1x;
@@ -124,6 +132,14 @@
struct drm_fb_helper helper;
};
+struct tegra_drm_task {
+ union {
+ SIMPLEQ_ENTRY(tegra_drm_task) queue;
+ struct work work;
+ } tdt_u;
+ void (*tdt_fn)(struct tegra_drm_task *);
+};
+
#define HDMI_READ(enc, reg) \
bus_space_read_4((enc)->bst, (enc)->bsh, (reg))
#define HDMI_WRITE(enc, reg, val) \
@@ -155,4 +171,8 @@
int tegra_drm_framebuffer_init(struct drm_device *,
struct tegra_framebuffer *);
+void tegra_task_init(struct tegra_drm_task *,
+ void (*)(struct tegra_drm_task *));
+void tegra_task_schedule(device_t, struct tegra_drm_task *);
+
#endif /* _ARM_TEGRA_DRM_H */
diff -r 564d411b5f73 -r a6a5b386c9f2 sys/arch/arm/nvidia/tegra_fb.c
--- a/sys/arch/arm/nvidia/tegra_fb.c Sun Dec 19 12:44:43 2021 +0000
+++ b/sys/arch/arm/nvidia/tegra_fb.c Sun Dec 19 12:44:50 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_fb.c,v 1.5 2021/12/19 12:44:14 riastradh Exp $ */
+/* $NetBSD: tegra_fb.c,v 1.6 2021/12/19 12:44:50 riastradh Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_fb.c,v 1.5 2021/12/19 12:44:14 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_fb.c,v 1.6 2021/12/19 12:44:50 riastradh Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -42,6 +42,8 @@
static int tegra_fb_match(device_t, cfdata_t, void *);
static void tegra_fb_attach(device_t, device_t, void *);
+static void tegra_fb_init(struct tegra_drm_task *);
+
static bool tegra_fb_shutdown(device_t, int);
struct tegra_fb_softc {
@@ -50,6 +52,7 @@
struct tegra_drm_softc *sc_drm;
struct tegra_drmfb_attach_args sc_tfa;
struct tegra_framebuffer *sc_fb;
+ struct tegra_drm_task sc_attach_task;
};
static paddr_t tegra_fb_mmapfb(struct drmfb_softc *, off_t, int);
@@ -77,7 +80,6 @@
struct tegra_fb_softc * const sc = device_private(self);
struct tegra_drm_softc * const drmsc = device_private(parent);
struct tegra_drmfb_attach_args * const tfa = aux;
- int error;
sc->sc_dev = self;
sc->sc_drm = drmsc;
@@ -87,6 +89,17 @@
aprint_naive("\n");
aprint_normal("\n");
+ tegra_task_init(&sc->sc_attach_task, &tegra_fb_init);
+ tegra_task_schedule(parent, &sc->sc_attach_task);
+}
+
+static void
+tegra_fb_init(struct tegra_drm_task *task)
+{
+ struct tegra_fb_softc *sc = container_of(task, struct tegra_fb_softc,
+ sc_attach_task);
+ device_t self = sc->sc_dev;
+ struct tegra_drmfb_attach_args * const tfa = &sc->sc_tfa;
const struct drmfb_attach_args da = {
.da_dev = self,
.da_fb_helper = tfa->tfa_fb_helper,
@@ -95,6 +108,7 @@
.da_fb_linebytes = tfa->tfa_fb_linebytes,
.da_params = &tegrafb_drmfb_params,
};
+ int error;
error = drmfb_attach(&sc->sc_drmfb, &da);
if (error) {
Home |
Main Index |
Thread Index |
Old Index