Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Apr 2009 05:59:28 +1000
From:      Peter Jeremy <peterjeremy@optushome.com.au>
To:        freebsd-hackers@freebsd.org
Subject:   Using bus_dma(9)
Message-ID:  <20090423195928.GB8531@server.vk2pj.dyndns.org>

next in thread | raw e-mail | index | archive | help

--R3G7APHDIzY6R/pk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

I'm currently trying to port some code that uses bus_dma(9) from
OpenBSD to FreeBSD and am having some difficulties in following the
way bus_dma is intended to be used on FreeBSD (and how it differs from
Net/OpenBSD).  Other than the man page and existing FreeBSD drivers, I
am unable to locate any information on bus_dma care and feeding.  Has
anyone written any tutorial guide to using bus_dma?

The OpenBSD man page provides pseudo-code showing the basic cycle.
Unfortunately, FreeBSD doesn't provide any similar pseudo-code and
the functionality is distributed somewhat differently amongst the
functions (and the drivers I've looked at tend to use a different
order of calls).

So far, I've hit a number of issues that I'd like some advice on:

Firstly, the OpenBSD model only provides a single DMA tag for the
device at attach() time, whereas FreeBSD provides the parent's DMA tag
at attach time and allows the driver to create multiple tags.  Rather
than just creating a single tag for a device, many drivers create a
device tag which is only used as the parent for additional tags to
handle receive, transmit etc.  Whilst the need for multiple tags is
probably a consequence of moving much of the dmamap information from
OpenBSD bus_dmamap_create() into FreeBSD bus_dma_tag_create(), the
rationale behind multiple levels of tags is unclear.  Is this solely
to provide a single point where overall device DMA characteristics &
limitations can be specified or is there another reason?

Secondly, bus_dma_tag_create() supports a BUS_DMA_ALLOCNOW flag that
"pre-allocates enough resources to handle at least one map load
operation on this tag".  However it also states "[t]his should not be
used for tags that only describe buffers that will be allocated with
bus_dmamem_alloc()" - does this mean that only one of bus_dmamap_load()
or bus_dmamap_alloc() should be used on a tag/mapping?  Or is the
sense backwards (ie "don't specify BUS_DMA_ALLOCNOW for tags that are
only used as the parent for other tags and never mapped themselves")?
Or is there some other explanation.

Thirdly, bus_dmamap_load() has a uses a callback function to return
the actual mapping details.  According to the man page, there is no
way to ensure that the callback occurs synchronously - a caller can
only request that bus_dmamap_load() fail if resources are not
immediately available.  Despite this, many drivers pass 0 for flags
(allowing an asynchronous invocation of the callback) and then fail
(and cleanup) if bus_dmamap_load() returns EINPROGRESS.  This appears
to open a race condition where the callback and cleanup could occur
simultaneously.  Mitigating the race condition seems to rely on one of
the following two behaviours:

a) The system is implicitly single-threaded when bus_dmamap_load() is
called (generally as part of the device attach() function).  Whilst
this is true at boot time, it would not be true for a dynamically
loaded module.

b) Passing BUS_DMA_ALLOCNOW to bus_dma_tag_create() guarantees that
the first bus_dmamap_load() on that tag will be synchronous.  Is this
true?  Whilst it appears to be implied, it's not explicitly stated.

Finally, what are the ordering requirements between the alloc, create,
load and sync functions?  OpenBSD implies that the normal ordering is
create, alloc, load, sync whilst several FreeBSD drivers use
tag_create, alloc, load and then create.

As a side-note, the manpage does not document the behaviour when
bus_dmamap_destroy() or bus_dma_tag_destroy() are called whilst a
bus_dmamap_load() callback is queued.  Is the callback cancelled
or do one or both destroy operations fail?

--=20
Peter Jeremy

--R3G7APHDIzY6R/pk
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.11 (FreeBSD)

iEYEARECAAYFAknwyKAACgkQ/opHv/APuIf7sACgimXrMPSYG9F/4zWS42aVU+m1
5sMAnRd27cCB2ps/84k7zQs2hD3NSavP
=kdEz
-----END PGP SIGNATURE-----

--R3G7APHDIzY6R/pk--



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