Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Dec 2007 16:08:16 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        arm@freebsd.org
Subject:   Only set bus tag/handles in activate_resource() methods
Message-ID:  <200712211608.16557.jhb@freebsd.org>

next in thread | raw e-mail | index | archive | help
This patch (untested) tries to fix an issue on arm I fixed on the
ACPI-using platforms a while back.  It fixes the top-level bus drivers to
activate resources (assign bus tags and handles so you can use bus_space_*())
in bus_activate_resource() methods instead of in bus_alloc_resource().  This
is important for any drivers that want do what ACPI does: allocate a resource
and then subdivide it to hand it out to child devices.  A driver that does
this can still pass the bus_activate_resource() request up the tree to
actually get bus_space properly set up with this fix.

Note that i80321_pci still has a hack to deal with the variant base address
for the PCI memory region, but the rest of the drivers should be correct now.
Please test, thanks.

--- //depot/vendor/freebsd/src/sys/arm/arm/nexus.c	2007/02/23 12:24:01
+++ //depot/user/jhb/acpipci/arm/arm/nexus.c	2007/03/05 17:04:36
@@ -206,6 +206,8 @@
 	struct rman *rm;
 	int needactivate = flags & RF_ACTIVE;
 
+	flags &= ~RF_ACTIVE;
+
 	switch (type) {
 	case SYS_RES_MEMORY:
 		rm = &mem_rman;
@@ -220,8 +222,6 @@
 		return 0;
 
 	rman_set_rid(rv, *rid);
-	rman_set_bustag(rv, (void*)ARM_BUS_SPACE_MEM);
-	rman_set_bushandle(rv, rman_get_start(rv));		
 	
 	if (needactivate) {
 		if (bus_activate_resource(child, type, *rid, rv)) {
@@ -241,7 +241,7 @@
 	/*
 	 * If this is a memory resource, map it into the kernel.
 	 */
-	if (rman_get_bustag(r) == (void*)ARM_BUS_SPACE_MEM) {
+	if (type == SYS_RES_MEMORY) {
 		caddr_t vaddr = 0;
 		u_int32_t paddr;
 		u_int32_t psize;
@@ -252,6 +252,7 @@
 		poffs = paddr - trunc_page(paddr);
 		vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
 		rman_set_virtual(r, vaddr);
+		rman_set_bustag(r, (void*)ARM_BUS_SPACE_MEM);
 		rman_set_bushandle(r, (bus_space_handle_t) vaddr);
 	}
 	return (rman_activate_resource(r));
--- //depot/vendor/freebsd/src/sys/arm/at91/at91.c	2007/12/19 17:36:50
+++ //depot/user/jhb/acpipci/arm/at91/at91.c	2007/12/20 18:42:26
@@ -511,11 +511,14 @@
 	struct resource_list_entry *rle;
 	struct at91_ivar *ivar = device_get_ivars(child);
 	struct resource_list *rl = &ivar->resources;
+	int needactivate = flags & RF_ACTIVE;
 
 	if (device_get_parent(child) != dev)
 		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
 		    type, rid, start, end, count, flags));
 	
+	flags &= ~RF_ACTIVE;
+
 	rle = resource_list_find(rl, type, *rid);
 	if (rle == NULL)
 		return (NULL);
@@ -541,8 +544,6 @@
 #endif
 			rle->res = rman_reserve_resource(&sc->sc_mem_rman,
 			    start, end, count, flags, child);
-		rman_set_bustag(rle->res, &at91_bs_tag);
-		rman_set_bushandle(rle->res, start);
 		break;
 	}
 	if (rle->res) {
@@ -550,6 +551,12 @@
 		rle->end = rman_get_end(rle->res);
 		rle->count = count;
 		rman_set_rid(rle->res, *rid);
+		if (needactivate) {
+			if (bus_activate_resource(child, type, *rid, rv)) {
+				rman_release_resource(rv);
+				return (NULL);
+			}
+		}
 	}
 	return (rle->res);
 }
@@ -576,6 +583,11 @@
 	rle = resource_list_find(rl, type, rid);
 	if (rle == NULL)
 		return (EINVAL);
+	if (rman_get_flags(r) & RF_ACTIVE) {
+		int error = bus_deactivate_resource(child, type, rid, r);
+		if (error)
+			return (error);
+	}
 	rman_release_resource(r);
 	rle->res = NULL;
 	return (0);
@@ -615,15 +627,19 @@
 #if 0
 	u_long p;
 	int error;
+#endif
 	
 	if (type == SYS_RES_MEMORY) {
+		rman_set_bustag(r, &at91_bs_tag);
+		rman_set_bushandle(r, start);
+#if 0
 		error = bus_space_map(rman_get_bustag(r),
 		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
 		if (error) 
 			return (error);
 		rman_set_bushandle(r, p);
+#endif
 	}
-#endif	
 	return (rman_activate_resource(r));
 }
 
--- //depot/vendor/freebsd/src/sys/arm/xscale/i80321/i80321_pci.c	2007/09/30 11:08:30
+++ //depot/user/jhb/acpipci/arm/xscale/i80321/i80321_pci.c	2007/12/20 23:43:49
@@ -283,8 +283,7 @@
 	struct i80321_pci_softc *sc = device_get_softc(bus);	
 	struct resource *rv;
 	struct rman *rm;
-	bus_space_tag_t bt = NULL;
-	bus_space_handle_t bh = 0;
+	bus_handle_t bh = 0;
 
 	switch (type) {
 	case SYS_RES_IRQ:
@@ -292,7 +291,6 @@
 		break;
 	case SYS_RES_MEMORY:
 		rm = &sc->sc_mem_rman;
-		bt = sc->sc_pcimem;
 		bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 :
 		    sc->sc_mem;
 		start &= (0x1000000 - 1);
@@ -300,8 +298,6 @@
 		break;
 	case SYS_RES_IOPORT:
 		rm = &sc->sc_io_rman;
-		bt = sc->sc_pciio;
-		bh = sc->sc_io;
 		if (start < sc->sc_io) {
 			start = start - 0x90000000 + sc->sc_io;
 			end = end - 0x90000000 + sc->sc_io;
@@ -311,21 +307,22 @@
 		return (NULL);
 	}
 
-	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
 	if (rv == NULL)
 		return (NULL);
 	rman_set_rid(rv, *rid);
-	if (type != SYS_RES_IRQ) {
-		if (type == SYS_RES_MEMORY)
-			bh += (rman_get_start(rv));
-		rman_set_bustag(rv, bt);
+	if (type == SYS_RES_MEMORY)
+		/*
+		 * XXX: This isn't quite right but we don't have a better way
+		 * to pass this on to our activate_resource() routine.
+		 */
 		rman_set_bushandle(rv, bh);
-		if (flags & RF_ACTIVE) {
-			if (bus_activate_resource(child, type, *rid, rv)) {
-				rman_release_resource(rv);
-				return (NULL);
-			}
-		} 
+	if (flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
+		}
 	}
 	return (rv);
 }
@@ -334,16 +331,27 @@
 i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
+	struct i80321_pci_softc *sc = device_get_softc(bus);	
 	u_long p;
 	int error;
-	
-	if (type == SYS_RES_MEMORY) {
-		error = bus_space_map(rman_get_bustag(r),
-		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		/*
+		 * XXX: We rely on having the bushandle initially set to the
+		 * start of the PCI memio window above.
+		 */
+		error = bus_space_map(sc->sc_pcimem, rman_get_bushandle(r) +
+		    rman_get_start(r), rman_get_size(r), 0, &p);
 		if (error) 
 			return (error);
+		rman_set_bustag(r, sc->sc_pcimem);
 		rman_set_bushandle(r, p);
-	
+		break;
+	case SYS_RES_IOPORT:
+		rman_set_bustag(r, sc->sc_pciio);
+		rman_set_bushandle(r, sc->sc_io);
+		break;
 	}
 	return (rman_activate_resource(r));
 }
--- //depot/vendor/freebsd/src/sys/arm/xscale/i80321/obio.c	2007/07/27 14:57:30
+++ //depot/user/jhb/acpipci/arm/xscale/i80321/obio.c	2007/09/24 17:24:13
@@ -98,8 +98,6 @@
 {
 	struct resource *rv;
 	struct rman *rm;
-	bus_space_tag_t bt = NULL;
-	bus_space_handle_t bh = 0;
 	struct obio_softc *sc = device_get_softc(bus);
 
 	switch (type) {
@@ -110,24 +108,24 @@
 		return (NULL);
 	case SYS_RES_IOPORT:
 		rm = &sc->oba_rman;
-		bt = sc->oba_st;
-		bh = sc->oba_addr;
-		start = bh;
+		start = sc->oba_addr;
 		break;
 	default:
 		return (NULL);
 	}
 
-
-	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
 	if (rv == NULL) 
 		return (NULL);
-	if (type == SYS_RES_IRQ)
-		return (rv);
 	rman_set_rid(rv, *rid);
-	rman_set_bustag(rv, bt);
-	rman_set_bushandle(rv, bh);
 	
+	if (flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}
 	return (rv);
 
 }
@@ -136,8 +134,15 @@
 obio_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
-	return (0);
+	struct obio_softc *sc = device_get_softc(bus);
+
+	if (type == SYS_RES_IOPORT) {
+		rman_set_bustag(r, sc->oba_st);
+		rman_set_bushandle(r, sc->oba_addr);
+	}
+	return (rman_activate_resource(r));
 }
+
 static device_method_t obio_methods[] = {
 	DEVMETHOD(device_probe, obio_probe),
 	DEVMETHOD(device_attach, obio_attach),
--- //depot/vendor/freebsd/src/sys/arm/xscale/i8134x/i81342_pci.c	2007/09/30 11:08:30
+++ //depot/user/jhb/acpipci/arm/xscale/i8134x/i81342_pci.c	2007/12/20 23:44:30
@@ -334,8 +334,7 @@
 	struct i81342_pci_softc *sc = device_get_softc(bus);	
 	struct resource *rv;
 	struct rman *rm;
-	bus_space_tag_t bt = NULL;
-	bus_space_handle_t bh = 0;
+	u_long off;
 
 	switch (type) {
 	case SYS_RES_IRQ:
@@ -343,41 +342,30 @@
 		break;
 	case SYS_RES_MEMORY:
 		rm = &sc->sc_mem_rman;
-		bt = &sc->sc_pcimem;
-		bh = 0;
 		break;
 	case SYS_RES_IOPORT:
 		rm = &sc->sc_io_rman;
-		bt = &sc->sc_pciio;
-		bh = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
+		off = sc->sc_is_atux ? IOP34X_PCIX_OIOBAR_VADDR :
 		    IOP34X_PCIE_OIOBAR_VADDR;
-		start += bh;
-		end += bh;
+		start += off;
+		end += off;
 		break;
 	default:
 		return (NULL);
 	}
 
-	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
 	if (rv == NULL)
 		return (NULL);
 	rman_set_rid(rv, *rid);
-	if (type != SYS_RES_IRQ) {
-		if (type == SYS_RES_MEMORY)
-			bh += (rman_get_start(rv));
-		rman_set_bustag(rv, bt);
-		rman_set_bushandle(rv, bh);
-		if (flags & RF_ACTIVE) {
-			if (bus_activate_resource(child, type, *rid, rv)) {
-				rman_release_resource(rv);
-				return (NULL);
-			}
-		} 
-	}
+	if (flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	} 
 	return (rv);
-
-
-	return (NULL);
 }
 
 static int
@@ -386,14 +374,23 @@
 {
 	u_long p;
 	int error;
-	
-	if (type == SYS_RES_MEMORY) {
-		error = bus_space_map(rman_get_bustag(r),
-		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		error = bus_space_map(&sc->sc_pcimem, rman_get_start(r),
+		    rman_get_size(r), 0, &p);
 		if (error)
 			return (error);
+		rman_set_bustag(r, &sc->sc_pcimem);
 		rman_set_bushandle(r, p);
-	
+		break;
+	case SYS_RES_IOPORT:
+		rman_set_bus_tag(r, &sc->sc_pciio);
+		if (sc->sc_is_atux)
+			rman_set_bushandle(r, IOP34X_PCIX_OIOBAR_VADDR);
+		else
+			rman_set_bushandle(r, IOP34X_PCIE_OIOBAR_VADDR);
+		break;
 	}
 	return (rman_activate_resource(r));
 }
--- //depot/vendor/freebsd/src/sys/arm/xscale/i8134x/obio.c	2007/07/27 14:57:30
+++ //depot/user/jhb/acpipci/arm/xscale/i8134x/obio.c	2007/12/20 23:44:30
@@ -93,8 +93,6 @@
 {
 	struct resource *rv;
 	struct rman *rm;
-	bus_space_tag_t bt = NULL;
-	bus_space_handle_t bh = 0;
 	struct obio_softc *sc = device_get_softc(bus);
 	int unit = device_get_unit(child);
 
@@ -110,14 +108,11 @@
 		return (NULL);
 	case SYS_RES_IOPORT:
 		rm = &sc->oba_rman;
-		bt = sc->oba_st;
 		if (unit == 0) {
-			bh = IOP34X_UART0_VADDR;
-			start = bh;
+			start = IOP34X_UART0_VADDR;
 			end = IOP34X_UART1_VADDR;
 		} else {
-			bh = IOP34X_UART1_VADDR;
-			start = bh;
+			start = IOP34X_UART1_VADDR;
 			end = start + 0x40;
 		}
 		break;
@@ -126,15 +121,18 @@
 	}
 
 
-	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
 	if (rv == NULL) 
 		return (NULL);
-	if (type == SYS_RES_IRQ)
-		return (rv);
 	rman_set_rid(rv, *rid);
-	rman_set_bustag(rv, bt);
-	rman_set_bushandle(rv, bh);
-	
+	if (flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}		
+
 	return (rv);
 
 }
@@ -143,8 +141,16 @@
 obio_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
-	return (0);
+
+	switch (type) {
+	case SYS_RES_IOPORT:
+		rman_set_bustag(r, sc->oba_st);
+		rman_set_bushandle(r, rman_get_start(r));
+		break;
+	}
+	return (rman_activate_resource(r));
 }
+
 static device_method_t obio_methods[] = {
 	DEVMETHOD(device_probe, obio_probe),
 	DEVMETHOD(device_attach, obio_attach),
--- //depot/vendor/freebsd/src/sys/arm/xscale/ixp425/ixp425.c	2007/05/29 18:18:31
+++ //depot/user/jhb/acpipci/arm/xscale/ixp425/ixp425.c	2007/09/24 17:24:13
@@ -319,7 +319,7 @@
 	struct ixp425_softc *sc = device_get_softc(dev);
 	struct rman *rmanp;
 	struct resource *rv;
-	uint32_t vbase, addr;
+	uint32_t addr;
 	int irq;
 
 	switch (type) {
@@ -329,7 +329,7 @@
 		if (BUS_READ_IVAR(dev, child, IXP425_IVAR_IRQ, &irq) == 0)
 			start = end = irq;
 		rv = rman_reserve_resource(rmanp, start, end, count,
-			flags, child);
+			flags & ~RF_ACTIVE, child);
 		if (rv != NULL)
 			rman_set_rid(rv, *rid);
 		break;
@@ -344,21 +344,45 @@
 		if (getvbase(start, end - start, &vbase))
 			return NULL;
 		rv = rman_reserve_resource(rmanp, start, end, count,
-			flags, child);
-		if (rv != NULL) {
+			flags & ~RF_ACTIVE, child);
+		if (rv != NULL)
 			rman_set_rid(rv, *rid);
-			if (strcmp(device_get_name(child), "uart") == 0)
-				rman_set_bustag(rv, &ixp425_a4x_bs_tag);
-			else
-				rman_set_bustag(rv, sc->sc_iot);
-			rman_set_bushandle(rv, vbase);
-		}
 		break;
 	default:
 		rv = NULL;
 		break;
 	}
-	return rv;
+
+	if (rv != NULL && flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}
+
+	return (rv);
+}
+
+static int
+ixp425_activate_resource(device_t dev, device_t child, int type, int rid,
+    struct resource *r)
+{
+	struct ixp425_softc *sc = device_get_softc(dev);
+	int error;
+	uint32_t vbase;
+
+	if (type == SYS_RES_MEMORY) {
+		error = getvbase(rman_get_start(r), rman_get_size(r), &vbase);
+		if (error)
+			return (error);
+		if (strcmp(device_get_name(child), "uart") == 0)
+			rman_set_bustag(rv, &ixp425_a4x_bs_tag);
+		else
+			rman_set_bustag(rv, sc->sc_iot);
+		rman_set_bushandle(rv, vbase);		
+	}
+
+	return (rman_activate_resource(r));
 }
 
 static int
@@ -409,6 +433,7 @@
 	DEVMETHOD(bus_read_ivar, ixp425_read_ivar),
 
 	DEVMETHOD(bus_alloc_resource, ixp425_alloc_resource),
+	DEVMETHOD(bus_activate_resource, ixp425_activate_resource),
 	DEVMETHOD(bus_setup_intr, ixp425_setup_intr),
 	DEVMETHOD(bus_teardown_intr, ixp425_teardown_intr),
 
--- //depot/vendor/freebsd/src/sys/arm/xscale/ixp425/ixp425_pci.c	2007/09/30 11:08:30
+++ //depot/user/jhb/acpipci/arm/xscale/ixp425/ixp425_pci.c	2007/10/08 16:52:09
@@ -279,12 +279,10 @@
 ixppcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
 {
-	bus_space_tag_t tag;
 	struct ixppcib_softc *sc = device_get_softc(bus);
 	struct rman *rmanp;
 	struct resource *rv;
 
-	tag = NULL; /* shut up stupid gcc */
 	rv = NULL;
 	switch (type) {
 	case SYS_RES_IRQ:
@@ -293,28 +291,25 @@
 
 	case SYS_RES_IOPORT:
 		rmanp = &sc->sc_io_rman;
-		tag = &sc->sc_pci_iot;
 		break;
 
 	case SYS_RES_MEMORY:
 		rmanp = &sc->sc_mem_rman;
-		tag = &sc->sc_pci_memt;
 		break;
 
 	default:
 		return (rv);
 	}
 
-	rv = rman_reserve_resource(rmanp, start, end, count, flags, child);
-	if (rv != NULL) {
-		rman_set_rid(rv, *rid);
-		if (type == SYS_RES_IOPORT) {
-			rman_set_bustag(rv, tag);
-			rman_set_bushandle(rv, rman_get_start(rv));
-		} else if (type == SYS_RES_MEMORY) {
-			rman_set_bustag(rv, tag);
-			rman_set_bushandle(rv, rman_get_bushandle(sc->sc_mem) +
-			    (rman_get_start(rv) - IXP425_PCI_MEM_HWBASE));
+	rv = rman_reserve_resource(rmanp, start, end, count, flags & ~RF_ACTIVE,
+	    child);
+	if (rv == NULL)
+		return (NULL);
+	rman_set_rid(rv, *rid);
+	if (flags & RF_ACTIVE) {
+		if (bus_activate_resource(child, type, *rid, rv)) {
+			rman_release_resource(rv);
+			return (NULL);
 		}
 	}
 
@@ -325,9 +320,21 @@
 ixppcib_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r) 
 {
+	struct ixppcib_softc *sc = device_get_softc(bus);
 
-	device_printf(bus, "%s called activate_resource\n", device_get_nameunit(child));
-	return (ENXIO);
+	switch (type) {
+	case SYS_RES_IOPORT:
+		rman_set_bustag(r, &sc->sc_pci_iot);
+		rman_set_bushandle(r, rman_get_start(r));
+		break;
+	case SYS_RES_MEMORY:
+		rman_set_bustag(r, &sc->sc_pci_memt);
+		rman_set_bushandle(r, rman_get_bushandle(sc->sc_mem) +
+		    (rman_get_start(r) - IXP425_PCI_MEM_HWBASE));
+		break;
+	}
+		
+	return (rman_activate_resource(r));
 }
 
 static int


-- 
John Baldwin



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