Author: mmel
Date: Sun Jul 17 13:43:00 2016
New Revision: 302951
URL: https://svnweb.freebsd.org/changeset/base/302951

Log:
  OFWPCI: Improve resource handling.
  - add new rman for prefetchable memory. Is used only if given 'ranges'
    property contains prefetchable memory range.
  
  - not all ranges in 'ranges' property are subject for rman's filling.
    Tegra for example, have two addition records which are used for
    'pci 'register' -> 'assigned-address' -> 'ranges' machinery.
    Add sc_ranges_mask for masking not rman related ranges.
  
  - consistently pass unknown (not managed at this level) resources
    allocation/release/adjust requests to parent.
  
  MFC after: 3 weeks

Modified:
  head/sys/dev/ofw/ofwpci.c
  head/sys/dev/ofw/ofwpci.h

Modified: head/sys/dev/ofw/ofwpci.c
==============================================================================
--- head/sys/dev/ofw/ofwpci.c   Sun Jul 17 13:33:35 2016        (r302950)
+++ head/sys/dev/ofw/ofwpci.c   Sun Jul 17 13:43:00 2016        (r302951)
@@ -94,6 +94,7 @@ static phandle_t ofw_pci_get_node(device
  * local methods
  */
 static int ofw_pci_fill_ranges(phandle_t, struct ofw_pci_range *);
+static struct rman *ofw_pci_get_rman(struct ofw_pci_softc *, int, u_int);
 
 /*
  * Driver methods.
@@ -137,7 +138,7 @@ ofw_pci_init(device_t dev)
        phandle_t node;
        u_int32_t busrange[2];
        struct ofw_pci_range *rp;
-       int error;
+       int i, error;
        struct ofw_pci_cell_info *cell_info;
 
        node = ofw_bus_get_node(dev);
@@ -201,17 +202,27 @@ ofw_pci_init(device_t dev)
        }
 
        sc->sc_mem_rman.rm_type = RMAN_ARRAY;
-       sc->sc_mem_rman.rm_descr = "PCI Memory";
+       sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory";
        error = rman_init(&sc->sc_mem_rman);
        if (error != 0) {
                device_printf(dev, "rman_init() failed. error = %d\n", error);
                goto out;
        }
 
-       for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
-           rp->pci_hi != 0; rp++) {
+       sc->sc_pmem_rman.rm_type = RMAN_ARRAY;
+       sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory";
+       error = rman_init(&sc->sc_pmem_rman);
+       if (error != 0) {
+               device_printf(dev, "rman_init() failed. error = %d\n", error);
+               goto out;
+       }
+
+       for (i = 0; i < sc->sc_nrange; i++) {
                error = 0;
+               rp = sc->sc_range + i;
 
+               if (sc->sc_range_mask & ((uint64_t)1 << i))
+                       continue;
                switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
                case OFW_PCI_PHYS_HI_SPACE_CONFIG:
                        break;
@@ -221,8 +232,14 @@ ofw_pci_init(device_t dev)
                        break;
                case OFW_PCI_PHYS_HI_SPACE_MEM32:
                case OFW_PCI_PHYS_HI_SPACE_MEM64:
-                       error = rman_manage_region(&sc->sc_mem_rman, rp->pci,
-                           rp->pci + rp->size - 1);
+                       if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) {
+                               sc->sc_have_pmem = 1;
+                               error = rman_manage_region(&sc->sc_pmem_rman,
+                                   rp->pci, rp->pci + rp->size - 1);
+                       } else {
+                               error = rman_manage_region(&sc->sc_mem_rman,
+                                   rp->pci, rp->pci + rp->size - 1);
+                       }
                        break;
                }
 
@@ -244,6 +261,7 @@ out:
        free(sc->sc_range, M_DEVBUF);
        rman_fini(&sc->sc_io_rman);
        rman_fini(&sc->sc_mem_rman);
+       rman_fini(&sc->sc_pmem_rman);
 
        return (error);
 }
@@ -385,28 +403,16 @@ ofw_pci_alloc_resource(device_t bus, dev
        struct rman *rm;
        int needactivate;
 
+
        needactivate = flags & RF_ACTIVE;
        flags &= ~RF_ACTIVE;
 
        sc = device_get_softc(bus);
 
-       switch (type) {
-       case SYS_RES_MEMORY:
-               rm = &sc->sc_mem_rman;
-               break;
-
-       case SYS_RES_IOPORT:
-               rm = &sc->sc_io_rman;
-               break;
-
-       case SYS_RES_IRQ:
-               return (bus_alloc_resource(bus, type, rid, start, end, count,
-                   flags));
-
-       default:
-               device_printf(bus, "unknown resource request from %s\n",
-                   device_get_nameunit(child));
-               return (NULL);
+       rm = ofw_pci_get_rman(sc, type, flags);
+       if (rm == NULL)  {
+               return (bus_generic_alloc_resource(bus, child, type, rid,
+                   start, end, count, flags));
        }
 
        rv = rman_reserve_resource(rm, start, end, count, flags, child);
@@ -435,15 +441,24 @@ static int
 ofw_pci_release_resource(device_t bus, device_t child, int type, int rid,
     struct resource *res)
 {
+       struct ofw_pci_softc *sc;
+       struct rman *rm;
+       int error;
 
-       if (rman_get_flags(res) & RF_ACTIVE) {
-               int error;
+       sc = device_get_softc(bus);
+
+       rm = ofw_pci_get_rman(sc, type, rman_get_flags(res));
+       if (rm == NULL) {
+               return (bus_generic_release_resource(bus, child, type, rid,
+                   res));
+       }
+       KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
 
+       if (rman_get_flags(res) & RF_ACTIVE) {
                error = bus_deactivate_resource(child, type, rid, res);
                if (error != 0)
                        return (error);
        }
-
        return (rman_release_resource(res));
 }
 
@@ -454,63 +469,62 @@ ofw_pci_activate_resource(device_t bus, 
        struct ofw_pci_softc *sc;
        bus_space_handle_t handle;
        bus_space_tag_t tag;
+       struct ofw_pci_range *rp;
+       vm_paddr_t start;
+       int space;
        int rv;
 
        sc = device_get_softc(bus);
 
-       if (type == SYS_RES_IRQ) {
-               return (bus_activate_resource(bus, type, rid, res));
+       if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
+               return (bus_generic_activate_resource(bus, child, type, rid,
+                   res));
        }
-       if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
-               struct ofw_pci_range *rp;
-               vm_paddr_t start;
-               int space;
-
-               start = (vm_paddr_t)rman_get_start(res);
-
-               /*
-                * Map this through the ranges list
-                */
-               for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
-                   rp->pci_hi != 0; rp++) {
-                       if (start < rp->pci || start >= rp->pci + rp->size)
-                               continue;
-
-                       switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
-                       case OFW_PCI_PHYS_HI_SPACE_IO:
-                               space = SYS_RES_IOPORT;
-                               break;
-                       case OFW_PCI_PHYS_HI_SPACE_MEM32:
-                       case OFW_PCI_PHYS_HI_SPACE_MEM64:
-                               space = SYS_RES_MEMORY;
-                               break;
-                       default:
-                               space = -1;
-                       }
 
-                       if (type == space) {
-                               start += (rp->host - rp->pci);
-                               break;
+       start = (vm_paddr_t)rman_get_start(res);
+
+       /*
+        * Map this through the ranges list
+        */
+       for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+           rp->pci_hi != 0; rp++) {
+               if (start < rp->pci || start >= rp->pci + rp->size)
+                       continue;
+
+               switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+               case OFW_PCI_PHYS_HI_SPACE_IO:
+                       space = SYS_RES_IOPORT;
+                       break;
+               case OFW_PCI_PHYS_HI_SPACE_MEM32:
+               case OFW_PCI_PHYS_HI_SPACE_MEM64:
+                       space = SYS_RES_MEMORY;
+                       break;
+               default:
+                       space = -1;
                        }
+
+               if (type == space) {
+                       start += (rp->host - rp->pci);
+                       break;
                }
+       }
 
-               if (bootverbose)
-                       printf("ofw_pci mapdev: start %jx, len %jd\n",
-                           (rman_res_t)start, rman_get_size(res));
-
-               tag = BUS_GET_BUS_TAG(child, child);
-               if (tag == NULL)
-                       return (ENOMEM);
-
-               rman_set_bustag(res, tag);
-               rv = bus_space_map(tag, start,
-                   rman_get_size(res), 0, &handle);
-               if (rv != 0)
-                       return (ENOMEM);
+       if (bootverbose)
+               printf("ofw_pci mapdev: start %jx, len %jd\n",
+                   (rman_res_t)start, rman_get_size(res));
+
+       tag = BUS_GET_BUS_TAG(child, child);
+       if (tag == NULL)
+               return (ENOMEM);
+
+       rman_set_bustag(res, tag);
+       rv = bus_space_map(tag, start,
+           rman_get_size(res), 0, &handle);
+       if (rv != 0)
+               return (ENOMEM);
 
-               rman_set_bushandle(res, handle);
-               rman_set_virtual(res, (void *)handle); /* XXX  for powerpc only 
? */
-       }
+       rman_set_bushandle(res, handle);
+       rman_set_virtual(res, (void *)handle); /* XXX  for powerpc only ? */
 
        return (rman_activate_resource(res));
 }
@@ -528,17 +542,19 @@ static int
 ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *res)
 {
+       struct ofw_pci_softc *sc;
+       vm_size_t psize;
 
-       /*
-        * If this is a memory resource, unmap it.
-        */
-       if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
-               u_int32_t psize;
+       sc = device_get_softc(bus);
 
-               psize = rman_get_size(res);
-               pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+       if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
+               return (bus_generic_deactivate_resource(bus, child, type, rid,
+                   res));
        }
 
+       psize = rman_get_size(res);
+       pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+
        return (rman_deactivate_resource(res));
 }
 
@@ -550,24 +566,15 @@ ofw_pci_adjust_resource(device_t bus, de
        struct ofw_pci_softc *sc;
 
        sc = device_get_softc(bus);
-       KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
-           ("active resources cannot be adjusted"));
-       if (rman_get_flags(res) & RF_ACTIVE)
-               return (EINVAL);
 
-       switch (type) {
-       case SYS_RES_MEMORY:
-               rm = &sc->sc_mem_rman;
-               break;
-       case SYS_RES_IOPORT:
-               rm = &sc->sc_io_rman;
-               break;
-       default:
-               return (ENXIO);
+       rm = ofw_pci_get_rman(sc, type, rman_get_flags(res));
+       if (rm == NULL) {
+               return (bus_generic_adjust_resource(bus, child, type, res,
+                   start, end));
        }
-
-       if (!rman_is_region_manager(res, rm))
-               return (EINVAL);
+       KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
+       KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
+           ("active resources cannot be adjusted"));
 
        return (rman_adjust_resource(res, start, end));
 }
@@ -629,3 +636,22 @@ ofw_pci_fill_ranges(phandle_t node, stru
        free(base_ranges, M_DEVBUF);
        return (nranges);
 }
+
+static struct rman *
+ofw_pci_get_rman(struct ofw_pci_softc *sc, int type, u_int flags)
+{
+
+       switch (type) {
+       case SYS_RES_IOPORT:
+               return (&sc->sc_io_rman);
+       case SYS_RES_MEMORY:
+               if (sc->sc_have_pmem  && (flags & RF_PREFETCHABLE))
+                       return (&sc->sc_pmem_rman);
+               else
+                       return (&sc->sc_mem_rman);
+       default:
+               break;
+       }
+
+       return (NULL);
+}

Modified: head/sys/dev/ofw/ofwpci.h
==============================================================================
--- head/sys/dev/ofw/ofwpci.h   Sun Jul 17 13:33:35 2016        (r302950)
+++ head/sys/dev/ofw/ofwpci.h   Sun Jul 17 13:43:00 2016        (r302951)
@@ -60,13 +60,16 @@ struct ofw_pci_softc {
        int             sc_bus;
        int             sc_initialized;
        int             sc_quirks;
+       int             sc_have_pmem;
 
        struct ofw_pci_range            *sc_range;
        int                             sc_nrange;
+       uint64_t                        sc_range_mask;
        struct ofw_pci_cell_info        *sc_cell_info;
 
        struct rman                     sc_io_rman;
        struct rman                     sc_mem_rman;
+       struct rman                     sc_pmem_rman;
        bus_space_tag_t                 sc_memt;
        bus_dma_tag_t                   sc_dmat;
 
_______________________________________________
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