From owner-p4-projects@FreeBSD.ORG Sun Mar 2 23:20:29 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 4200C106567B; Sun, 2 Mar 2008 23:20:29 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DACA11065674 for ; Sun, 2 Mar 2008 23:20:28 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id B45AA8FC21 for ; Sun, 2 Mar 2008 23:20:28 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m22NKSbK046750 for ; Sun, 2 Mar 2008 23:20:28 GMT (envelope-from thompsa@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m22NKSW5046748 for perforce@freebsd.org; Sun, 2 Mar 2008 23:20:28 GMT (envelope-from thompsa@freebsd.org) Date: Sun, 2 Mar 2008 23:20:28 GMT Message-Id: <200803022320.m22NKSW5046748@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to thompsa@freebsd.org using -f From: Andrew Thompson To: Perforce Change Reviews Cc: Subject: PERFORCE change 136701 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Mar 2008 23:20:29 -0000 http://perforce.freebsd.org/chv.cgi?CH=136701 Change 136701 by thompsa@thompsa_heff on 2008/03/02 23:20:12 MF //depot/user/benjsc/wpi/sys/dev/wpi/if_wpi.c@131137 Perform memory allocation differently in contig_alloc, fix bug in config_free. Affected files ... .. //depot/projects/wifi/sys/dev/wpi/if_wpi.c#12 edit .. //depot/projects/wifi/sys/dev/wpi/if_wpivar.h#3 edit Differences ... ==== //depot/projects/wifi/sys/dev/wpi/if_wpi.c#12 (text+ko) ==== @@ -16,7 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define VERSION "20071127" +#define VERSION "20071218-p4" #include __FBSDID("$FreeBSD: src/sys/dev/wpi/if_wpi.c,v 1.8 2008/02/01 19:36:25 phk Exp $"); @@ -832,31 +832,46 @@ *(bus_addr_t *)arg = segs[0].ds_addr; } +/* + * Allocates a contiguous block of dma memory of the requested size and + * alignment. Due to limitations of the FreeBSD dma subsystem as of 20071217, + * allocations greater than 4096 may fail. Hence if the requested alignment is + * greater we allocate 'alignment' size extra memory and shift the vaddr and + * paddr after the dma load. This bypasses the problem at the cost of a little + * more memory. + */ static int wpi_dma_contig_alloc(struct wpi_softc *sc, struct wpi_dma_info *dma, void **kvap, bus_size_t size, bus_size_t alignment, int flags) { int error; - int count = 0; + bus_size_t align; + bus_size_t reqsize; DPRINTFN(WPI_DEBUG_DMA, - ("Size: %zd - alignement %zd\n", size, alignment)); + ("Size: %zd - alignment %zd\n", size, alignment)); dma->size = size; dma->tag = NULL; -again: - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment, + if (alignment > 4096) { + align = PAGE_SIZE; + reqsize = size + alignment; + } else { + align = alignment; + reqsize = size; + } + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), align, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, size, - 1, size, flags, + NULL, NULL, reqsize, + 1, reqsize, flags, NULL, NULL, &dma->tag); if (error != 0) { device_printf(sc->sc_dev, "could not create shared page DMA tag\n"); goto fail; } - error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr, + error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr_start, flags | BUS_DMA_ZERO, &dma->map); if (error != 0) { device_printf(sc->sc_dev, @@ -864,31 +879,34 @@ goto fail; } - /** - * Sadly FreeBSD can't always align on a 16k boundary, hence we give it - * 10 attempts increasing the size of the allocation by 4k each time. - * This should eventually align us on a 16k boundary at the cost - * of chewing up dma memory + error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr_start, + reqsize, wpi_dma_map_addr, &dma->paddr_start, flags); + + /* Save the original pointers so we can free all the memory */ + dma->paddr = dma->paddr_start; + dma->vaddr = dma->vaddr_start; + + /* + * Check the alignment and increment by 4096 until we get the + * requested alignment. Fail if can't obtain the alignment + * we requested. */ - if ((((uintptr_t)dma->vaddr) & (alignment-1)) && count < 10) { - DPRINTFN(WPI_DEBUG_DMA, - ("Memory Unaligned, trying again: %d\n", count++)); - wpi_dma_contig_free(dma); - size += 4096; - goto again; - } + if ((dma->paddr & (alignment -1 )) != 0) { + int i; - DPRINTFN(WPI_DEBUG_DMA,("Memory, allocated & %s Aligned!\n", - count == 10 ? "FAILED" : "")); - if (count == 10) { - device_printf(sc->sc_dev, "Unable to align memory\n"); - error = ENOMEM; - goto fail; + for (i = 0; i < alignment / 4096; i++) { + if ((dma->paddr & (alignment - 1 )) == 0) + break; + dma->paddr += 4096; + dma->vaddr += 4096; + } + if (i == alignment / 4096) { + device_printf(sc->sc_dev, + "alignment requirement was not satisfied\n"); + goto fail; + } } - error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, - size, wpi_dma_map_addr, &dma->paddr, flags); - if (error != 0) { device_printf(sc->sc_dev, "could not load shared page DMA map\n"); @@ -910,12 +928,12 @@ { if (dma->tag) { if (dma->map != NULL) { - if (dma->paddr == 0) { + if (dma->paddr_start != 0) { bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(dma->tag, dma->map); } - bus_dmamem_free(dma->tag, &dma->vaddr, dma->map); + bus_dmamem_free(dma->tag, &dma->vaddr_start, dma->map); } bus_dma_tag_destroy(dma->tag); } ==== //depot/projects/wifi/sys/dev/wpi/if_wpivar.h#3 (text+ko) ==== @@ -62,8 +62,10 @@ struct wpi_dma_info { bus_dma_tag_t tag; bus_dmamap_t map; - bus_addr_t paddr; - caddr_t vaddr; + bus_addr_t paddr; /* aligned p address */ + bus_addr_t paddr_start; /* possibly unaligned p start*/ + caddr_t vaddr; /* aligned v address */ + caddr_t vaddr_start; /* possibly unaligned v start */ bus_size_t size; };