svn commit: r302951 - head/sys/dev/ofw
Michal Meloun
mmel at FreeBSD.org
Sun Jul 17 13:43:02 UTC 2016
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;
More information about the svn-src-head
mailing list