The branch stable/14 has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=621c8145b81a42e412256e5b6a4088d8e54042d8

commit 621c8145b81a42e412256e5b6a4088d8e54042d8
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2024-02-09 18:27:45 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-02-27 13:09:21 +0000

    pcib: Refine handling of resources allocated from bridge windows
    
    Fix a long-standing layering violation in the original NEW_PCIB code
    by not passing suballocated resources up to the parent bus for
    activation and mapping.  Instead, handle activation and mapping of
    sub-allocated resources in this driver.  When mapping resources,
    request a mapping from a suitable sub-region of the resource allocated
    from the parent bus for the associated bridge window.
    
    Note that this does require passing RF_ACTIVE (with RF_UNMAPPED) when
    allocating bridge window resources from the parent.
    
    Reviewed by:    imp
    Differential Revision:  https://reviews.freebsd.org/D43690
    
    (cherry picked from commit b377ff8110e3489eb6e6b920b51a2384dfc4eb0b)
---
 sys/dev/pci/pci_pci.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 126 insertions(+), 4 deletions(-)

diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 5286d4e82e53..02fa8cf1fb9e 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -66,6 +66,10 @@ static bus_alloc_resource_t  pcib_alloc_resource;
 #ifdef NEW_PCIB
 static bus_adjust_resource_t   pcib_adjust_resource;
 static bus_release_resource_t  pcib_release_resource;
+static bus_activate_resource_t pcib_activate_resource;
+static bus_deactivate_resource_t pcib_deactivate_resource;
+static bus_map_resource_t      pcib_map_resource;
+static bus_unmap_resource_t    pcib_unmap_resource;
 #endif
 static int             pcib_reset_child(device_t dev, device_t child, int 
flags);
 
@@ -108,12 +112,16 @@ static device_method_t pcib_methods[] = {
 #ifdef NEW_PCIB
     DEVMETHOD(bus_adjust_resource,     pcib_adjust_resource),
     DEVMETHOD(bus_release_resource,    pcib_release_resource),
+    DEVMETHOD(bus_activate_resource,   pcib_activate_resource),
+    DEVMETHOD(bus_deactivate_resource, pcib_deactivate_resource),
+    DEVMETHOD(bus_map_resource,                pcib_map_resource),
+    DEVMETHOD(bus_unmap_resource,      pcib_unmap_resource),
 #else
     DEVMETHOD(bus_adjust_resource,     bus_generic_adjust_resource),
     DEVMETHOD(bus_release_resource,    bus_generic_release_resource),
-#endif
     DEVMETHOD(bus_activate_resource,   bus_generic_activate_resource),
     DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+#endif
     DEVMETHOD(bus_setup_intr,          bus_generic_setup_intr),
     DEVMETHOD(bus_teardown_intr,       bus_generic_teardown_intr),
     DEVMETHOD(bus_reset_child,         pcib_reset_child),
@@ -381,7 +389,7 @@ alloc_ranges(rman_res_t start, rman_res_t end, void *arg)
                device_printf(as->sc->dev,
                    "allocating non-ISA range %#jx-%#jx\n", start, end);
        as->res[as->count] = bus_alloc_resource(as->sc->dev, SYS_RES_IOPORT,
-           &rid, start, end, end - start + 1, 0);
+           &rid, start, end, end - start + 1, RF_ACTIVE | RF_UNMAPPED);
        if (as->res[as->count] == NULL)
                as->error = ENXIO;
        else
@@ -454,7 +462,7 @@ pcib_alloc_window(struct pcib_softc *sc, struct pcib_window 
*w, int type,
        else {
                rid = w->reg;
                res = bus_alloc_resource(sc->dev, type, &rid, w->base, w->limit,
-                   w->limit - w->base + 1, flags);
+                   w->limit - w->base + 1, flags | RF_ACTIVE | RF_UNMAPPED);
                if (res != NULL)
                        pcib_add_window_resources(w, &res, 1);
        }
@@ -2001,7 +2009,7 @@ pcib_alloc_new_window(struct pcib_softc *sc, struct 
pcib_window *w, int type,
        count = roundup2(count, (rman_res_t)1 << w->step);
        rid = w->reg;
        res = bus_alloc_resource(sc->dev, type, &rid, start, end, count,
-           flags & ~RF_ACTIVE);
+           flags | RF_ACTIVE | RF_UNMAPPED);
        if (res == NULL)
                return (ENOSPC);
        pcib_add_window_resources(w, &res, 1);
@@ -2452,6 +2460,120 @@ pcib_release_resource(device_t dev, device_t child, int 
type, int rid,
        }
        return (bus_generic_release_resource(dev, child, type, rid, r));
 }
+
+static int
+pcib_activate_resource(device_t dev, device_t child, int type, int rid,
+    struct resource *r)
+{
+       struct pcib_softc *sc = device_get_softc(dev);
+       struct resource_map map;
+       int error;
+
+       if (!pcib_is_resource_managed(sc, type, r))
+               return (bus_generic_activate_resource(dev, child, type, rid,
+                   r));
+
+       error = rman_activate_resource(r);
+       if (error != 0)
+               return (error);
+
+       if ((rman_get_flags(r) & RF_UNMAPPED) == 0 &&
+           (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
+               error = BUS_MAP_RESOURCE(dev, child, type, r, NULL, &map);
+               if (error != 0) {
+                       rman_deactivate_resource(r);
+                       return (error);
+               }
+
+               rman_set_mapping(r, &map);
+       }
+       return (0);
+}
+
+static int
+pcib_deactivate_resource(device_t dev, device_t child, int type, int rid,
+    struct resource *r)
+{
+       struct pcib_softc *sc = device_get_softc(dev);
+       struct resource_map map;
+       int error;
+
+       if (!pcib_is_resource_managed(sc, type, r))
+               return (bus_generic_deactivate_resource(dev, child, type, rid,
+                   r));
+
+       error = rman_deactivate_resource(r);
+       if (error != 0)
+               return (error);
+
+       if ((rman_get_flags(r) & RF_UNMAPPED) == 0 &&
+           (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT)) {
+               rman_get_mapping(r, &map);
+               BUS_UNMAP_RESOURCE(dev, child, type, r, &map);
+       }
+       return (0);
+}
+
+static struct resource *
+pcib_find_parent_resource(struct pcib_window *w, struct resource *r)
+{
+       for (int i = 0; i < w->count; i++) {
+               if (rman_get_start(w->res[i]) <= rman_get_start(r) &&
+                   rman_get_end(w->res[i]) >= rman_get_end(r))
+                       return (w->res[i]);
+       }
+       return (NULL);
+}
+
+static int
+pcib_map_resource(device_t dev, device_t child, int type, struct resource *r,
+    struct resource_map_request *argsp, struct resource_map *map)
+{
+       struct pcib_softc *sc = device_get_softc(dev);
+       struct resource_map_request args;
+       struct pcib_window *w;
+       struct resource *pres;
+       rman_res_t length, start;
+       int error;
+
+       w = pcib_get_resource_window(sc, type, r);
+       if (w == NULL)
+               return (bus_generic_map_resource(dev, child, type, r, argsp,
+                   map));
+
+       /* Resources must be active to be mapped. */
+       if (!(rman_get_flags(r) & RF_ACTIVE))
+               return (ENXIO);
+
+       resource_init_map_request(&args);
+       error = resource_validate_map_request(r, argsp, &args, &start, &length);
+       if (error)
+               return (error);
+
+       pres = pcib_find_parent_resource(w, r);
+       if (pres == NULL)
+               return (ENOENT);
+
+       args.offset = start - rman_get_start(pres);
+       args.length = length;
+       return (bus_generic_map_resource(dev, child, type, pres, &args, map));
+}
+
+static int
+pcib_unmap_resource(device_t dev, device_t child, int type, struct resource *r,
+    struct resource_map *map)
+{
+       struct pcib_softc *sc = device_get_softc(dev);
+       struct pcib_window *w;
+
+       w = pcib_get_resource_window(sc, type, r);
+       if (w != NULL) {
+               r = pcib_find_parent_resource(w, r);
+               if (r == NULL)
+                       return (ENOENT);
+       }
+       return (bus_generic_unmap_resource(dev, child, type, r, map));
+}
 #else
 /*
  * We have to trap resource allocation requests and ensure that the bridge

Reply via email to