Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 01 Feb 2015 10:29:31 -0700
From:      Ian Lepore <ian@freebsd.org>
To:        John Baldwin <jhb@freebsd.org>
Cc:        'freebsd-arch' <freebsd-arch@freebsd.org>
Subject:   Re: Wrapper API for static bus_dma allocations
Message-ID:  <1422811771.15718.269.camel@freebsd.org>
In-Reply-To: <2800970.jY4xzTy9Hz@ralph.baldwin.cx>
References:  <2800970.jY4xzTy9Hz@ralph.baldwin.cx>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 2015-01-29 at 15:37 -0500, John Baldwin wrote:
[...]
> +int
> +bus_dma_mem_create(struct bus_dmamem *mem, bus_dma_tag_t parent,
> +    bus_size_t alignment, bus_addr_t lowaddr, bus_size_t len, int flags)
> +{
> +	struct bus_dma_mem_cb_data d;
> +	int error;
> +
> +	bzero(mem, sizeof(*mem));
> +	error = bus_dma_tag_create(parent, alignment, 0, lowaddr,
> +	    BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, 0, NULL, NULL,
> +	    &mem->dma_tag);
> +	if (error) {
> +		bus_dma_mem_free(mem);
> +		return (error);
> +	}
> +	error = bus_dmamem_alloc(mem->dma_tag, &mem->dma_vaddr, flags,
> +	    &mem->dma_map);
> +	if (error) {
> +		bus_dma_mem_free(mem);
> +		return (error);
> +	}
> +	d.mem = mem;
> +	error = bus_dmamap_load(mem->dma_tag, mem->dma_map, mem->dma_vaddr, len,
> +	    bus_dma_mem_cb, &d, BUS_DMA_NOWAIT);
> +	if (error == 0)
> +		error = d.error;
> +	if (error) {
> +		bus_dma_mem_free(mem);
> +		return (error);
> +	}
> +	return (0);
> +}
> +[...]

A couple more thoughts on this...

It would be good to pass the flags to both bus_dma_tag_create() and
bus_dmamem_alloc().  While the manpage seems to indicate that certain
flags are specific to tag-create or mem-alloc, there is actually no
overlap in values, so passing flags to tag-create that a given arch only
uses in mem-alloc should be harmless.  Implementations may be able
optimize things if they can see flags at tag-create time that normally
apply to allocation.

Hmmm, it just popped into my head that a new flag that means "this is
going to be a combined tag+map+buffer allocation" might allow for even
more optimizations.  For example you can avoid allocating any resources
related to bouncing if you know that the only mapping that will ever be
created with that tag+map is one belonging to a buffer that the
implementation can carefully allocate in a way that avoids bouncing.

Another way to achieve that would be to allow the whole implementation
of bus_dma_mem_create() to be supplied by the arch, rather than having
it be generic in kern.  The more I think about it, the more I like this.

Could we eliminate the alignment arg and instead document that the
alignment of the allocated buffer will be at least the same as the size
argument up to PAGE_SIZE, and will be PAGE_SIZE for anything 1 page or
larger?   There is a standard uma-based allocator available in
kern/subr_busdma_buffalloc.c that implements this behavior.  It's
currently used only by arm, but should be trivial to use more widely.
When I investigated alignment usage a couple years ago, I found nearly
all existing uses of alignment specify a value <= the size in the tag.

-- Ian





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1422811771.15718.269.camel>