From owner-freebsd-arm@FreeBSD.ORG Sun Oct 16 20:30:16 2011 Return-Path: Delivered-To: freebsd-arm@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EB2CA1065673 for ; Sun, 16 Oct 2011 20:30:15 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id DA3788FC14 for ; Sun, 16 Oct 2011 20:30:15 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p9GKUFIX031419 for ; Sun, 16 Oct 2011 20:30:15 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p9GKUFdZ031416; Sun, 16 Oct 2011 20:30:15 GMT (envelope-from gnats) Date: Sun, 16 Oct 2011 20:30:15 GMT Message-Id: <201110162030.p9GKUFdZ031416@freefall.freebsd.org> To: freebsd-arm@FreeBSD.org From: Mark Tinguely Cc: Subject: Re: arm/160431: [patch] Disable interrupts during busdma cache sync operations. X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Mark Tinguely List-Id: Porting FreeBSD to the StrongARM Processor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 16 Oct 2011 20:30:16 -0000 The following reply was made to PR arm/160431; it has been noted by GNATS. From: Mark Tinguely 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--