summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2004-07-22 15:46:51 +0000
committerscottl <scottl@FreeBSD.org>2004-07-22 15:46:51 +0000
commit8301474d15880d948c235e7b20ea41e8fd92fcdd (patch)
tree5f002aaafdae37e43b47e2f88e96b6cbf692f4f0 /sys
parent9c40ab7a35a0df2f230c65ce9fa4e4c7c8b1a05e (diff)
downloadFreeBSD-src-8301474d15880d948c235e7b20ea41e8fd92fcdd.zip
FreeBSD-src-8301474d15880d948c235e7b20ea41e8fd92fcdd.tar.gz
Don't count needed bounce pages if loading a buffer that was created with
bus_dmamem_alloc() Submitted by: harti
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/i386/busdma_machdep.c64
1 files changed, 41 insertions, 23 deletions
diff --git a/sys/i386/i386/busdma_machdep.c b/sys/i386/i386/busdma_machdep.c
index 455f956..24d2240 100644
--- a/sys/i386/i386/busdma_machdep.c
+++ b/sys/i386/i386/busdma_machdep.c
@@ -50,6 +50,14 @@ __FBSDID("$FreeBSD$");
#define MAX_BPAGES 512
+struct bounce_page {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
+ vm_offset_t datavaddr; /* kva of client data */
+ bus_size_t datacount; /* client data count */
+ STAILQ_ENTRY(bounce_page) links;
+};
+
struct bus_dma_tag {
bus_dma_tag_t parent;
bus_size_t alignment;
@@ -67,20 +75,16 @@ struct bus_dma_tag {
bus_dma_lock_t *lockfunc;
void *lockfuncarg;
bus_dma_segment_t *segments;
-};
-
-struct bounce_page {
- vm_offset_t vaddr; /* kva of bounce buffer */
- bus_addr_t busaddr; /* Physical address */
- vm_offset_t datavaddr; /* kva of client data */
- bus_size_t datacount; /* client data count */
- STAILQ_ENTRY(bounce_page) links;
+ STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
};
int busdma_swi_pending;
+/*
+ * In order to reduce extra lock/unlock sequences in the main bounce path,
+ * this lock covers the global bounce lists and the dmat bounce lists.
+ */
static struct mtx bounce_lock;
-static STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
static int free_bpages;
static int reserved_bpages;
static int active_bpages;
@@ -127,7 +131,7 @@ static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
vm_offset_t vaddr, bus_size_t size);
static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr,
- bus_size_t len);
+ bus_size_t len, struct bus_dmamap *map);
/*
* Return true if a match is made.
@@ -138,21 +142,30 @@ static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr,
* to check for a match, if there is no filter callback then assume a match.
*/
static __inline int
-run_filter(bus_dma_tag_t dmat, bus_addr_t paddr, bus_size_t len)
+run_filter(bus_dma_tag_t dmat, bus_addr_t paddr, bus_size_t len, struct bus_dmamap *map)
{
+ bus_addr_t endaddr;
bus_size_t bndy;
int retval;
retval = 0;
bndy = dmat->boundary;
+ endaddr = paddr + len - 1;
do {
if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr)
|| ((paddr & (dmat->alignment - 1)) != 0)
- || ((paddr & bndy) != ((paddr + len) & bndy)))
+ || ((paddr & bndy) != (endaddr & bndy)))
&& (dmat->filter == NULL
- || (*dmat->filter)(dmat->filterarg, paddr) != 0))
+ || (*dmat->filter)(dmat->filterarg, paddr) != 0)) {
+ if ((paddr & (dmat->alignment - 1)) != 0)
+ printf("bouncing due alignment, paddr= 0x%lx, map= %p\n", (u_long)paddr, map);
+ if ((paddr & bndy) != (endaddr & bndy)) {
+ printf("bouncing due to boundary, paddr= 0x%lx, endaddr= 0x%lx, map= %p\n", (u_long)paddr, (u_long)endaddr, map);
+ printf("paddr & bndy = 0x%lx, paddr + len & bndy = 0x%lx\n", (u_long)(paddr & bndy), (u_long)(endaddr & bndy));
+ }
retval = 1;
+ }
dmat = dmat->parent;
} while (retval == 0 && dmat != NULL);
@@ -221,6 +234,7 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
if (newtag == NULL)
return (ENOMEM);
+ STAILQ_INIT(&newtag->bounce_page_list);
newtag->parent = parent;
newtag->alignment = alignment;
newtag->boundary = boundary;
@@ -526,7 +540,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
if ((dmat->lowaddr < ptoa((vm_paddr_t)Maxmem)
|| dmat->boundary > 0 || dmat->alignment > 1)
- && map->pagesneeded == 0) {
+ && map != &nobounce_dmamap && map->pagesneeded == 0) {
vm_offset_t vendaddr;
/*
@@ -538,7 +552,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
while (vaddr < vendaddr) {
paddr = pmap_kextract(vaddr);
- if (run_filter(dmat, paddr, 0) != 0) {
+ if (run_filter(dmat, paddr, PAGE_SIZE, map) != 0) {
needbounce = 1;
map->pagesneeded++;
}
@@ -558,7 +572,11 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
}
} else {
if (reserve_bounce_pages(dmat, map, 1) != 0) {
- /* Queue us for resources */
+ /*
+ * Queue us for resources. A future
+ * optimization might be to search other bounce
+ * lists for extra pages.
+ */
map->dmat = dmat;
map->buf = buf;
map->buflen = buflen;
@@ -599,7 +617,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
sgsize = (baddr - curaddr);
}
- if (map->pagesneeded != 0 && run_filter(dmat, curaddr, sgsize))
+ if (map->pagesneeded != 0 && run_filter(dmat, curaddr, sgsize, map))
curaddr = add_bounce_page(dmat, map, vaddr, sgsize);
/*
@@ -826,7 +844,6 @@ init_bounce_pages(void *dummy __unused)
reserved_bpages = 0;
active_bpages = 0;
total_bpages = 0;
- STAILQ_INIT(&bounce_page_list);
STAILQ_INIT(&bounce_map_waitinglist);
STAILQ_INIT(&bounce_map_callbacklist);
mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
@@ -850,7 +867,8 @@ alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
M_NOWAIT, 0ul,
dmat->lowaddr,
- PAGE_SIZE,
+ dmat->alignment?
+ dmat->alignment : 1ul,
dmat->boundary);
if (bpage->vaddr == 0) {
free(bpage, M_DEVBUF);
@@ -858,7 +876,7 @@ alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
}
bpage->busaddr = pmap_kextract(bpage->vaddr);
mtx_lock(&bounce_lock);
- STAILQ_INSERT_TAIL(&bounce_page_list, bpage, links);
+ STAILQ_INSERT_TAIL(&dmat->bounce_page_list, bpage, links);
total_bpages++;
free_bpages++;
mtx_unlock(&bounce_lock);
@@ -903,11 +921,11 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
map->pagesreserved--;
mtx_lock(&bounce_lock);
- bpage = STAILQ_FIRST(&bounce_page_list);
+ bpage = STAILQ_FIRST(&dmat->bounce_page_list);
if (bpage == NULL)
panic("add_bounce_page: free page list is empty");
- STAILQ_REMOVE_HEAD(&bounce_page_list, links);
+ STAILQ_REMOVE_HEAD(&dmat->bounce_page_list, links);
reserved_bpages--;
active_bpages++;
mtx_unlock(&bounce_lock);
@@ -927,7 +945,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
bpage->datacount = 0;
mtx_lock(&bounce_lock);
- STAILQ_INSERT_HEAD(&bounce_page_list, bpage, links);
+ STAILQ_INSERT_HEAD(&dmat->bounce_page_list, bpage, links);
free_bpages++;
active_bpages--;
if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
OpenPOWER on IntegriCloud