Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/x86/busdma_bounce.c
Show All 25 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/domainset.h> | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/interrupt.h> | #include <sys/interrupt.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/ktr.h> | #include <sys/ktr.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/memdesc.h> | #include <sys/memdesc.h> | ||||
▲ Show 20 Lines • Show All 247 Lines • ▼ Show 20 Lines | bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) | ||||
struct bounce_zone *bz; | struct bounce_zone *bz; | ||||
int error, maxpages, pages; | int error, maxpages, pages; | ||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s", __func__); | WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s", __func__); | ||||
error = 0; | error = 0; | ||||
if (dmat->segments == NULL) { | if (dmat->segments == NULL) { | ||||
dmat->segments = (bus_dma_segment_t *)malloc_domain( | dmat->segments = (bus_dma_segment_t *)malloc_domainset( | ||||
sizeof(bus_dma_segment_t) * dmat->common.nsegments, | sizeof(bus_dma_segment_t) * dmat->common.nsegments, | ||||
M_DEVBUF, dmat->common.domain, M_NOWAIT); | M_DEVBUF, DOMAINSET_PREF(dmat->common.domain), M_NOWAIT); | ||||
if (dmat->segments == NULL) { | if (dmat->segments == NULL) { | ||||
CTR3(KTR_BUSDMA, "%s: tag %p error %d", | CTR3(KTR_BUSDMA, "%s: tag %p error %d", | ||||
__func__, dmat, ENOMEM); | __func__, dmat, ENOMEM); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Bouncing might be required if the driver asks for an active | * Bouncing might be required if the driver asks for an active | ||||
* exclusion region, a data alignment that is stricter than 1, and/or | * exclusion region, a data alignment that is stricter than 1, and/or | ||||
* an active address boundary. | * an active address boundary. | ||||
*/ | */ | ||||
if (dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) { | if (dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) { | ||||
/* Must bounce */ | /* Must bounce */ | ||||
if (dmat->bounce_zone == NULL) { | if (dmat->bounce_zone == NULL) { | ||||
if ((error = alloc_bounce_zone(dmat)) != 0) | if ((error = alloc_bounce_zone(dmat)) != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
bz = dmat->bounce_zone; | bz = dmat->bounce_zone; | ||||
*mapp = (bus_dmamap_t)malloc_domain(sizeof(**mapp), M_DEVBUF, | *mapp = (bus_dmamap_t)malloc_domainset(sizeof(**mapp), M_DEVBUF, | ||||
dmat->common.domain, M_NOWAIT | M_ZERO); | DOMAINSET_PREF(dmat->common.domain), M_NOWAIT | M_ZERO); | ||||
if (*mapp == NULL) { | if (*mapp == NULL) { | ||||
CTR3(KTR_BUSDMA, "%s: tag %p error %d", | CTR3(KTR_BUSDMA, "%s: tag %p error %d", | ||||
__func__, dmat, ENOMEM); | __func__, dmat, ENOMEM); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* Initialize the new map */ | /* Initialize the new map */ | ||||
STAILQ_INIT(&((*mapp)->bpages)); | STAILQ_INIT(&((*mapp)->bpages)); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | if (flags & BUS_DMA_NOWAIT) | ||||
mflags = M_NOWAIT; | mflags = M_NOWAIT; | ||||
else | else | ||||
mflags = M_WAITOK; | mflags = M_WAITOK; | ||||
/* If we succeed, no mapping/bouncing will be required */ | /* If we succeed, no mapping/bouncing will be required */ | ||||
*mapp = NULL; | *mapp = NULL; | ||||
if (dmat->segments == NULL) { | if (dmat->segments == NULL) { | ||||
dmat->segments = (bus_dma_segment_t *)malloc_domain( | dmat->segments = (bus_dma_segment_t *)malloc_domainset( | ||||
sizeof(bus_dma_segment_t) * dmat->common.nsegments, | sizeof(bus_dma_segment_t) * dmat->common.nsegments, | ||||
M_DEVBUF, dmat->common.domain, mflags); | M_DEVBUF, DOMAINSET_PREF(dmat->common.domain), mflags); | ||||
if (dmat->segments == NULL) { | if (dmat->segments == NULL) { | ||||
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | ||||
__func__, dmat, dmat->common.flags, ENOMEM); | __func__, dmat, dmat->common.flags, ENOMEM); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
} | } | ||||
if (flags & BUS_DMA_ZERO) | if (flags & BUS_DMA_ZERO) | ||||
mflags |= M_ZERO; | mflags |= M_ZERO; | ||||
Show All 22 Lines | bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, | ||||
* should be rewritten to take that into account. | * should be rewritten to take that into account. | ||||
* | * | ||||
* In the meantime warn the user if malloc gets it wrong. | * In the meantime warn the user if malloc gets it wrong. | ||||
*/ | */ | ||||
if ((dmat->common.maxsize <= PAGE_SIZE) && | if ((dmat->common.maxsize <= PAGE_SIZE) && | ||||
(dmat->common.alignment <= dmat->common.maxsize) && | (dmat->common.alignment <= dmat->common.maxsize) && | ||||
dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) && | dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) && | ||||
attr == VM_MEMATTR_DEFAULT) { | attr == VM_MEMATTR_DEFAULT) { | ||||
*vaddr = malloc_domain(dmat->common.maxsize, M_DEVBUF, | *vaddr = malloc_domainset(dmat->common.maxsize, M_DEVBUF, | ||||
dmat->common.domain, mflags); | DOMAINSET_PREF(dmat->common.domain), mflags); | ||||
} else if (dmat->common.nsegments >= | } else if (dmat->common.nsegments >= | ||||
howmany(dmat->common.maxsize, MIN(dmat->common.maxsegsz, PAGE_SIZE)) && | howmany(dmat->common.maxsize, MIN(dmat->common.maxsegsz, PAGE_SIZE)) && | ||||
dmat->common.alignment <= PAGE_SIZE && | dmat->common.alignment <= PAGE_SIZE && | ||||
(dmat->common.boundary % PAGE_SIZE) == 0) { | (dmat->common.boundary % PAGE_SIZE) == 0) { | ||||
/* Page-based multi-segment allocations allowed */ | /* Page-based multi-segment allocations allowed */ | ||||
*vaddr = (void *)kmem_alloc_attr_domain(dmat->common.domain, | *vaddr = (void *)kmem_alloc_attr_domainset( | ||||
dmat->common.maxsize, mflags, 0ul, dmat->common.lowaddr, | DOMAINSET_PREF(dmat->common.domain), dmat->common.maxsize, | ||||
attr); | mflags, 0ul, dmat->common.lowaddr, attr); | ||||
dmat->bounce_flags |= BUS_DMA_KMEM_ALLOC; | dmat->bounce_flags |= BUS_DMA_KMEM_ALLOC; | ||||
} else { | } else { | ||||
*vaddr = (void *)kmem_alloc_contig_domain(dmat->common.domain, | *vaddr = (void *)kmem_alloc_contig_domainset( | ||||
dmat->common.maxsize, mflags, 0ul, dmat->common.lowaddr, | DOMAINSET_PREF(dmat->common.domain), dmat->common.maxsize, | ||||
mflags, 0ul, dmat->common.lowaddr, | |||||
dmat->common.alignment != 0 ? dmat->common.alignment : 1ul, | dmat->common.alignment != 0 ? dmat->common.alignment : 1ul, | ||||
dmat->common.boundary, attr); | dmat->common.boundary, attr); | ||||
dmat->bounce_flags |= BUS_DMA_KMEM_ALLOC; | dmat->bounce_flags |= BUS_DMA_KMEM_ALLOC; | ||||
} | } | ||||
if (*vaddr == NULL) { | if (*vaddr == NULL) { | ||||
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", | ||||
__func__, dmat, dmat->common.flags, ENOMEM); | __func__, dmat, dmat->common.flags, ENOMEM); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
▲ Show 20 Lines • Show All 667 Lines • ▼ Show 20 Lines | alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages) | ||||
struct bounce_zone *bz; | struct bounce_zone *bz; | ||||
int count; | int count; | ||||
bz = dmat->bounce_zone; | bz = dmat->bounce_zone; | ||||
count = 0; | count = 0; | ||||
while (numpages > 0) { | while (numpages > 0) { | ||||
struct bounce_page *bpage; | struct bounce_page *bpage; | ||||
bpage = (struct bounce_page *)malloc_domain(sizeof(*bpage), | bpage = malloc_domainset(sizeof(*bpage), M_DEVBUF, | ||||
M_DEVBUF, dmat->common.domain, M_NOWAIT | M_ZERO); | DOMAINSET_PREF(dmat->common.domain), M_NOWAIT | M_ZERO); | ||||
if (bpage == NULL) | if (bpage == NULL) | ||||
break; | break; | ||||
bpage->vaddr = (vm_offset_t)contigmalloc_domain(PAGE_SIZE, | bpage->vaddr = (vm_offset_t)contigmalloc_domainset(PAGE_SIZE, | ||||
M_DEVBUF, dmat->common.domain, M_NOWAIT, 0ul, | M_DEVBUF, DOMAINSET_PREF(dmat->common.domain), M_NOWAIT, | ||||
bz->lowaddr, PAGE_SIZE, 0); | 0ul, bz->lowaddr, PAGE_SIZE, 0); | ||||
if (bpage->vaddr == 0) { | if (bpage->vaddr == 0) { | ||||
free_domain(bpage, M_DEVBUF); | free_domain(bpage, M_DEVBUF); | ||||
break; | break; | ||||
} | } | ||||
bpage->busaddr = pmap_kextract(bpage->vaddr); | bpage->busaddr = pmap_kextract(bpage->vaddr); | ||||
mtx_lock(&bounce_lock); | mtx_lock(&bounce_lock); | ||||
STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links); | STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links); | ||||
total_bpages++; | total_bpages++; | ||||
▲ Show 20 Lines • Show All 148 Lines • Show Last 20 Lines |