diff options
author | Hartmut Brandt <harti@FreeBSD.org> | 2003-07-15 08:59:38 +0000 |
---|---|---|
committer | Hartmut Brandt <harti@FreeBSD.org> | 2003-07-15 08:59:38 +0000 |
commit | 7e9024cdd9a555f05fef1a872eb05e0d4fefebc1 (patch) | |
tree | eac7c97625d7814908b085bb062256b985ea60a7 | |
parent | 8e36ed92f292b37d496c38412f856b3c7df7bc26 (diff) | |
download | src-test2-7e9024cdd9a555f05fef1a872eb05e0d4fefebc1.tar.gz src-test2-7e9024cdd9a555f05fef1a872eb05e0d4fefebc1.zip |
Notes
-rw-r--r-- | share/man/man9/Makefile | 13 | ||||
-rw-r--r-- | share/man/man9/mbpool.9 | 206 | ||||
-rw-r--r-- | sys/conf/NOTES | 2 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/kern/subr_mbpool.c | 399 | ||||
-rw-r--r-- | sys/modules/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/libmbpool/Makefile | 19 | ||||
-rw-r--r-- | sys/sys/mbpool.h | 88 |
9 files changed, 729 insertions, 1 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 8c38020d71a7..82bcd39aebe2 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -53,7 +53,7 @@ MAN= BUF_LOCK.9 BUF_LOCKFREE.9 BUF_LOCKINIT.9 BUF_REFCNT.9 \ kernacc.9 kobj.9 kthread.9 ktr.9 \ lock.9 \ mac.9 \ - make_dev.9 malloc.9 mbchain.9 mbuf.9 mdchain.9 \ + make_dev.9 malloc.9 mbchain.9 mbpool.9 mbuf.9 mdchain.9 \ mi_switch.9 microseq.9 microtime.9 microuptime.9 \ module.9 mtx_pool.9 mutex.9 \ namei.9 \ @@ -361,6 +361,17 @@ MLINKS+=mdchain.9 md_get_mem.9 MLINKS+=mdchain.9 md_get_mbuf.9 MLINKS+=mdchain.9 md_get_uio.9 +MLINKS+=mbpool.9 mbp_create.9 +MLINKS+=mbpool.9 mbp_destroy.9 +MLINKS+=mbpool.9 mbp_alloc.9 +MLINKS+=mbpool.9 mbp_free.9 +MLINKS+=mbpool.9 mbp_ext_free.9 +MLINKS+=mbpool.9 mbp_card_free.9 +MLINKS+=mbpool.9 mbp_count.9 +MLINKS+=mbpool.9 mbp_get.9 +MLINKS+=mbpool.9 mbp_get_keep.9 +MLINKS+=mbpool.9 mbp_sync.9 + MLINKS+=microtime.9 getmicrotime.9 microtime.9 nanotime.9 MLINKS+=microtime.9 getnanotime.9 MLINKS+=microuptime.9 getmicrouptime.9 microuptime.9 nanouptime.9 diff --git a/share/man/man9/mbpool.9 b/share/man/man9/mbpool.9 new file mode 100644 index 000000000000..f40a927dd434 --- /dev/null +++ b/share/man/man9/mbpool.9 @@ -0,0 +1,206 @@ +.\" Copyright (c) 2003 +.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Author: Hartmut Brandt <harti@freebsd.org> +.\" +.\" $FreeBSD$ +.Dd July 15, 2003 +.Dt MBPOOL 9 +.Os FreeBSD +.Sh NAME +.Nm mbpool +.Nd Buffer pools for network interfaces +.Sh SYNOPSIS +.In sys/types.h +.In machine/bus.h +.In sys/mbpool.h +.Vt struct mbpool; +.Ft int +.Fn mbp_create "struct mbpool **mbp" "const char *name" "bus_dma_tag_t dmat" "u_int max_pages" "size_t page_size" "size_t chunk_size" +.Ft void +.Fn mbp_destroy "struct mbpool *mbp" +.Ft void * +.Fn mbp_alloc "struct mbpool *mbp" "bus_addr_t *pa" "uint32_t *hp" +.Ft void +.Fn mbp_free "struct mbpool *mbp" "void *p" +.Ft void +.Fn mbp_ext_free "void *" "void *" +.Ft void +.Fn mbp_card_free "struct mbpool *mbp" +.Ft void +.Fn mbp_count "struct mbpool *mbp" "u_int *used" "u_int *card" "u_int *free" +.Ft void * +.Fn mbp_get "struct mbpool *mbp" "uint32_t h" +.Ft void * +.Fn mbp_get_keep "struct mbpool *mbp" "uint32_t h" +.Ft void +.Fn mbp_sync "struct mbpool *mbp" "uint32_t h" "bus_addr_t off" "bus_size_t len" "u_int op" +.Pp +.Fn MODULE_DEPEND "your_module" "libmbpool" 1 1 1 +.Pp +.Cd options LIBMBPOOL +.Sh DESCRIPTION +Mbuf pools are intented to help drivers for interface cards that need huge +amounts of receive buffers and additionally provides a mapping between these +buffers and 32-bit handles. +.Pp +An example of these cards are the Fore/Marconi ForeRunnerHE cards. These +employ up to 8 receive groups, each with two buffer pools, each of which +can contain up to 8192. This gives a total maximum number of more than +100000 buffers. Even with a more moderate configuration the card eats several +thousand buffers. Each of these buffers must be mapped for DMA. While for +machines without an IOMMU and with lesser than 4GByte memory this is not +a problem, for other machines this may quickly eat up all available IOMMU +address space and/or bounce buffers. On the sparc64 the default IO page size +is 16k, so mapping a simple mbuf wastes 31/32 of the address space. +.Pp +Another problem with most of these cards is that they support putting a 32-bit +handle into the buffer descriptor together with the physical address. +This handle is reflected back to the driver when the buffer is filled and +assists the driver in finding the buffer in host memory. For 32-bit machines +usually the virtual address of the buffer is used as the handle. This does not +work for 64-machines for obvious reasons so a mapping is needed between +these handles and the buffers. This mapping should be possible without +searching lists and the like. +.Pp +An mbuf pool overcomes both problems by allocating DMA-able memory page wise +with a per-pool configurable page size. Each page is divided into a number +equally-sized chunks the last +.Dv MBPOOL_TRAILER_SIZE +of which are used by the pool code (4 bytes). The rest of each chunk is +usable as buffer. +There is a per-pool limit on pages that will be allocated. +.Pp +Additionally the code manages two flags for each buffer: on-card and used. +A buffer may be in one of three states: +.Bl -tag -width XXX +.It free +none of the flags is set. +.It on-card +both flags are set. The buffer is assumed to be handed over to the card and +waiting to be filled. +.It used +The buffer was returned by the card and is now travelling through the system. +.El +.Pp +A pool is created with +.Fn mbp_create . +This call specifies a DMA tag +.Fa dmat +to be used to create and map the memory pages via +.Fn bus_dmamem_alloc . +The +.Fa chunk_size +includes the pool overhead. That means to get buffers for 5 ATM cells +(240 bytes) a chunk size of 256 should be specified. This results in 12 unused +bytes between the buffer and the pool overhead of four byte. The total +maximum number of buffers in a pool is +.Fa max_pages * +( +.Fa page_size / +.Fa chunk_size ). +The maximum value for +.Fa max_pages +is 2^14-1 (16383) and the maximum of +.Fa page_size / +.Fa chunk_size +is 2^9 (512). +If the call is sucessful a pointer to a newly allocated +.Vt "struct mbpool" +is set into the variable pointed to by +.Fa mpb . +.Pp +A pool is destroyed with +.Fn mbp_destroy . +This frees all pages and the pool structure itself. If compiled with +.Dv DIAGNOSTICS +the code checks that all buffers are free. If not a warning message is issued +to the console. +.Pp +A buffer is allocate with +.Fn mbp_alloc . +This returns the virtual address of the buffer and stores the physical +address into the variable pointed to by +.Fa pa . +The handle is stored into the variable pointed to by +.Fa hp . +The two most significant bits and the 7 least significant bits of the handle +are unused by the pool code and may be used by the caller. These are +automatically stripped when passing a handle to one of the other functions. +If a buffer cannot be allocated (either because the maximum number of pages +is reached, no memory is available or the memory cannot be mapped) NULL is +returned. If a buffer could be allocated it is in the on-card state. +.Pp +When the buffer is returned by the card the driver calls +.Fn mbp_get +with the handle. This function returns the virtual address of the buffer +and clears the on-card bit. The buffer is now in the used state. +The function +.Fn mbp_get_keep +differs from +.Fn mbp_get +in that it does not clear the on-card bit. This can be used for buffers +that are returned +.Sq partially +by the card. +.Pp +A buffer is freed by calling +.Fn mbp_free +with the virtual address of the buffer. This clears the used bit, and +puts the buffer on the free list of the pool. Note, that free buffers +are NOT returned to the system. +The function +.Fn mbp_ext_free can be given to +.Fn m_extadd +as the free function. The user argument must be the pointer to +the pool. +.Pp +Before useing the contents of a buffer returned by the card the driver +must call +.Fn mbp_sync +with the appropriate parameters. This results in a call to +.Fn bus_dmamap_sync +for the buffer. +.Pp +All buffers in the pool that are currently in the on-card state can be freed +with a call to +.Fn mbp_card_free . +This may be called by the driver when it stops the interface. Buffers in +the used state are not freed by this call. +.Pp +For debugging it is possible to call +.Fn mbp_count . +This returns the number of buffers in the used and on-card states and +the number of buffers on the free list. +.Sh SEE ALSO +.Xr mbuf 9 +.Sh CAVEATS +The function +.Fn mbp_sync +is currently a NOP because +.Fn bus_dmamap_sync +is missing the offset and length parameters. +.Sh AUTHOR +.An Harti Brandt Aq harti@freebsd.org . diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 857370f9fce6..9c31748c54da 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1702,6 +1702,8 @@ device hatm #Fore/Marconi HE155/622 device utopia #ATM PHY driver options NATM #native ATM +options LIBMBPOOL #needed by patm, iatm + # # Audio drivers: `pcm', `sbc', `gusc' # diff --git a/sys/conf/files b/sys/conf/files index 502fc5790c49..8a29cd685a20 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1096,6 +1096,7 @@ kern/subr_eventhandler.c standard kern/subr_hints.c standard kern/subr_kobj.c standard kern/subr_log.c standard +kern/subr_mbpool.c optional libmbpool kern/subr_mbuf.c standard kern/subr_mchain.c optional libmchain kern/subr_module.c standard diff --git a/sys/conf/options b/sys/conf/options index ba2b4102034f..484547a494c4 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -346,6 +346,7 @@ IPV6FIREWALL_DEFAULT_TO_ACCEPT opt_ip6fw.h IPSTEALTH IPX IPXIP opt_ipx.h +LIBMBPOOL LIBMCHAIN NCP NETATALK opt_atalk.h diff --git a/sys/kern/subr_mbpool.c b/sys/kern/subr_mbpool.c new file mode 100644 index 000000000000..02c25e8f6265 --- /dev/null +++ b/sys/kern/subr_mbpool.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Hartmut Brandt <harti@freebsd.org> + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/module.h> + +#include <machine/bus.h> + +#include <sys/mbpool.h> + +MODULE_VERSION(libmbpool, 1); + +/* + * Memory is allocated as DMA-able pages. Each page is divided into a number + * of equal chunks where the last 4 bytes of each chunk are occupied by + * the page number and the chunk number. The caller must take these four + * bytes into account when specifying the chunk size. Each page is mapped by + * its own DMA map using the user specified DMA tag. + * + * Each chunk has a used and a card bit in the high bits of its page number. + * 0 0 chunk is free and may be allocated + * 1 1 chunk has been given to the interface + * 0 1 chunk is traveling through the system + * 1 0 illegal + */ +struct mbtrail { + uint16_t chunk; + uint16_t page; +}; +#define MBP_CARD 0x8000 +#define MBP_USED 0x4000 +#define MBP_PMSK 0x3fff /* page number mask */ +#define MBP_CMSK 0x01ff /* chunk number mask */ + +struct mbfree { + SLIST_ENTRY(mbfree) link; /* link on free list */ +}; + +struct mbpage { + bus_dmamap_t map; /* map for this page */ + bus_addr_t phy; /* physical address */ + void *va; /* the memory */ +}; + +struct mbpool { + const char *name; /* a name for this pool */ + bus_dma_tag_t dmat; /* tag for mapping */ + u_int max_pages; /* maximum number of pages */ + size_t page_size; /* size of each allocation */ + size_t chunk_size; /* size of each external mbuf */ + + struct mtx free_lock; /* lock of free list */ + SLIST_HEAD(, mbfree) free_list; /* free list */ + u_int npages; /* current number of pages */ + u_int nchunks; /* chunks per page */ + struct mbpage pages[]; /* pages */ +}; + +static MALLOC_DEFINE(M_MBPOOL, "mbpools", "mbuf pools"); + +/* + * Make a trail pointer from a chunk pointer + */ +#define C2T(P, C) ((struct mbtrail *)((char *)(C) + (P)->chunk_size - \ + sizeof(struct mbtrail))) + +/* + * Make a free chunk pointer from a chunk number + */ +#define N2C(P, PG, C) ((struct mbfree *)((char *)(PG)->va + \ + (C) * (P)->chunk_size)) + +/* + * Make/parse handles + */ +#define HMAKE(P, C) ((((P) & MBP_PMSK) << 16) | ((C) << 7)) +#define HPAGE(H) (((H) >> 16) & MBP_PMSK) +#define HCHUNK(H) (((H) >> 7) & MBP_CMSK) + +/* + * initialize a pool + */ +int +mbp_create(struct mbpool **pp, const char *name, bus_dma_tag_t dmat, + u_int max_pages, size_t page_size, size_t chunk_size) +{ + u_int nchunks; + + if (max_pages > MBPOOL_MAX_MAXPAGES || chunk_size == 0) + return (EINVAL); + nchunks = page_size / chunk_size; + if (nchunks == 0 || nchunks > MBPOOL_MAX_CHUNKS) + return (EINVAL); + + (*pp) = malloc(sizeof(struct mbpool) + + max_pages * sizeof(struct mbpage), + M_MBPOOL, M_WAITOK | M_ZERO); + + (*pp)->name = name; + (*pp)->dmat = dmat; + (*pp)->max_pages = max_pages; + (*pp)->page_size = page_size; + (*pp)->chunk_size = chunk_size; + (*pp)->nchunks = nchunks; + + SLIST_INIT(&(*pp)->free_list); + mtx_init(&(*pp)->free_lock, name, NULL, 0); + + return (0); +} + +/* + * destroy a pool + */ +void +mbp_destroy(struct mbpool *p) +{ + u_int i; + struct mbpage *pg; +#ifdef DIAGNOSTIC + struct mbtrail *tr; + u_int b; +#endif + + for (i = 0; i < p->npages; i++) { + pg = &p->pages[i]; +#ifdef DIAGNOSTIC + for (b = 0; b < p->nchunks; b++) { + tr = C2T(p, N2C(p, pg, b)); + if (tr->page & MBP_CARD) + printf("%s: (%s) buf still on card" + " %u/%u\n", __func__, p->name, i, b); + if (tr->page & MBP_USED) + printf("%s: (%s) sbuf still in use" + " %u/%u\n", __func__, p->name, i, b); + } +#endif + bus_dmamap_unload(p->dmat, pg->map); + bus_dmamem_free(p->dmat, pg->va, pg->map); + } + mtx_destroy(&p->free_lock); + + free(p, M_MBPOOL); +} + +/* + * Helper function when loading a one segment DMA buffer. + */ +static void +mbp_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + if (error == 0) + *(bus_addr_t *)arg = segs[0].ds_addr; +} + +/* + * Allocate a new page + */ +static void +mbp_alloc_page(struct mbpool *p) +{ + int error; + struct mbpage *pg; + u_int i; + struct mbfree *f; + struct mbtrail *t; + + if (p->npages == p->max_pages) { +#ifdef DIAGNOSTIC + printf("%s: (%s) page limit reached %u\n", __func__, + p->name, p->max_pages); +#endif + return; + } + pg = &p->pages[p->npages]; + + error = bus_dmamem_alloc(p->dmat, &pg->va, BUS_DMA_NOWAIT, &pg->map); + if (error != 0) { + free(pg, M_MBPOOL); + return; + } + + error = bus_dmamap_load(p->dmat, pg->map, pg->va, p->page_size, + mbp_callback, &pg->phy, 0); + if (error != 0) { + bus_dmamem_free(p->dmat, pg->va, pg->map); + free(pg, M_MBPOOL); + return; + } + + for (i = 0; i < p->nchunks; i++) { + f = N2C(p, pg, i); + t = C2T(p, f); + t->page = p->npages; + t->chunk = i; + SLIST_INSERT_HEAD(&p->free_list, f, link); + } + + p->npages++; +} + +/* + * allocate a chunk + */ +void * +mbp_alloc(struct mbpool *p, bus_addr_t *pap, uint32_t *hp) +{ + struct mbfree *cf; + struct mbtrail *t; + + mtx_lock(&p->free_lock); + if ((cf = SLIST_FIRST(&p->free_list)) == NULL) { + mbp_alloc_page(p); + cf = SLIST_FIRST(&p->free_list); + } + if (cf == NULL) { + mtx_unlock(&p->free_lock); + return (NULL); + } + SLIST_REMOVE_HEAD(&p->free_list, link); + mtx_unlock(&p->free_lock); + + t = C2T(p, cf); + + *pap = p->pages[t->page].phy + t->chunk * p->chunk_size; + *hp = HMAKE(t->page, t->chunk); + + t->page |= MBP_CARD | MBP_USED; + + return (cf); +} + +/* + * Free a chunk + */ +void +mbp_free(struct mbpool *p, void *ptr) +{ + struct mbtrail *t; + + mtx_lock(&p->free_lock); + t = C2T(p, ptr); + t->page &= ~(MBP_USED | MBP_CARD); + SLIST_INSERT_HEAD(&p->free_list, (struct mbfree *)ptr, link); + mtx_unlock(&p->free_lock); +} + +/* + * Mbuf system external mbuf free routine + */ +void +mbp_ext_free(void *buf, void *arg) +{ + mbp_free(arg, buf); +} + +/* + * Free all buffers that are marked as beeing on the card + */ +void +mbp_card_free(struct mbpool *p) +{ + u_int i, b; + struct mbpage *pg; + struct mbtrail *tr; + struct mbfree *cf; + + mtx_lock(&p->free_lock); + for (i = 0; i < p->npages; i++) { + pg = &p->pages[i]; + for (b = 0; b < p->nchunks; b++) { + cf = N2C(p, pg, b); + tr = C2T(p, cf); + if (tr->page & MBP_CARD) { + tr->page &= MBP_PMSK; + SLIST_INSERT_HEAD(&p->free_list, cf, link); + } + } + } + mtx_unlock(&p->free_lock); +} + +/* + * Count buffers + */ +void +mbp_count(struct mbpool *p, u_int *used, u_int *card, u_int *free) +{ + u_int i, b; + struct mbpage *pg; + struct mbtrail *tr; + struct mbfree *cf; + + *used = *card = *free = 0; + for (i = 0; i < p->npages; i++) { + pg = &p->pages[i]; + for (b = 0; b < p->nchunks; b++) { + tr = C2T(p, N2C(p, pg, b)); + if (tr->page & MBP_CARD) + (*card)++; + if (tr->page & MBP_USED) + (*used)++; + } + } + mtx_lock(&p->free_lock); + SLIST_FOREACH(cf, &p->free_list, link) + *free++; + mtx_unlock(&p->free_lock); +} + +/* + * Get the buffer from a handle and clear the card flag. + */ +void * +mbp_get(struct mbpool *p, uint32_t h) +{ + struct mbfree *cf; + struct mbtrail *tr; + + cf = N2C(p, &p->pages[HPAGE(h)], HCHUNK(h)); + tr = C2T(p, cf); + +#ifdef DIAGNOSTIC + if (!(tr->page & MBP_CARD)) + printf("%s: (%s) chunk %u page %u not on card\n", __func__, + p->name, HCHUNK(h), HPAGE(h)); +#endif + + tr->page &= ~MBP_CARD; + return (cf); +} + +/* + * Get the buffer from a handle and keep the card flag. + */ +void * +mbp_get_keep(struct mbpool *p, uint32_t h) +{ + struct mbfree *cf; + struct mbtrail *tr; + + cf = N2C(p, &p->pages[HPAGE(h)], HCHUNK(h)); + tr = C2T(p, cf); + +#ifdef DIAGNOSTIC + if (!(tr->page & MBP_CARD)) + printf("%s: (%s) chunk %u page %u not on card\n", __func__, + p->name, HCHUNK(h), HPAGE(h)); +#endif + + return (cf); +} + +/* + * sync the chunk + */ +void +mbp_sync(struct mbpool *p, uint32_t h, bus_addr_t off, bus_size_t len, u_int op) +{ + +#if 0 + bus_dmamap_sync_size(p->dmat, p->pages[HPAGE(h)].map, + HCHUNK(h) * p->chunk_size + off, len, op); +#endif +} diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 778f4e1ae663..04d41df5e7ae 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -62,6 +62,7 @@ SUBDIR= accf_data \ kue \ lge \ libiconv \ + libmbpool \ libmchain \ lpt \ mac_biba \ diff --git a/sys/modules/libmbpool/Makefile b/sys/modules/libmbpool/Makefile new file mode 100644 index 000000000000..efd15ec759c7 --- /dev/null +++ b/sys/modules/libmbpool/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../kern + +KMOD= libmbpool +SRCS= subr_mbpool.c + +EXPORT_SYMS= mbp_create \ + mbp_destroy \ + mbp_alloc \ + mbp_free \ + mbp_ext_free \ + mbp_card_free \ + mbp_count \ + mbp_get \ + mbp_get_keep \ + mbp_sync + +.include <bsd.kmod.mk> diff --git a/sys/sys/mbpool.h b/sys/sys/mbpool.h new file mode 100644 index 000000000000..60ad4f8be399 --- /dev/null +++ b/sys/sys/mbpool.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Hartmut Brandt <harti@freebsd.org> + * + * This implements pools of DMA-able buffers that conserve DMA address space + * by putting several buffers into one page and that allow to map between + * 32-bit handles for the buffer and buffer addresses (to use 32-bit network + * interfaces on 64bit machines). This assists network interfaces that may need + * huge numbers of mbufs. + * + * $FreeBSD$ + */ +#ifndef _SYS_MBPOOL_H_ +#define _SYS_MBPOOL_H_ + +#ifdef _KERNEL + +#include <sys/queue.h> + +/* opaque */ +struct mbpool; + +/* size of reserved area at end of each chunk */ +#define MBPOOL_TRAILER_SIZE 4 + +/* maximum value of max_pages */ +#define MBPOOL_MAX_MAXPAGES ((1 << 14) - 1) + +/* maximum number of chunks per page */ +#define MBPOOL_MAX_CHUNKS (1 << 9) + +/* initialize a pool */ +int mbp_create(struct mbpool **, const char *, bus_dma_tag_t, u_int, + size_t, size_t); + +/* destroy a pool */ +void mbp_destroy(struct mbpool *); + +/* allocate a chunk and set used and on card */ +void *mbp_alloc(struct mbpool *, bus_addr_t *, uint32_t *); + +/* free a chunk */ +void mbp_free(struct mbpool *, void *); + +/* free a chunk that is an external mbuf */ +void mbp_ext_free(void *, void *); + +/* free all buffers that are marked to be on the card */ +void mbp_card_free(struct mbpool *); + +/* count used buffers and buffers on card */ +void mbp_count(struct mbpool *, u_int *, u_int *, u_int *); + +/* get the buffer from a handle and clear card bit */ +void *mbp_get(struct mbpool *, uint32_t); + +/* get the buffer from a handle and don't clear card bit */ +void *mbp_get_keep(struct mbpool *, uint32_t); + +/* sync the chunk */ +void mbp_sync(struct mbpool *, uint32_t, bus_addr_t, bus_size_t, u_int); + +#endif /* _KERNEL */ +#endif /* _SYS_MBPOOL_H_ */ |