Date: Sun, 16 Oct 2011 20:30:15 GMT From: Mark Tinguely <marktinguely@gmail.com> To: freebsd-arm@FreeBSD.org Subject: Re: arm/160431: [patch] Disable interrupts during busdma cache sync operations. Message-ID: <201110162030.p9GKUFdZ031416@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR arm/160431; it has been noted by GNATS. From: Mark Tinguely <marktinguely@gmail.com> To: bug-followup@FreeBSD.org, freebsd@damnhippie.dyndns.org Cc: Subject: Re: arm/160431: [patch] Disable interrupts during busdma cache sync operations. Date: Sun, 16 Oct 2011 14:57:50 -0500 This is a multi-part message in MIME format. --------------090706000403080305010106 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Ian and I have been sending emails this week about this problem. He and I have examples where turning off interrupts will not be enough, but I think this is a good start. If we cache align the allocation sizes that are less than a PAGE_SIZE in bus_dmamem_alloc(), then it may help avoid this routine. Attached is a crude alignment concept code. --Mark. --------------090706000403080305010106 Content-Type: text/plain; name="arm_busdma_machdep_c.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="arm_busdma_machdep_c.diff" --- sys/arm/arm/busdma_machdep.c.orig 2011-10-16 13:09:49.000000000 -0500 +++ sys/arm/arm/busdma_machdep.c 2011-10-16 14:20:27.000000000 -0500 @@ -579,6 +579,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi { bus_dmamap_t newmap = NULL; + bus_size_t len; int mflags; if (flags & BUS_DMA_NOWAIT) @@ -598,17 +599,23 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi *mapp = newmap; newmap->dmat = dmat; - if (dmat->maxsize <= PAGE_SIZE && - (dmat->alignment < dmat->maxsize) && + if (dmat->maxsize < PAGE_SIZE) + /* round up to nearest cache line size */ + len = (dmat->maxsize + arm_dcache_align_mask) & + ~arm_dcache_align_mask; + else + len = dmat->maxsize; + if (len <= PAGE_SIZE && + (dmat->alignment < len) && !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) { - *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); + *vaddr = malloc(len, M_DEVBUF, mflags); } else { /* * XXX Use Contigmalloc until it is merged into this facility * and handles multi-seg allocations. Nobody is doing * multi-seg allocations yet though. */ - *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, + *vaddr = contigmalloc(len, M_DEVBUF, mflags, 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, dmat->boundary); } @@ -623,7 +630,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi if (flags & BUS_DMA_COHERENT) { void *tmpaddr = arm_remap_nocache( (void *)((vm_offset_t)*vaddr &~ PAGE_MASK), - dmat->maxsize + ((vm_offset_t)*vaddr & PAGE_MASK)); + len + ((vm_offset_t)*vaddr & PAGE_MASK)); if (tmpaddr) { tmpaddr = (void *)((vm_offset_t)(tmpaddr) + @@ -645,19 +652,28 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) { + bus_size_t len; + + if (dmat->maxsize < PAGE_SIZE) + /* round up to nearest cache line size */ + len = (dmat->maxsize + arm_dcache_align_mask) & + ~arm_dcache_align_mask; + else + len = dmat->maxsize; + if (map->allocbuffer) { KASSERT(map->allocbuffer == vaddr, ("Trying to freeing the wrong DMA buffer")); vaddr = map->origbuffer; arm_unmap_nocache(map->allocbuffer, - dmat->maxsize + ((vm_offset_t)vaddr & PAGE_MASK)); + len + ((vm_offset_t)vaddr & PAGE_MASK)); } - if (dmat->maxsize <= PAGE_SIZE && - dmat->alignment < dmat->maxsize && + if (len <= PAGE_SIZE && + dmat->alignment < len && !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) free(vaddr, M_DEVBUF); else { - contigfree(vaddr, dmat->maxsize, M_DEVBUF); + contigfree(vaddr, len, M_DEVBUF); } dmat->map_count--; _busdma_free_dmamap(map); --------------090706000403080305010106--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110162030.p9GKUFdZ031416>