svn commit: r307347 - stable/11/sys/dev/ofw

Michal Meloun mmel at FreeBSD.org
Sat Oct 15 09:09:27 UTC 2016


Author: mmel
Date: Sat Oct 15 09:09:25 2016
New Revision: 307347
URL: https://svnweb.freebsd.org/changeset/base/307347

Log:
  MFC r302951,r302952,r304071:
  
    r302951:
      OFWPCI: Improve resource handling.  - add new rman for prefetchable memory.
      Is used only if given 'ranges'
        property contains prefetchable memory range.
    r302952:
      OFWPCI: Add support for NEW_PCIB.
    r304071:
      OFWPCI: Don't strip RF_ACTIVE from flags when parent bus method is called.

Modified:
  stable/11/sys/dev/ofw/ofwpci.c
  stable/11/sys/dev/ofw/ofwpci.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/ofw/ofwpci.c
==============================================================================
--- stable/11/sys/dev/ofw/ofwpci.c	Sat Oct 15 08:52:42 2016	(r307346)
+++ stable/11/sys/dev/ofw/ofwpci.c	Sat Oct 15 09:09:25 2016	(r307347)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
 
 #include <machine/bus.h>
 #include <machine/md_var.h>
@@ -94,6 +95,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,13 +139,14 @@ 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);
 	sc = device_get_softc(dev);
 	sc->sc_initialized = 1;
 	sc->sc_range = NULL;
+	sc->sc_pci_domain = device_get_unit(dev);
 
 	cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info),
 	    M_DEVBUF, M_WAITOK | M_ZERO);
@@ -201,17 +204,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 +234,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 +263,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);
 }
@@ -318,7 +338,7 @@ ofw_pci_read_ivar(device_t dev, device_t
 
 	switch (which) {
 	case PCIB_IVAR_DOMAIN:
-		*result = device_get_unit(dev);
+		*result = sc->sc_pci_domain;
 		return (0);
 	case PCIB_IVAR_BUS:
 		*result = sc->sc_bus;
@@ -385,28 +405,23 @@ 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));
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type ==  PCI_RES_BUS) {
+		  return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid,
+		      start, end, count, flags | needactivate));
+	}
+#endif
 
-	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 | needactivate));
 	}
 
 	rv = rman_reserve_resource(rm, start, end, count, flags, child);
@@ -435,15 +450,30 @@ 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);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type == PCI_RES_BUS)
+		return (pci_domain_release_bus(sc->sc_pci_domain, child, rid,
+		    res));
+#endif
 
+	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 +484,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 +557,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 +581,20 @@ 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);
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+	if (type == PCI_RES_BUS)
+		return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res,
+		    start, end));
+#endif
 
-	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 +656,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: stable/11/sys/dev/ofw/ofwpci.h
==============================================================================
--- stable/11/sys/dev/ofw/ofwpci.h	Sat Oct 15 08:52:42 2016	(r307346)
+++ stable/11/sys/dev/ofw/ofwpci.h	Sat Oct 15 09:09:25 2016	(r307347)
@@ -60,15 +60,19 @@ 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;
+	int				sc_pci_domain;
 
 	struct ofw_bus_iinfo		sc_pci_iinfo;
 };


More information about the svn-src-all mailing list