Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Jul 2016 13:43:01 +0000 (UTC)
From:      Michal Meloun <mmel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r302951 - head/sys/dev/ofw
Message-ID:  <201607171343.u6HDh1dM026194@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607171343.u6HDh1dM026194>