Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Aug 2001 00:23:39 -0600
From:      "Justin T. Gibbs" <gibbs@scsiguy.com>
To:        wpaul@FreeBSD.ORG (Bill Paul)
Cc:        mjacob@feral.com, hackers@FreeBSD.ORG, current@FreeBSD.ORG
Subject:   Re: Where to put new bus_dmamap_load_mbuf() code 
Message-ID:  <200108210623.f7L6NdY90348@aslan.scsiguy.com>
In-Reply-To: Your message of "Mon, 20 Aug 2001 17:06:30 PDT." <20010821000630.92CF937B406@hub.freebsd.org> 

next in thread | previous in thread | raw e-mail | index | archive | help
>Every hear the phrase "you get what you pay for?" The API isn't all that
>clear, and we don't have a man page or document that describes in detail
>how to use it properly. Rather than whining about that, I decided to
>tinker with it and Use The Source, Luke (tm). This is the result.

Fair enough.

>My understanding is that you need a dmamap for every buffer that you want
>to map into bus space.

You need one dmamap for each independantly manageable mapping.  A
single mapping may result in a long list of segments, regardless
of whether you have a single KVA buffer or multiple KVA buffers
that might contribute to the mapping.

>Each mbuf has a single data buffer associated with
>it (either the data area in the mbuf itself, or external storage). We're
>not allowed to make assumptions about where these buffers are. Also, a
>single ethernet frame can be fragmented across multiple mbufs in a list.
>
>So unless I'm mistaken, for each mbuf in an mbuf list, what we
>have to do is this:
>
>- create a bus_dmamap_t for the data area in the mbuf using
>  bus_dmamap_create()

Creating a dmamap, depending on the architecture, could be expensive.
You really want to create them in advance (or pool them), with at most
one dmamap per concurrent transaction you support in your driver.

>- do the physical to bus mapping with bus_dmamap_load()

bus_dmamap_load() only understands how to map a single buffer.
You will have to pull pieces of bus_dmamap_load into a new
function (or create inlines for common bits) to do this
correctly.  The algorithm goes something like this:

	foreach mbuf in the mbuf chain to load
		/*
		 * Parse this contiguous piece of KVA into
		 * its bus space regions.
		 */
		foreach "bus space" discontiguous region
			if (too_many_segs)
				return (error);
			Add new S/G element

With the added complications of deferring the mapping if we're
out of space, issuing the callback, etc.

>- call bus_dmamap_sync() as needed (might handle copying if bounce
>  buffers are required)
>- <insert mysterious DMA operation here>
>- do post-DMA sync as needed (again, might require bounce copying)
>- call bus_dmamap_unload() to un-do the bus mapping (which might free
>  bounce buffers if some were allocated by bus_dmamap_load())
>- destroy the bus_dmamap_t

Chances are you are going to use the map again soon, so destroying
it on every transaction is a waste.

--
Justin

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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