Author: andrew
Date: Mon Jun 22 10:49:50 2020
New Revision: 362493
URL: https://svnweb.freebsd.org/changeset/base/362493

Log:
  Translaate the PCI address when activating a resource
  
  When the PCI address != physical address we need to translate from the
  former to the latter before passing to the parent to map into the kernels
  virtual address space.
  
  Sponsored by: Innovate UK

Modified:
  head/sys/dev/pci/pci_host_generic.c

Modified: head/sys/dev/pci/pci_host_generic.c
==============================================================================
--- head/sys/dev/pci/pci_host_generic.c Mon Jun 22 10:32:41 2020        
(r362492)
+++ head/sys/dev/pci/pci_host_generic.c Mon Jun 22 10:49:50 2020        
(r362493)
@@ -324,13 +324,11 @@ pci_host_generic_core_release_resource(device_t dev, d
        return (bus_generic_release_resource(dev, child, type, rid, res));
 }
 
-struct resource *
-pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
-    int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+static bool
+generic_pcie_translate_resource(device_t dev, int type, rman_res_t start,
+    rman_res_t end, rman_res_t *new_start, rman_res_t *new_end)
 {
        struct generic_pcie_core_softc *sc;
-       struct resource *res;
-       struct rman *rm;
        uint64_t phys_base;
        uint64_t pci_base;
        uint64_t size;
@@ -338,19 +336,6 @@ pci_host_generic_core_alloc_resource(device_t dev, dev
        bool found;
 
        sc = device_get_softc(dev);
-
-#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
-       if (type == PCI_RES_BUS) {
-               return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
-                   count, flags));
-       }
-#endif
-
-       rm = generic_pcie_rman(sc, type, flags);
-       if (rm == NULL)
-               return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
-                   type, rid, start, end, count, flags));
-
        /* Translate the address from a PCI address to a physical address */
        switch (type) {
        case SYS_RES_IOPORT:
@@ -378,25 +363,57 @@ pci_host_generic_core_alloc_resource(device_t dev, dev
                        }
 
                        if (type == space) {
-                               start = start - pci_base + phys_base;
-                               end = end - pci_base + phys_base;
+                               *new_start = start - pci_base + phys_base;
+                               *new_end = end - pci_base + phys_base;
                                found = true;
                                break;
                        }
                }
-               if (!found) {
-                       device_printf(dev,
-                           "Failed to allocate %s resource %jx-%jx for %s\n",
-                           type == SYS_RES_IOPORT ? "IOPORT" : "MEMORY",
-                           (uintmax_t)start, (uintmax_t)end,
-                           device_get_nameunit(child));
-                       return (NULL);
-               }
                break;
        default:
+               /* No translation for non-memory types */
+               *new_start = start;
+               *new_end = end;
+               found = true;
                break;
        }
 
+       return (found);
+}
+
+struct resource *
+pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
+    int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+       struct generic_pcie_core_softc *sc;
+       struct resource *res;
+       struct rman *rm;
+       rman_res_t phys_start, phys_end;
+
+       sc = device_get_softc(dev);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+       if (type == PCI_RES_BUS) {
+               return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
+                   count, flags));
+       }
+#endif
+
+       rm = generic_pcie_rman(sc, type, flags);
+       if (rm == NULL)
+               return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+                   type, rid, start, end, count, flags));
+
+       /* Translate the address from a PCI address to a physical address */
+       if (!generic_pcie_translate_resource(dev, type, start, end, &phys_start,
+           &phys_end)) {
+               device_printf(dev,
+                   "Failed to translate resource %jx-%jx type %x for %s\n",
+                   (uintmax_t)start, (uintmax_t)end, type,
+                   device_get_nameunit(child));
+               return (NULL);
+       }
+
        if (bootverbose) {
                device_printf(dev,
                    "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
@@ -430,12 +447,21 @@ generic_pcie_activate_resource(device_t dev, device_t 
     int rid, struct resource *r)
 {
        struct generic_pcie_core_softc *sc;
+       rman_res_t start, end;
        int res;
 
        sc = device_get_softc(dev);
 
        if ((res = rman_activate_resource(r)) != 0)
                return (res);
+
+       start = rman_get_start(r);
+       end = rman_get_end(r);
+       if (!generic_pcie_translate_resource(dev, type, start, end, &start,
+           &end))
+               return (EINVAL);
+       rman_set_start(r, start);
+       rman_set_end(r, end);
 
        return (BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type,
            rid, r));
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to