Because of the way the Linux code behind apldrm(4) is structured it may
authorkettenis <kettenis@openbsd.org>
Mon, 29 Jan 2024 14:52:25 +0000 (14:52 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 29 Jan 2024 14:52:25 +0000 (14:52 +0000)
fail to create a framebuffer without propagating an error to its callers.
Prevent a kernel panic by explicitly checking that we have a framebuffer.
To prevent us ending up with no framebuffer at all, only claim the
framebuffer in apldrm(4) when we actually created our own.  Delay the
attach of simplefb(4) such that we check whether someone else claimed its
framebuffer until apldrm(4) has done its thing.

tested by robert@
ok jsg@

sys/arch/arm64/dev/mainbus.c
sys/dev/pci/drm/apple/apldrm.c

index 495a4ca..d3b8bcb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.28 2023/08/10 19:29:32 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.29 2024/01/29 14:52:25 kettenis Exp $ */
 /*
  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -160,7 +160,11 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        }
        sc->sc_early = 0;
 
-       mainbus_attach_framebuffer(self);
+       /*
+        * Delay attaching the framebuffer to give other drivers a
+        * chance to claim it.
+        */
+       config_mountroot(self, mainbus_attach_framebuffer);
 
        thermal_init();
 }
index b860463..f3c8b87 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: apldrm.c,v 1.1 2024/01/22 18:54:01 kettenis Exp $     */
+/*     $OpenBSD: apldrm.c,v 1.2 2024/01/29 14:52:25 kettenis Exp $     */
 /*
  * Copyright (c) 2023 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -83,35 +83,9 @@ apldrm_attach(struct device *parent, struct device *self, void *aux)
 {
        struct apldrm_softc *sc = (struct apldrm_softc *)self;
        struct fdt_attach_args *faa = aux;
-       int idx, len, node;
-       uint32_t *phandles;
-       uint64_t reg[2];
 
        sc->sc_node = faa->fa_node;
 
-       /* Claim framebuffer to prevent attaching other drivers. */
-       len = OF_getproplen(faa->fa_node, "memory-region");
-       idx = OF_getindex(faa->fa_node, "framebuffer", "memory-region-names");
-       if (idx >= 0 && idx < len / sizeof(uint32_t)) {
-               phandles = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
-               OF_getpropintarray(faa->fa_node, "memory-region",
-                   phandles, len);
-               node = OF_getnodebyphandle(phandles[idx]);
-               if (node) {
-                       if (OF_getpropint64array(node, "reg", reg,
-                           sizeof(reg)) == sizeof(reg))
-                               rasops_claim_framebuffer(reg[0], reg[1], self);
-               }
-               free(phandles, M_TEMP, len);
-       }
-
-       /*
-        * Update our understanding of the console output node if
-        * we're using the framebuffer console.
-        */
-       if (OF_is_compatible(stdout_node, "simple-framebuffer"))
-               stdout_node = sc->sc_node;
-
        printf("\n");
 
        sc->sc_dev.faa = faa;
@@ -324,7 +298,7 @@ apldrm_attachhook(struct device *self)
        struct drm_fb_helper *fb_helper;
        struct rasops_info *ri = &sc->sc_ri;
        struct wsemuldisplaydev_attach_args waa;
-       int console = 0;
+       int idx, len, console = 0;
        uint32_t defattr;
        int error;
 
@@ -332,10 +306,45 @@ apldrm_attachhook(struct device *self)
        if (error)
                return;
 
+       /*
+        * If no display coprocessors were registered with the
+        * component framework, the call above will succeed without
+        * setting up a framebuffer.  Bail if we don't have one.
+        */
+       fb_helper = sc->sc_ddev.fb_helper;
+       if (fb_helper == NULL)
+               return;
+
+       /* Claim framebuffer to prevent attaching other drivers. */
+       len = OF_getproplen(sc->sc_node, "memory-region");
+       idx = OF_getindex(sc->sc_node, "framebuffer", "memory-region-names");
+       if (idx >= 0 && idx < len / sizeof(uint32_t)) {
+               uint32_t *phandles;
+               uint64_t reg[2];
+               int node;
+
+               phandles = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
+               OF_getpropintarray(sc->sc_node, "memory-region",
+                   phandles, len);
+               node = OF_getnodebyphandle(phandles[idx]);
+               if (node) {
+                       if (OF_getpropint64array(node, "reg", reg,
+                           sizeof(reg)) == sizeof(reg))
+                               rasops_claim_framebuffer(reg[0], reg[1], self);
+               }
+               free(phandles, M_TEMP, len);
+       }
+
+       /*
+        * Update our understanding of the console output node if
+        * we're using the framebuffer console.
+        */
+       if (OF_is_compatible(stdout_node, "simple-framebuffer"))
+               stdout_node = sc->sc_node;
+
        if (sc->sc_node == stdout_node)
                console = 1;
 
-       fb_helper = sc->sc_ddev.fb_helper;
        ri->ri_hw = sc;
        ri->ri_bits = fb_helper->info->screen_buffer;
        ri->ri_flg = RI_CENTER | RI_VCONS | RI_WRONLY;