Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Instead of trying to prevent pciconf from reconf...



details:   https://anonhg.NetBSD.org/src/rev/a8ef791a8590
branches:  trunk
changeset: 941426:a8ef791a8590
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Tue Oct 20 23:03:30 2020 +0000

description:
Instead of trying to prevent pciconf from reconfiguring the firmware's
framebuffer, instead allow MD code to register callbacks. If a resource is
changed, the driver can unmap the old resource and remap the new. Do this
with simplefb so the console doesn't explode when the VGA device is
(potentially) reconfigured at boot.

diffstat:

 sys/arch/arm/fdt/arm_simplefb.c   |   42 +++++++++++-
 sys/arch/arm/fdt/arm_simplefb.h   |    3 +-
 sys/arch/evbarm/fdt/fdt_machdep.c |   12 +++-
 sys/dev/fdt/simplefb.c            |   12 ++-
 sys/dev/pci/pciconf.c             |  122 ++++++++++++++++++++-----------------
 sys/dev/pci/pciconf.h             |    5 +-
 6 files changed, 127 insertions(+), 69 deletions(-)

diffs (truncated from 434 to 300 lines):

diff -r e9b9e6b71ffe -r a8ef791a8590 sys/arch/arm/fdt/arm_simplefb.c
--- a/sys/arch/arm/fdt/arm_simplefb.c   Tue Oct 20 22:50:55 2020 +0000
+++ b/sys/arch/arm/fdt/arm_simplefb.c   Tue Oct 20 23:03:30 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $ */
+/* $NetBSD: arm_simplefb.c,v 1.3 2020/10/20 23:03:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #include "opt_pci.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.3 2020/10/20 23:03:30 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -85,6 +85,10 @@
 static struct vcons_data arm_simplefb_vcons_data;
 static struct vcons_screen arm_simplefb_screen;
 
+static bus_addr_t arm_simplefb_addr;
+static bus_size_t arm_simplefb_size;
+static bus_space_handle_t arm_simplefb_bsh;
+
 static int
 arm_simplefb_find_node(void)
 {
@@ -157,6 +161,29 @@
 {
 }
 
+static void
+arm_simplefb_reconfig(void *arg, uint64_t new_addr)
+{
+       struct arm_simplefb_softc * const sc = &arm_simplefb_softc;
+       struct rasops_info *ri = &arm_simplefb_screen.scr_ri;
+       bus_space_tag_t bst = &arm_generic_bs_tag;
+
+       bus_space_unmap(bst, arm_simplefb_bsh, arm_simplefb_size);
+       bus_space_map(bst, new_addr, arm_simplefb_size,
+           BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &arm_simplefb_bsh);
+
+       sc->sc_bits = bus_space_vaddr(bst, arm_simplefb_bsh);
+       ri->ri_bits = sc->sc_bits;
+
+       arm_simplefb_addr = (bus_addr_t)new_addr;
+}
+
+uint64_t
+arm_simplefb_physaddr(void)
+{
+       return arm_simplefb_addr;
+}
+
 void
 arm_simplefb_preattach(void)
 {
@@ -205,6 +232,10 @@
            BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &bsh) != 0)
                return;
 
+       arm_simplefb_addr = addr;
+       arm_simplefb_size = size;
+       arm_simplefb_bsh = bsh;
+
        sc->sc_width = width;
        sc->sc_height = height;
        sc->sc_depth = depth;
@@ -240,9 +271,10 @@
 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
        /*
         * Let the PCI resource allocator know about our framebuffer. This
-        * protects the VGA device BARs from being reprogrammed when we the
-        * framebuffer is located in VRAM.
+        * lets us know if the FB base address changes so we can remap the
+        * framebuffer if necessary.
         */
-       pciconf_resource_reserve(PCI_CONF_MAP_MEM, addr, size);
+       pciconf_resource_reserve(PCI_CONF_MAP_MEM, addr, size,
+           arm_simplefb_reconfig, NULL);
 #endif
 }
diff -r e9b9e6b71ffe -r a8ef791a8590 sys/arch/arm/fdt/arm_simplefb.h
--- a/sys/arch/arm/fdt/arm_simplefb.h   Tue Oct 20 22:50:55 2020 +0000
+++ b/sys/arch/arm/fdt/arm_simplefb.h   Tue Oct 20 23:03:30 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: arm_simplefb.h,v 1.1 2020/10/10 15:25:31 jmcneill Exp $ */
+/* $NetBSD: arm_simplefb.h,v 1.2 2020/10/20 23:03:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -33,5 +33,6 @@
 #define _ARM_ARM_SIMPLEFB_H
 
 void           arm_simplefb_preattach(void);
+uint64_t       arm_simplefb_physaddr(void);
 
 #endif /* !_ARM_ARM_SIMPLEFB_H */
diff -r e9b9e6b71ffe -r a8ef791a8590 sys/arch/evbarm/fdt/fdt_machdep.c
--- a/sys/arch/evbarm/fdt/fdt_machdep.c Tue Oct 20 22:50:55 2020 +0000
+++ b/sys/arch/evbarm/fdt/fdt_machdep.c Tue Oct 20 23:03:30 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $ */
+/* $NetBSD: fdt_machdep.c,v 1.77 2020/10/20 23:03:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.77 2020/10/20 23:03:30 jmcneill Exp $");
 
 #include "opt_machdep.h"
 #include "opt_bootconfig.h"
@@ -880,6 +880,14 @@
 #endif
        }
 
+#if NWSDISPLAY > 0 && NGENFB > 0
+       if (device_is_a(self, "genfb")) {
+               prop_dictionary_t dict = device_properties(self);
+               prop_dictionary_set_uint64(dict,
+                   "simplefb-physaddr", arm_simplefb_physaddr());
+       }
+#endif
+
        if (plat && plat->ap_device_register)
                plat->ap_device_register(self, aux);
 }
diff -r e9b9e6b71ffe -r a8ef791a8590 sys/dev/fdt/simplefb.c
--- a/sys/dev/fdt/simplefb.c    Tue Oct 20 22:50:55 2020 +0000
+++ b/sys/dev/fdt/simplefb.c    Tue Oct 20 23:03:30 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $ */
+/* $NetBSD: simplefb.c,v 1.10 2020/10/20 23:03:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_wsdisplay_compat.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.10 2020/10/20 23:03:30 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -132,7 +132,7 @@
        uint32_t width, height, stride;
        uint16_t depth;
        const char *format;
-       bus_addr_t addr;
+       bus_addr_t addr, sfb_addr;
        bus_size_t size;
 
        if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
@@ -168,6 +168,12 @@
                return ENXIO;
        }
 
+       /* Device may have been reconfigured. MD code will tell us. */
+       if (prop_dictionary_get_uint64(dict, "simplefb-physaddr", &sfb_addr) &&
+           sfb_addr != 0) {
+               addr = (bus_addr_t)sfb_addr;
+       }
+
        if (bus_space_map(sc->sc_bst, addr, size,
            BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
            &sc->sc_bsh) != 0) {
diff -r e9b9e6b71ffe -r a8ef791a8590 sys/dev/pci/pciconf.c
--- a/sys/dev/pci/pciconf.c     Tue Oct 20 22:50:55 2020 +0000
+++ b/sys/dev/pci/pciconf.c     Tue Oct 20 23:03:30 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pciconf.c,v 1.49 2020/10/10 15:22:15 jmcneill Exp $    */
+/*     $NetBSD: pciconf.c,v 1.50 2020/10/20 23:03:30 jmcneill Exp $    */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.49 2020/10/10 15:22:15 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciconf.c,v 1.50 2020/10/20 23:03:30 jmcneill Exp $");
 
 #include "opt_pci.h"
 
@@ -121,6 +121,8 @@
        int             type;
        uint64_t        start;
        bus_size_t      size;
+       void            (*callback)(void *, uint64_t);
+       void            *callback_arg;
        LIST_ENTRY(pciconf_resource_rsvd) next;
 };
 
@@ -516,7 +518,7 @@
        return NULL;
 }
 
-static bool
+static struct pciconf_resource_rsvd *
 pci_resource_is_reserved(int type, uint64_t addr, uint64_t size)
 {
        struct pciconf_resource_rsvd *rsvd;
@@ -525,62 +527,61 @@
                if (rsvd->type != type)
                        continue;
                if (rsvd->start <= addr + size && rsvd->start + rsvd->size >= addr)
-                       return true;
+                       return rsvd;
        }
 
-       return false;
+       return NULL;
 }
 
-static bool
-pci_device_is_reserved(pciconf_bus_t *pb, pcitag_t tag)
+static struct pciconf_resource_rsvd *
+pci_bar_is_reserved(pciconf_bus_t *pb, pciconf_dev_t *pd, int br)
 {
        pcireg_t base, base64, mask, mask64;
+       pcitag_t tag;
        uint64_t addr, size;
-       int br, width;
+
+       /*
+        * Resource reservation does not apply to bridges
+        */
+       if (pd->ppb)
+               return NULL;
+
+       tag = pd->tag;
 
        /*
         * Look to see if this device is enabled and one of the resources
-        * is already in use (firmware configured console device). If so,
-        * skip resource assignment and use firmware values.
+        * is already in use (eg. firmware configured console device).
         */
-       width = 4;
-       for (br = PCI_MAPREG_START; br < PCI_MAPREG_END; br += width) {
+       base = pci_conf_read(pb->pc, tag, br);
+       pci_conf_write(pb->pc, tag, br, 0xffffffff);
+       mask = pci_conf_read(pb->pc, tag, br);
+       pci_conf_write(pb->pc, tag, br, base);
 
-               base = pci_conf_read(pb->pc, tag, br);
-               pci_conf_write(pb->pc, tag, br, 0xffffffff);
-               mask = pci_conf_read(pb->pc, tag, br);
-               pci_conf_write(pb->pc, tag, br, base);
-               width = 4;
+       switch (PCI_MAPREG_TYPE(base)) {
+       case PCI_MAPREG_TYPE_IO:
+               addr = PCI_MAPREG_IO_ADDR(base);
+               size = PCI_MAPREG_IO_SIZE(mask);
+               return pci_resource_is_reserved(PCI_CONF_MAP_IO, addr, size);
 
-               switch (PCI_MAPREG_TYPE(base)) {
-               case PCI_MAPREG_TYPE_IO:
-                       addr = PCI_MAPREG_IO_ADDR(base);
-                       size = PCI_MAPREG_IO_SIZE(mask);
-                       if (pci_resource_is_reserved(PCI_CONF_MAP_IO, addr, size))
-                               return true;
-                       break;
-               case PCI_MAPREG_TYPE_MEM:
-                       if (PCI_MAPREG_MEM_TYPE(base) == PCI_MAPREG_MEM_TYPE_64BIT) {
-                               base64 = pci_conf_read(pb->pc, tag, br + 4);
-                               pci_conf_write(pb->pc, tag, br + 4, 0xffffffff);
-                               mask64 = pci_conf_read(pb->pc, tag, br + 4);
-                               pci_conf_write(pb->pc, tag, br + 4, base64);
-                               addr = (uint64_t)PCI_MAPREG_MEM64_ADDR(
-                                     (((uint64_t)base64) << 32) | base);
-                               size = (uint64_t)PCI_MAPREG_MEM64_SIZE(
-                                     (((uint64_t)mask64) << 32) | mask);
-                               width = 8;
-                       } else {
-                               addr = PCI_MAPREG_MEM_ADDR(base);
-                               size = PCI_MAPREG_MEM_SIZE(mask);
-                       }
-                       if (pci_resource_is_reserved(PCI_CONF_MAP_MEM, addr, size))
-                               return true;
-                       break;
+       case PCI_MAPREG_TYPE_MEM:
+               if (PCI_MAPREG_MEM_TYPE(base) == PCI_MAPREG_MEM_TYPE_64BIT) {
+                       base64 = pci_conf_read(pb->pc, tag, br + 4);
+                       pci_conf_write(pb->pc, tag, br + 4, 0xffffffff);
+                       mask64 = pci_conf_read(pb->pc, tag, br + 4);
+                       pci_conf_write(pb->pc, tag, br + 4, base64);
+                       addr = (uint64_t)PCI_MAPREG_MEM64_ADDR(
+                             (((uint64_t)base64) << 32) | base);
+                       size = (uint64_t)PCI_MAPREG_MEM64_SIZE(
+                             (((uint64_t)mask64) << 32) | mask);
+               } else {
+                       addr = PCI_MAPREG_MEM_ADDR(base);



Home | Main Index | Thread Index | Old Index