This is the mail archive of the
ecos-devel@sourceware.org
mailing list for the eCos project.
Re: DMA capable Ethernet driver... (zero-copy)?
Nick Garnett wrote:
"Lars Povlsen" <lpovlsen@vitesse.com> writes:
> Hello!
>
> On working on a.k.a. Ethernet for eCos I was initially triggered by
> seeing a stack-allocated Ethernet header (redboot/stand-alone) to
> investigate other Ethernet drivers... I was sad to see only copying
> send() implementations until I saw the following comment in the eCos
> docs:
>
> "Note: In future, this function may be extended so that the data need
> not be copied by having the function return a "disposition" code (done,
> send pending, etc). At this point, you should move the data to some
> "safe" location before returning."
>
> Is this really the state of affairs? Copy no matter that the hardware
> may have all kinds of fancy scatter/gather frame DMA?
Direct DMA from the buffers should work since they should not be
released until the driver calls the tx_done() function. A key is
passed back and forth so that the calls can be properly matched. As an
example the Intel 82544 driver does direct DMA transmission.
Thanks for the pointers - I'll have a look.
I have to admit that I'm not entirely sure what that note means, since
the functionality it describes is already mostly present in the
send()/tx_done() interface. Perhaps Gary, who probably wrote it
several years ago, could explain what he meant.
>
> I guess I may DMA the frame directly out - spinning on completion. Ouch!
No need to spin or even wait in the send() function. You just return
once the transmission has been started. Eventually an interrupt will
indicate completion, and cause the deliver function to be called, in
which you call tx_done().
See redboot/current/src/net/enet.c:
void
__enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type)
{
=> eth_header_t eth_hdr;
// Set up ethernet header
memcpy(ð_hdr.destination, dest, sizeof(enet_addr_t));
memcpy(ð_hdr.source, __local_enet_addr, sizeof(enet_addr_t));
eth_hdr.type = htons(eth_type);
eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes);
#ifdef ENET_STATS
++num_transmitted;
#endif
}
Unless the fragments (notably the first - the ethernet header) are
squirelled away, it will be thrashed randomly by subsequent stack use.
So is this a bug?
Off course, other network stacks may have better characteristics, but at
least redboot will exhibit random data thrashing if I use straight DMA.
The occurrence will be dependent on how fast the DMA is started (other
system/network) activity - which may be non-existing in the redboot -
which could explain why this apparently is not a problem...?
---Lars
--
Nick Garnett eCos Kernel Architect
http://www.ecoscentric.com The eCos and RedBoot experts