Date: Tue, 22 Mar 2016 10:45:19 -0700 From: John Baldwin <jhb@freebsd.org> To: freebsd-arch@freebsd.org Subject: Re: Wrapper API for static bus_dma allocations Message-ID: <1576055.6UjqO6PkRX@ralph.baldwin.cx> In-Reply-To: <2856669.mkVhDvxH7k@ralph.baldwin.cx> References: <2800970.jY4xzTy9Hz@ralph.baldwin.cx> <2856669.mkVhDvxH7k@ralph.baldwin.cx>
index | next in thread | previous in thread | raw e-mail
On Friday, February 26, 2016 05:10:53 PM John Baldwin wrote: > On Thursday, January 29, 2015 03:37:19 PM John Baldwin wrote: > > The bus_dma API to allocate a chunk of static DMA'able memory (e.g. for > > descriptor rings) can be a bit obtuse to use in that it require a bit of > > boilerplate to create a tag, allocate memory for the tag, then load it to get > > the bus address. Similarly, freeing it also requires several steps. In > > addition, some of the steps are a bit subtle (e.g. the need to check for an > > error in the bus_dma callback instead of from bus_dmamap_load()) and not all > > drivers get those correct. > > > > To try to make this simpler I've written a little wrapper API that tries to > > provide a single call to allocate a buffer and a single call to free a buffer. > > Each buffer is described by a structure defined by the API, and if the call to > > allocate a buffer succeeds, the structure contains both a pointer to the > > buffer in the kernel's address space as well as a bus address of the buffer. > > > > In the interests of simplicity, this API does not allow the buffer to be quite > > as fully configured as the underlying bus_dma API, instead it aims to handle > > the most common cases that are used in most drivers. As such, it assumes that > > the buffer must be one contiguous range of DMA address space, and the only > > parameters that can be specified are the parent tag, the alignment of the > > buffer, the lowaddr parameter, the size of the buffer to allocate, and the > > flags parameter that is normally passed to bus_dmamem_alloc(). I believe that > > this should be sufficient to cover the vast majority of the drivers in our > > tree. After some more thinking, I've altered this API to include an 'args' struct similar to the one Konstantin used for make_dev_s() to specify constraints. This would permit most constraints to be specified on an as-needed basis without requiring all of them each time. It does still assume 1 contiguous region, but the majority of our drivers require that anyway. I've forward ported this and converted a more typical driver (xl(4)) as a demo of the new API. You can find the full diff here: https://reviews.freebsd.org/D5704 (I've not yet written manpage updates) Here's the new code in xl(4) to allocate the TX and RX rings. I think it highlights the specific constraints (alignment, etc.) more clearly than the previous version: /* * Now allocate a chunk of DMA-able memory for the DMA * descriptor lists. All of our lists are allocated as a * contiguous block of memory. */ bus_dma_mem_args_init(&args); args.dma_alignment = 8; args.dma_lowaddr = BUS_SPACE_MAXADDR_32BIT; error = bus_dma_mem_alloc(bus_get_dma_tag(dev), XL_RX_LIST_SZ, 0, &args, &sc->xl_ldata.xl_rx_ring); if (error) { device_printf(dev, "failed to allocate rx ring\n"); goto fail; } sc->xl_ldata.xl_rx_list = sc->xl_ldata.xl_rx_ring.dma_vaddr; error = bus_dma_mem_alloc(bus_get_dma_tag(dev), XL_TX_LIST_SZ, 0, &args, &sc->xl_ldata.xl_tx_ring); if (error) { device_printf(dev, "failed to allocate tx ring\n"); goto fail; } sc->xl_ldata.xl_tx_list = sc->xl_ldata.xl_tx_ring.dma_vaddr; -- John Baldwinhome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1576055.6UjqO6PkRX>
