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>