Context:
Network drivers have a limited number of tx descriptors to program
with DMA addresses when transmitting a packet. When we have an mbuf
ready to transmit, we prepare the IOMMU or whatever and get DMA
addresses to point the tx descriptors at with bus_dmamap_load_mbuf,
which fails if the mbuf has more noncontiguous segments than there are
DMA segments available in the DMA map.
Most drivers have more than one tx descriptor, so most of the time,
even if an mbuf is split into multiple segments, bus_dmamap_load_mbuf
will succeed.
For those cases when there are too many mbuf segments, most of our
drivers have copypasta that will allocate a new single-segment mbuf,
and copy the data into it to transmit.
Some drivers use m_defrag, which does this for _everything after the
first segment_ of the mbuf but leaves the identity of the mbuf intact,
in case there are pointers to it elsewhere.
The trouble with bwfm is that there is only one tx descriptor, so
m_defrag always fails to do what it needs. OpenBSD does some grody
hacks to compress it into a single mbuf without changing the identity
of the mbuf but apparently we can't do that.
Conceivably, there might be drivers with jumbo frames that can't
service either because two segments is not _enough_ segments. FreeBSD
also has a function m_collapse that takes the maximum number of
fragments (but does not preserve the identity of the mbuf).
What should we do? m_collapse seems like a good idea to me, provided
we take care when adapting drivers to use it that it is OK to change
the identity of the mbuf -- which most of the copypasta does anyway.
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de