tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bus_space(9) overrides & resource reservations



On Fri, May 28, 2010 at 03:37:13AM +0900, Izumi Tsutsui wrote:
> > It sounds like you may be concerned that I intend bus_space_tag_create()
> > to replace comparable MD routines such as bus_space_tag_alloc() on
> > sparc.  I do not.
> > 
> > If the name troubles you, is bus_space_tag_refine() better?
> 
> Aren't many other guys confused by the name "create tag"?
> 
> IMO "refine" is also too vague. It should imply what actually
> the function does, i.e just adding MI hooks.
> (no actual implementation in your patch so I can't comment)

Doh!  I'd added the hooks without adding bus_space_create_tag().  Here
is a new patch that has _create_tag() in it.

Dave

-- 
David Young             OJC Technologies
dyoung%ojctech.com@localhost      Urbana, IL * (217) 278-3933
Index: sys/arch/x86/include/bus.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/bus.h,v
retrieving revision 1.20
diff -u -p -r1.20 bus.h
--- sys/arch/x86/include/bus.h  28 Apr 2010 19:17:04 -0000      1.20
+++ sys/arch/x86/include/bus.h  28 May 2010 23:11:09 -0000
@@ -80,11 +80,24 @@
 typedef paddr_t bus_addr_t;
 typedef size_t bus_size_t;
 
-struct bus_space_tag {
-       int bst_type;
+struct bus_space_reservation {
+       bus_addr_t bsr_start;
+       bus_size_t bsr_size;
 };
 
+typedef struct bus_space_reservation bus_space_reservation_t;
+
+struct bus_space_tag;
 typedef        struct bus_space_tag *bus_space_tag_t;
+
+struct bus_space_tag {
+       int                                     bst_type;
+       bus_space_tag_t                         bst_super;
+       uint64_t                                bst_present;
+       const struct bus_space_overrides        *bst_ov;
+       void                                    *bst_ctx;
+};
+
 typedef        vaddr_t bus_space_handle_t;
 
 extern bus_space_tag_t x86_bus_space_mem;
Index: sys/arch/x86/x86/bus_space.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/bus_space.c,v
retrieving revision 1.29
diff -u -p -r1.29 bus_space.c
--- sys/arch/x86/x86/bus_space.c        10 May 2010 18:46:58 -0000      1.29
+++ sys/arch/x86/x86/bus_space.c        28 May 2010 23:11:09 -0000
@@ -37,6 +37,7 @@ __KERNEL_RCSID(0, "$NetBSD: bus_space.c,
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/extent.h>
+#include <sys/kmem.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -156,42 +157,49 @@ int
 bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
                int flags, bus_space_handle_t *bshp)
 {
+       bus_space_reservation_t bsr;
        int error;
-       struct extent *ex;
 
-       /*
-        * Pick the appropriate extent map.
-        */
-       if (x86_bus_space_is_io(t)) {
-               if (flags & BUS_SPACE_MAP_LINEAR)
-                       return (EOPNOTSUPP);
-               ex = ioport_ex;
-       } else if (x86_bus_space_is_mem(t))
-               ex = iomem_ex;
-       else
-               panic("x86_memio_map: bad bus space tag");
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_MAP) != 0) {
+               return (*t->bst_ov->ov_space_map)(t->bst_ctx, t, bpa, size,
+                   flags, bshp);
+       }
+       if (t->bst_super != NULL)
+               return bus_space_map(t->bst_super, bpa, size, flags, bshp);
+
+       error = bus_space_reserve(t, bpa, size, flags, &bsr);
+       if (error != 0)
+               return error;
+
+       error = bus_space_reservation_map(t, &bsr, flags, bshp);
+       if (error != 0)
+               bus_space_release(t, &bsr);
 
-       /*
-        * Before we go any further, let's make sure that this
-        * region is available.
-        */
-       error = extent_alloc_region(ex, bpa, size,
-           EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
-       if (error)
-               return (error);
+       return error;
+}
+
+int
+bus_space_reservation_map(bus_space_tag_t t, bus_space_reservation_t *bsr,
+    int flags, bus_space_handle_t *bshp)
+{
+       bus_addr_t bpa;
+       bus_size_t size;
+
+       bpa = bsr->bsr_start;
+       size = bsr->bsr_size;
 
        /*
         * For I/O space, that's all she wrote.
         */
        if (x86_bus_space_is_io(t)) {
                *bshp = bpa;
-               return (0);
+               return 0;
        }
 
 #ifndef XEN
        if (bpa >= IOM_BEGIN && (bpa + size) != 0 && (bpa + size) <= IOM_END) {
                *bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
-               return(0);
+               return 0;
        }
 #endif /* !XEN */
 
@@ -199,18 +207,8 @@ bus_space_map(bus_space_tag_t t, bus_add
         * For memory space, map the bus physical address to
         * a kernel virtual address.
         */
-       error = x86_mem_add_mapping(bpa, size,
-               (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
-       if (error) {
-               if (extent_free(ex, bpa, size, EX_NOWAIT |
-                   (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-                       printf("x86_memio_map: pa 0x%jx, size 0x%jx\n",
-                           (uintmax_t)bpa, (uintmax_t)size);
-                       printf("x86_memio_map: can't free region\n");
-               }
-       }
-
-       return (error);
+       return x86_mem_add_mapping(bpa, size,
+           (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
 }
 
 int
@@ -237,10 +235,56 @@ _x86_memio_map(bus_space_tag_t t, bus_ad
 }
 
 int
-bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
-               bus_size_t size, bus_size_t alignment, bus_size_t boundary,
-               int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+bus_space_reserve(bus_space_tag_t t,
+    bus_addr_t bpa,
+    bus_size_t size,
+    int flags, bus_space_reservation_t *bsrp)
+{
+       struct extent *ex;
+       int error;
+
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_RESERVE) != 0) {
+               return (*t->bst_ov->ov_space_reserve)(t->bst_ctx, t,
+                   bpa, size, flags, bsrp);
+       }
+       if (t->bst_super != NULL)
+               return bus_space_reserve(t->bst_super, bpa, size, flags, bsrp);
+
+       /*
+        * Pick the appropriate extent map.
+        */
+       if (x86_bus_space_is_io(t)) {
+               if (flags & BUS_SPACE_MAP_LINEAR)
+                       return (EOPNOTSUPP);
+               ex = ioport_ex;
+       } else if (x86_bus_space_is_mem(t))
+               ex = iomem_ex;
+       else
+               panic("x86_memio_alloc: bad bus space tag");
+
+       /*
+        * Before we go any further, let's make sure that this
+        * region is available.
+        */
+       error = extent_alloc_region(ex, bpa, size,
+           EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
+
+       if (error != 0)
+               return error;
+
+       bsrp->bsr_start = bpa;
+       bsrp->bsr_size = size;
+
+       return 0;
+}
+
+int
+bus_space_reserve_subregion(bus_space_tag_t t,
+    bus_addr_t rstart, bus_addr_t rend,
+    bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+    int flags, bus_space_reservation_t *bsrp)
 {
+       bus_space_reservation_t bsr;
        struct extent *ex;
        u_long bpa;
        int error;
@@ -274,32 +318,78 @@ bus_space_alloc(bus_space_tag_t t, bus_a
        if (error)
                return (error);
 
+       bsr.bsr_start = bpa;
+       bsr.bsr_size = size;
+
+       *bsrp = bsr;
+
+       return 0;
+}
+
+void
+bus_space_release(bus_space_tag_t t, bus_space_reservation_t *bsr)
+{
+       struct extent *ex;
+
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_RELEASE) != 0) {
+               (*t->bst_ov->ov_space_release)(t->bst_ctx, t, bsr);
+               return;
+       }
+       if (t->bst_super != NULL) {
+               bus_space_release(t->bst_super, bsr);
+               return;
+       }
        /*
-        * For I/O space, that's all she wrote.
+        * Pick the appropriate extent map.
         */
        if (x86_bus_space_is_io(t)) {
-               *bshp = *bpap = bpa;
-               return (0);
+               ex = ioport_ex;
+       } else if (x86_bus_space_is_mem(t))
+               ex = iomem_ex;
+       else
+               panic("x86_memio_alloc: bad bus space tag");
+
+       if (extent_free(ex, bsr->bsr_start, bsr->bsr_size, EX_NOWAIT |
+           (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+               printf("%s: pa 0x%jx, size 0x%jx\n", __func__,
+                   (uintmax_t)bsr->bsr_start, (uintmax_t)bsr->bsr_size);
+               printf("%s: can't free region\n", __func__);
+       }
+}
+
+int
+bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
+               bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+               int flags, bus_addr_t *bpap, bus_space_handle_t *bshp)
+{
+       bus_space_reservation_t bsr;
+       int error;
+
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_ALLOC) != 0) {
+               return (*t->bst_ov->ov_space_alloc)(t->bst_ctx, t, rstart, rend,
+                   size, alignment, boundary, flags, bpap, bshp);
+       }
+       if (t->bst_super != NULL) {
+               return bus_space_alloc(t->bst_super, rstart, rend, size,
+                   alignment, boundary, flags, bpap, bshp);
        }
 
        /*
-        * For memory space, map the bus physical address to
-        * a kernel virtual address.
+        * Do the requested allocation.
         */
-       error = x86_mem_add_mapping(bpa, size,
-           (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
-       if (error) {
-               if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
-                   (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-                       printf("x86_memio_alloc: pa 0x%jx, size 0x%jx\n",
-                           (uintmax_t)bpa, (uintmax_t)size);
-                       printf("x86_memio_alloc: can't free region\n");
-               }
-       }
+       error = bus_space_reserve_subregion(t, rstart, rend, size, alignment,
+           boundary, flags, &bsr);
 
-       *bpap = bpa;
+       if (error != 0)
+               return error;
 
-       return (error);
+       error = bus_space_reservation_map(t, &bsr, flags, bshp);
+       if (error != 0)
+               bus_space_release(t, &bsr);
+
+       *bpap = bsr.bsr_start;
+
+       return error;
 }
 
 int
@@ -410,10 +500,10 @@ _x86_memio_unmap(bus_space_tag_t t, bus_
        }
 }
 
-void
-bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+static void
+bus_space_reservation_unmap1(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size, bus_addr_t *bpap)
 {
-       struct extent *ex;
        u_long va, endva;
        bus_addr_t bpa;
 
@@ -421,11 +511,8 @@ bus_space_unmap(bus_space_tag_t t, bus_s
         * Find the correct extent and bus physical address.
         */
        if (x86_bus_space_is_io(t)) {
-               ex = ioport_ex;
                bpa = bsh;
        } else if (x86_bus_space_is_mem(t)) {
-               ex = iomem_ex;
-
                if (bsh >= atdevbase && (bsh + size) != 0 &&
                    (bsh + size) <= (atdevbase + IOM_SIZE)) {
                        bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
@@ -452,21 +539,51 @@ bus_space_unmap(bus_space_tag_t t, bus_s
                uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
        } else
                panic("x86_memio_unmap: bad bus space tag");
-
 ok:
-       if (extent_free(ex, bpa, size,
-           EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
-               printf("x86_memio_unmap: %s 0x%jx, size 0x%jx\n",
-                   x86_bus_space_is_io(t) ? "port" : "pa",
-                   (uintmax_t)bpa, (uintmax_t)size);
-               printf("x86_memio_unmap: can't free region\n");
+       if (bpap != NULL)
+               *bpap = bpa;
+}
+
+void
+bus_space_reservation_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size)
+{
+       bus_space_reservation_unmap1(t, bsh, size, NULL);
+}
+
+void
+bus_space_unmap(bus_space_tag_t t, const bus_space_handle_t bsh,
+    const bus_size_t size)
+{
+       bus_space_reservation_t bsr;
+
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_UNMAP) != 0) {
+               (*t->bst_ov->ov_space_unmap)(t->bst_ctx, t, bsh, size);
+               return;
+       }
+       if (t->bst_super != NULL) {
+               bus_space_unmap(t->bst_super, bsh, size);
+               return;
        }
+
+       bus_space_reservation_unmap1(t, bsh, size, &bsr.bsr_start);
+
+       bsr.bsr_size = size;
+       bus_space_release(t, &bsr);
 }
 
 void
 bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
 {
 
+       if ((t->bst_present & BUS_SPACE_OVERRIDE_FREE) != 0) {
+               (*t->bst_ov->ov_space_free)(t->bst_ctx, t, bsh, size);
+               return;
+       }
+       if (t->bst_super != NULL) {
+               bus_space_free(t->bst_super, bsh, size);
+               return;
+       }
        /* bus_space_unmap() does all that we need to do. */
        bus_space_unmap(t, bsh, size);
 }
@@ -716,3 +833,69 @@ bus_space_vaddr(bus_space_tag_t tag, bus
 
        return x86_bus_space_is_mem(tag) ? (void *)bsh : NULL;
 }
+
+static const void *
+bit_to_function_pointer(const struct bus_space_overrides *ov, uint64_t bit)
+{
+       switch (bit) {
+       case BUS_SPACE_OVERRIDE_MAP:
+               return ov->ov_space_map;
+       case BUS_SPACE_OVERRIDE_UNMAP:
+               return ov->ov_space_unmap;
+       case BUS_SPACE_OVERRIDE_ALLOC:
+               return ov->ov_space_alloc;
+       case BUS_SPACE_OVERRIDE_FREE:
+               return ov->ov_space_free;
+       case BUS_SPACE_OVERRIDE_RESERVE:
+               return ov->ov_space_reserve;
+       case BUS_SPACE_OVERRIDE_RELEASE:
+               return ov->ov_space_release;
+       default:
+               return NULL;
+       }
+}
+
+void
+bus_space_tag_destroy(bus_space_tag_t bst)
+{
+       kmem_free(bst, sizeof(struct bus_space_tag));
+}
+
+int
+bus_space_tag_create(bus_space_tag_t obst, const uint64_t present,
+    const struct bus_space_overrides *ov, void *ctx, bus_space_tag_t *bstp)
+{
+       uint64_t bit, bits, nbits;
+       bus_space_tag_t bst;
+       const void *fp;
+
+       if (ov == NULL || present == 0)
+               return EINVAL;
+
+       bst = kmem_alloc(sizeof(struct bus_space_tag), KM_SLEEP);
+
+       if (pc == NULL)
+               return ENOMEM;
+
+       bst->bst_super = obst;
+
+       for (bits = present; bits != 0; bits = nbits) {
+               nbits = bits & (bits - 1);
+               bit = nbits ^ bits;
+               if ((fp = bit_to_function_pointer(ov, bit)) == NULL) {
+                       printf("%s: missing bit %" PRIx64 "\n", __func__, bit);
+                       goto einval;
+               }
+       }
+
+       bst->bst_ov = ov;
+       bst->bst_present = present;
+       bst->bst_ctx = ctx;
+
+       *bstp = bst;
+
+       return 0;
+einval:
+       kmem_free(bst, sizeof(struct bus_space_tag));
+       return EINVAL;
+}
Index: sys/sys/bus.h
===================================================================
RCS file: /cvsroot/src/sys/sys/bus.h,v
retrieving revision 1.3
diff -u -p -r1.3 bus.h
--- sys/sys/bus.h       19 Apr 2010 18:24:27 -0000      1.3
+++ sys/sys/bus.h       28 May 2010 23:11:09 -0000
@@ -31,48 +31,47 @@
 
 #include <machine/bus.h>
 
-struct bus_space_reservation;
-
-typedef struct bus_space_reservation /* {
-       bus_addr_t      sr_addr;
-       bus_size_t      sr_size;
-} */ bus_space_reservation_t;
-
 enum bus_space_override_idx {
-         BUS_SPACE_OVERRIDE_SPACE_MAP          = __BIT(0)
-       , BUS_SPACE_OVERRIDE_SPACE_UNMAP        = __BIT(1)
-       , BUS_SPACE_OVERRIDE_SPACE_ALLOC        = __BIT(2)
-       , BUS_SPACE_OVERRIDE_SPACE_FREE         = __BIT(3)
-       , BUS_SPACE_OVERRIDE_SPACE_EXTEND       = __BIT(4)
-       , BUS_SPACE_OVERRIDE_SPACE_TRIM         = __BIT(5)
+         BUS_SPACE_OVERRIDE_MAP        = __BIT(0)
+       , BUS_SPACE_OVERRIDE_UNMAP      = __BIT(1)
+       , BUS_SPACE_OVERRIDE_ALLOC      = __BIT(2)
+       , BUS_SPACE_OVERRIDE_FREE       = __BIT(3)
+       , BUS_SPACE_OVERRIDE_RESERVE    = __BIT(4)
+       , BUS_SPACE_OVERRIDE_RELEASE    = __BIT(5)
+#if 0
+       , BUS_SPACE_OVERRIDE_EXTEND     = __BIT(6)
+       , BUS_SPACE_OVERRIDE_TRIM       = __BIT(7)
+#endif
 };
 
 /* Only add new members at the end of this struct! */
 struct bus_space_overrides {
-       int (*bs_space_map)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
+       int (*ov_space_map)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
            int, bus_space_handle_t *);
 
-       void (*bs_space_unmap)(void *, bus_space_tag_t, bus_space_handle_t,
+       void (*ov_space_unmap)(void *, bus_space_tag_t, bus_space_handle_t,
            bus_size_t);
 
-       int (*bs_space_alloc)(void *, bus_space_tag_t, bus_addr_t, bus_addr_t,
+       int (*ov_space_alloc)(void *, bus_space_tag_t, bus_addr_t, bus_addr_t,
            bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *,
            bus_space_handle_t *);
 
-       void (*bs_space_free)(void *, bus_space_tag_t, bus_space_handle_t,
+       void (*ov_space_free)(void *, bus_space_tag_t, bus_space_handle_t,
            bus_size_t);
 
-       int (*bs_space_reserve)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
-           bus_space_reservation_t *);
-
-       void (*bus_space_release)(void *, bus_space_tag_t,
-           bus_space_reservation_t);
+       int (*ov_space_reserve)(void *, bus_space_tag_t, bus_addr_t, bus_size_t,
+           int, bus_space_reservation_t *);
 
-       int (*bs_space_extend)(void *, bus_space_tag_t, bus_space_reservation_t,
-           bus_size_t, bus_size_t);
+       void (*ov_space_release)(void *, bus_space_tag_t,
+           bus_space_reservation_t *);
 
-       void (*bs_space_trim)(void *, bus_space_tag_t, bus_space_reservation_t,
-           bus_size_t, bus_size_t);
+#if 0
+       int (*ov_space_extend)(void *, bus_space_tag_t,
+           bus_space_reservation_t *, bus_size_t, bus_size_t);
+
+       void (*ov_space_trim)(void *, bus_space_tag_t,
+           bus_space_reservation_t *, bus_size_t, bus_size_t);
+#endif
 };
 
 bool   bus_space_is_equal(bus_space_tag_t, bus_space_tag_t);
@@ -84,20 +83,33 @@ void        bus_space_tag_destroy(bus_space_tag
 /* Reserve a region of bus space.  Reserved bus space cannot be allocated
  * with bus_space_alloc().  Reserved space has not been bus_space_map()'d.
  */
-int    bus_space_reserve(bus_space_tag_t, bus_addr_t, bus_size_t,
+int    bus_space_reserve(bus_space_tag_t, bus_addr_t, bus_size_t, int,
                          bus_space_reservation_t *);
 
+int
+bus_space_reserve_subregion(bus_space_tag_t,
+    bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, bus_size_t,
+    int, bus_space_reservation_t *);
+
 /* Cancel a reservation. */
-void   bus_space_release(bus_space_tag_t, bus_space_reservation_t);
+void   bus_space_release(bus_space_tag_t, bus_space_reservation_t *);
+
+int bus_space_reservation_map(bus_space_tag_t, bus_space_reservation_t *,
+    int, bus_space_handle_t *);
+
+void bus_space_reservation_unmap(bus_space_tag_t, bus_space_handle_t,
+    bus_size_t);
 
+#if 0
 /* Extend a reservation to the left and/or to the right.  The extension
  * has not been bus_space_map()'d.
  */
-int    bus_space_extend(bus_space_tag_t, bus_space_reservation_t, bus_size_t,
+int    bus_space_extend(bus_space_tag_t, bus_space_reservation_t *, bus_size_t,
                         bus_size_t);
 
 /* Trim bus space from a reservation on the left and/or on the right. */
-void   bus_space_trim(bus_space_tag_t, bus_space_reservation_t, bus_size_t,
+void   bus_space_trim(bus_space_tag_t, bus_space_reservation_t *, bus_size_t,
                       bus_size_t);
+#endif
 
 #endif /* _SYS_BUS_H_ */
Index: sys/kern/kern_stub.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_stub.c,v
retrieving revision 1.28
diff -u -p -r1.28 kern_stub.c
--- sys/kern/kern_stub.c        28 Apr 2010 20:33:52 -0000      1.28
+++ sys/kern/kern_stub.c        28 May 2010 23:11:09 -0000
@@ -127,6 +127,8 @@ __weak_alias(spldebug_stop, voidop);
 __weak_alias(machdep_init,nullop);
 __weak_alias(pci_chipset_tag_create, eopnotsupp);
 __weak_alias(pci_chipset_tag_destroy, voidop);
+__weak_alias(bus_space_reserve, eopnotsupp);
+__weak_alias(bus_space_release, voidop);
 __weak_alias(bus_space_tag_create, eopnotsupp);
 __weak_alias(bus_space_tag_destroy, voidop);
 __weak_alias(bus_space_is_equal, default_bus_space_is_equal);


Home | Main Index | Thread Index | Old Index