From 397c30a83d0680005b0723d7f244116c639d66c9 Mon Sep 17 00:00:00 2001
From: John Baldwin <jhb@FreeBSD.org>
Date: Wed, 21 Mar 2007 15:39:11 +0000
Subject: [PATCH] Change acpi's handling of suballocating system resources to
 be a little simpler.  It now can just use rman_is_region_manager() during
 acpi_release_resource() to see if the the resource is suballocated from a
 system resource.  Also, the driver no longer needs MD knowledge about how to
 setup bus space tags and handles when doing a suballocation, but can simply
 rely on bus_activate_resource() in the parent setting all that up.

---
 sys/dev/acpica/acpi.c | 94 ++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 55 deletions(-)

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 448c626916c1..881220387e23 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -106,8 +106,6 @@ static int	acpi_write_ivar(device_t dev, device_t child, int index,
 			uintptr_t value);
 static struct resource_list *acpi_get_rlist(device_t dev, device_t child);
 static int	acpi_sysres_alloc(device_t dev);
-static struct resource_list_entry *acpi_sysres_find(device_t dev, int type,
-		    u_long addr);
 static struct resource *acpi_alloc_resource(device_t bus, device_t child,
 			int type, int *rid, u_long start, u_long end,
 			u_long count, u_int flags);
@@ -958,31 +956,6 @@ acpi_sysres_alloc(device_t dev)
     return (0);
 }
 
-/* Find if we manage a given resource. */
-static struct resource_list_entry *
-acpi_sysres_find(device_t dev, int type, u_long addr)
-{
-    struct resource_list *rl;
-    struct resource_list_entry *rle;
-
-    ACPI_SERIAL_ASSERT(acpi);
-
-    /* We only consider IO and memory resources for our pool. */
-    rle = NULL;
-    if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
-	goto out;
-
-    rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
-    STAILQ_FOREACH(rle, rl, link) {
-	if (type == rle->type && addr >= rle->start &&
-	    addr < rle->start + rle->count)
-	    break;
-    }
-
-out:
-    return (rle);
-}
-
 static struct resource *
 acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
@@ -995,6 +968,19 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
     struct rman *rm;
 
     res = NULL;
+
+    /* We only handle memory and IO resources through rman. */
+    switch (type) {
+    case SYS_RES_IOPORT:
+	rm = &acpi_rman_io;
+	break;
+    case SYS_RES_MEMORY:
+	rm = &acpi_rman_mem;
+	break;
+    default:
+	rm = NULL;
+    }
+	    
     ACPI_SERIAL_BEGIN(acpi);
 
     /*
@@ -1011,35 +997,19 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
 	count = rle->count;
     }
 
-    /* If we don't manage this address, pass the request up to the parent. */
-    rle = acpi_sysres_find(bus, type, start);
-    if (rle == NULL) {
+    /*
+     * If this is an allocation of a specific range, see if we can satisfy
+     * the request from our system resource regions.  If we can't, pass the
+     * request up to the parent.
+     */
+    if (!(start == 0UL && end == ~0UL) && rm != NULL)
+	res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+	    child);
+    if (res == NULL) {
 	res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid,
 	    start, end, count, flags);
     } else {
-
-	/* We only handle memory and IO resources through rman. */
-	switch (type) {
-	case SYS_RES_IOPORT:
-	    rm = &acpi_rman_io;
-	    break;
-	case SYS_RES_MEMORY:
-	    rm = &acpi_rman_mem;
-	    break;
-	default:
-	    panic("acpi_alloc_resource: invalid res type %d", type);
-	}
-
-	/* If we do know it, allocate it from the local pool. */
-	res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
-	    child);
-	if (res == NULL)
-	    goto out;
-
-	/* Copy the bus tag and handle from the pre-allocated resource. */
 	rman_set_rid(res, *rid);
-	rman_set_bustag(res, rman_get_bustag(rle->res));
-	rman_set_bushandle(res, rman_get_start(res));
 
 	/* If requested, activate the resource using the parent's method. */
 	if (flags & RF_ACTIVE)
@@ -1075,15 +1045,29 @@ static int
 acpi_release_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
+    struct rman *rm;
     int ret;
 
+    /* We only handle memory and IO resources through rman. */
+    switch (type) {
+    case SYS_RES_IOPORT:
+	rm = &acpi_rman_io;
+	break;
+    case SYS_RES_MEMORY:
+	rm = &acpi_rman_mem;
+	break;
+    default:
+	rm = NULL;
+    }
+
     ACPI_SERIAL_BEGIN(acpi);
 
     /*
-     * If we know about this address, deactivate it and release it to the
-     * local pool.  If we don't, pass this request up to the parent.
+     * If this resource belongs to one of our internal managers,
+     * deactivate it and release it to the local pool.  If it doesn't,
+     * pass this request up to the parent.
      */
-    if (acpi_sysres_find(bus, type, rman_get_start(r)) != NULL) {
+    if (rm != NULL && rman_is_region_manager(r, rm)) {
 	if (rman_get_flags(r) & RF_ACTIVE) {
 	    ret = bus_deactivate_resource(child, type, rid, r);
 	    if (ret != 0)