From d788c4b21dd74bf3351258127a1ef2e91853b42c Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 29 Jan 2024 14:52:25 +0000 Subject: [PATCH] Because of the way the Linux code behind apldrm(4) is structured it may 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 | 8 +++- sys/dev/pci/drm/apple/apldrm.c | 67 +++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/sys/arch/arm64/dev/mainbus.c b/sys/arch/arm64/dev/mainbus.c index 495a4ca286a..d3b8bcb9d58 100644 --- a/sys/arch/arm64/dev/mainbus.c +++ b/sys/arch/arm64/dev/mainbus.c @@ -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 * Copyright (c) 2017 Mark Kettenis @@ -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(); } diff --git a/sys/dev/pci/drm/apple/apldrm.c b/sys/dev/pci/drm/apple/apldrm.c index b860463380b..f3c8b87f4d9 100644 --- a/sys/dev/pci/drm/apple/apldrm.c +++ b/sys/dev/pci/drm/apple/apldrm.c @@ -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 * @@ -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; -- 2.20.1