public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] Avoiding memcpy in ethernet drivers
@ 2009-02-27 20:43 Edgar Grimberg
  2009-03-02 17:09 ` [ECOS] " Tarmo Kuuse
  2009-03-04  8:39 ` [ECOS] " Bart Veer
  0 siblings, 2 replies; 6+ messages in thread
From: Edgar Grimberg @ 2009-02-27 20:43 UTC (permalink / raw)
  To: ecos-discuss

Hi,
Having to write a driver for an ethernet device, I noticed that there
are 2 memcpy()s in most of the drivers, one when sending and one when
receiving. This usually happens from and to the sg_list passed from
the hardware independent ethernet driver. Now, is this really
necessary?
For my case, I have one ring of buffers for each send and receive. I
would like to craft the driver as such to point the buffers to the
buffer in sg_list, but I can set up the rings only when the device is
stopped. This excludes ad-hoc setting when receiving/sending.
My idea was to create the sg_list-s (one for send and one for receive)
so they can be available to the init function from the NETDEVTAB_ENTRY
macro. In this way, a driver will need to take care of the pointers
to/from the sg_list-s.
Any comments/advices on this ?

Best regards,
Edgar

PS: reference files:
/ecos/packages/devs/eth/powerpc/fec/current/src/if_fec.c (specific
ethernet implementation, has 2 memcpy in fec_eth_send and
fec_eth_recv)
/ecos/packages/io/eth/current/src/net/eth_drv.c (hw independent
ethernet driver, sg_list appears on eth_drv_send and eth_drv_recv)

--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ECOS]  Re: Avoiding memcpy in ethernet drivers
  2009-02-27 20:43 [ECOS] Avoiding memcpy in ethernet drivers Edgar Grimberg
@ 2009-03-02 17:09 ` Tarmo Kuuse
  2009-03-03 18:23   ` Edgar Grimberg
  2009-03-04  8:39 ` [ECOS] " Bart Veer
  1 sibling, 1 reply; 6+ messages in thread
From: Tarmo Kuuse @ 2009-03-02 17:09 UTC (permalink / raw)
  To: ecos-discuss

Edgar Grimberg wrote:
> Having to write a driver for an ethernet device, I noticed that there
> are 2 memcpy()s in most of the drivers, one when sending and one when
> receiving. This usually happens from and to the sg_list passed from
> the hardware independent ethernet driver. Now, is this really
> necessary?
> For my case, I have one ring of buffers for each send and receive. I
> would like to craft the driver as such to point the buffers to the
> buffer in sg_list, but I can set up the rings only when the device is
> stopped. This excludes ad-hoc setting when receiving/sending.
> My idea was to create the sg_list-s (one for send and one for receive)
> so they can be available to the init function from the NETDEVTAB_ENTRY
> macro. In this way, a driver will need to take care of the pointers
> to/from the sg_list-s.
> Any comments/advices on this ?

Just pointing out that some ethernet HW requires aligned buffers. E.g. 
FEC in newer ColdFire devices needs data to be aligned to 4 bytes.

--
Kind regards,
Tarmo Kuuse


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [ECOS]  Re: Avoiding memcpy in ethernet drivers
  2009-03-02 17:09 ` [ECOS] " Tarmo Kuuse
@ 2009-03-03 18:23   ` Edgar Grimberg
  0 siblings, 0 replies; 6+ messages in thread
From: Edgar Grimberg @ 2009-03-03 18:23 UTC (permalink / raw)
  To: Tarmo Kuuse; +Cc: ecos-discuss

Tarmo Kuuse wrote:
> Edgar Grimberg wrote:
>> Having to write a driver for an ethernet device, I noticed that there
>> are 2 memcpy()s in most of the drivers, one when sending and one when
>> receiving. This usually happens from and to the sg_list passed from
>> the hardware independent ethernet driver. Now, is this really
>> necessary?
>> For my case, I have one ring of buffers for each send and receive. I
>> would like to craft the driver as such to point the buffers to the
>> buffer in sg_list, but I can set up the rings only when the device is
>> stopped. This excludes ad-hoc setting when receiving/sending.
>> My idea was to create the sg_list-s (one for send and one for receive)
>> so they can be available to the init function from the NETDEVTAB_ENTRY
>> macro. In this way, a driver will need to take care of the pointers
>> to/from the sg_list-s.
>> Any comments/advices on this ?
>
> Just pointing out that some ethernet HW requires aligned buffers. E.g. 
> FEC in newer ColdFire devices needs data to be aligned to 4 bytes.
>
Thanks for pointing that out. I'd say to align them at cache line, this 
will make it easier to debug in case there are some problems with caches 
and manual flushing and invalidation is needed. For my driver (eTSEC), 
the requirements are a bit unbalanced:
"Receive buffer pointer, written by the user. The receive buffer 
pointer, which always points to the first location of the associated 
data buffer, must be 8-byte aligned. The buffer must reside in memory 
external to the eTSEC."
and
"The transmit buffer pointer contains the address of the associated data 
buffer. There are no alignment requirements for this address."

On the subject, I've read the hardware independent ethernet code, and 
there is just pointer manipulation happening for sg lists. I guess the 
matching must be between the a higher level buffer (in the tcp/ip stack, 
I think) and the hardware dependent ethernet driver. This will break the 
independence of the low level driver from the stack implementation, I'm 
afraid. Any other ideas to get rid of the memcpy ?

Regards,
Edgar


> -- 
> Kind regards,
> Tarmo Kuuse
>
>


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [ECOS] Avoiding memcpy in ethernet drivers
  2009-02-27 20:43 [ECOS] Avoiding memcpy in ethernet drivers Edgar Grimberg
  2009-03-02 17:09 ` [ECOS] " Tarmo Kuuse
@ 2009-03-04  8:39 ` Bart Veer
  2009-03-04 11:34   ` [ECOS] " Grant Edwards
  2009-03-04 12:14   ` [ECOS] " Edgar Grimberg
  1 sibling, 2 replies; 6+ messages in thread
From: Bart Veer @ 2009-03-04  8:39 UTC (permalink / raw)
  To: Edgar Grimberg; +Cc: ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3880 bytes --]

>>>>> "Edgar" == Edgar Grimberg <edgar.grimberg@gmail.com> writes:

    Edgar> Having to write a driver for an ethernet device, I noticed
    Edgar> that there are 2 memcpy()s in most of the drivers, one when
    Edgar> sending and one when receiving. This usually happens from
    Edgar> and to the sg_list passed from the hardware independent
    Edgar> ethernet driver. Now, is this really necessary?

Ethernet hardware varies widely, but there are two main categories:
fifo vs. DMA.

With a fifo-based device the driver just puts an outgoing packet into
a transmit fifo, possibly an int at a time, possibly a byte at a time.
Similarly incoming packets are read out of a receive fifo. So there
has to be a copy operation between the sg_list and the fifo.

With DMA, ideally there would be no need for a copy operation - if the
hardware was designed just right, and if higher-level code like the
BSD, RedBoot or LWIP TCP/IP stacks did the right thing. Unfortunately
neither assumption is safe.

For outgoing packets the DMA engine typically imposes some
limitations. For example the start of a DMA buffer may have to be
aligned to an integer boundary, or to a cacheline boundary (typically
but not always 16-bytes). If an outgoing packet is split over multiple
buffers then the DMA engine may require that every buffer except the
last one is a multiple of the cacheline size. Currently there is no
mechanism for ethernet drivers to indicate such restrictions to
higher-level code, and the sg_list's provided by higher-level code may
provide buffers with arbitrary alignments and lengths.

So, typically ethernet drivers will copy the sg_list into a single
contiguous buffer aligned to a suitable boundary. Sometimes that copy
won't be necessary, but if you are not careful then you'll spend more
time figuring out which bits need copying and which don't than it
would take to just do the copy anyway. If you want to eliminate the
copy at the device driver level then you need to provide a way for
device drivers to indicate the h/w constraints to higher-level code,
and you need to update the higher-level code so that it will guarantee
that the constraints are always satisfied.

For incoming packets, the current API between device drivers and
higher-level code assumes that the driver knows the size of the
packet. With DMA engines that info is not available in time. Instead
typically the driver has a static full-sized receive buffer, and once
a full packet has been received it will allocate an sg_list and copy
from the static buffer. Using a static buffer also avoids problems
with DMA engine restrictions, e.g. it is possible to statically
allocate a buffer that is cacheline-aligned and a multiple of the
cacheline size.

Changing the current API between drivers and higher-level code would
impact existing drivers. There are a number of different ways of
tackling that problem, but nothing simple.


The current code works well enough for most people. Realistically, it
is unlikely that anything would happen in this area except possibly as
part of a re-import of the BSD stack. Just the re-import would be a
big job, never mind changing the device driver interface. It may
happen some day, most likely if/when somebody really needs maximum
performance and is willing to pay for the work.

Bart

-- 
Bart Veer                                   eCos Configuration Architect
eCosCentric Limited    The eCos experts      http://www.ecoscentric.com/
Barnwell House, Barnwell Drive, Cambridge, UK.      Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
Besuchen Sie uns vom 3.-5.03.09 auf der Embedded World 2009, Stand 11-300
Visit us at Embedded World 2009, Nürnberg, Germany, 3-5 Mar, Stand 11-300

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ECOS]  Re: Avoiding memcpy in ethernet drivers
  2009-03-04  8:39 ` [ECOS] " Bart Veer
@ 2009-03-04 11:34   ` Grant Edwards
  2009-03-04 12:14   ` [ECOS] " Edgar Grimberg
  1 sibling, 0 replies; 6+ messages in thread
From: Grant Edwards @ 2009-03-04 11:34 UTC (permalink / raw)
  To: ecos-discuss

On 2009-03-03, Bart Veer <bartv@ecoscentric.com> wrote:
>>>>>> "Edgar" == Edgar Grimberg <edgar.grimberg@gmail.com> writes:
>
>> Having to write a driver for an ethernet device, I noticed
>> that there are 2 memcpy()s in most of the drivers, one when
>> sending and one when receiving. This usually happens from and
>> to the sg_list passed from the hardware independent ethernet
>> driver. Now, is this really necessary?
>
> Ethernet hardware varies widely, but there are two main
> categories: fifo vs. DMA.
[...]
> With DMA, ideally there would be no need for a copy operation
> - if the hardware was designed just right, and if higher-level
> code like the BSD, RedBoot or LWIP TCP/IP stacks did the right
> thing. Unfortunately neither assumption is safe.
>
> For outgoing packets the DMA engine typically imposes some
> limitations. For example the start of a DMA buffer may have to
> be aligned to an integer boundary, or to a cacheline boundary
> (typically but not always 16-bytes). If an outgoing packet is
> split over multiple buffers then the DMA engine may require
> that every buffer except the last one is a multiple of the
> cacheline size.

My experience is somewhat limited, but I've yet to see a uC
Ethernet controller with a DMA engine that supported splitting
frames in any manner at all (inbound or outbound).  If the
network stack requires that packets be split into various
chunks, then there's simply no avoiding the copy operation.

I think some high-end PCI Ethernet controllers aimed at the
"server" market do have support for scatter/gather DMA, but
that's not really the market for which eCos is intended.

-- 
Grant Edwards                   grante             Yow! HELLO KITTY gang
                                  at               terrorizes town, family
                               visi.com            STICKERED to death!


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [ECOS] Avoiding memcpy in ethernet drivers
  2009-03-04  8:39 ` [ECOS] " Bart Veer
  2009-03-04 11:34   ` [ECOS] " Grant Edwards
@ 2009-03-04 12:14   ` Edgar Grimberg
  1 sibling, 0 replies; 6+ messages in thread
From: Edgar Grimberg @ 2009-03-04 12:14 UTC (permalink / raw)
  To: Bart Veer; +Cc: Edgar Grimberg, ecos-discuss

Hi Bart,

Thanks for the response. The reason why I started the conversation is 
that I did a bit of profiling on the working system and memcpy is on the 
top of the list. I was expecting this and, in order to optimize, I 
wanted to do something about the biggest CPU consumer. In other systems 
I would have been linking the code into a faster RAM area, but in this 
case I have none available. So my next idea was to minimize the usage of 
memcpy.
Some comments inlined:

>     Edgar> Having to write a driver for an ethernet device, I noticed
>     Edgar> that there are 2 memcpy()s in most of the drivers, one when
>     Edgar> sending and one when receiving. This usually happens from
>     Edgar> and to the sg_list passed from the hardware independent
>     Edgar> ethernet driver. Now, is this really necessary?
>
> Ethernet hardware varies widely, but there are two main categories:
> fifo vs. DMA.
>   
My case is, of course, DMA based ethernet.
> Changing the current API between drivers and higher-level code would
> impact existing drivers. There are a number of different ways of
> tackling that problem, but nothing simple.
>   
This is what I'm afraid of. I tried to hack my way around it for a short 
while, but I don't see an easy way to do it without breaking the 
existing code and to keep the drivers independent from the stack 
implementation.
> The current code works well enough for most people. Realistically, it
> is unlikely that anything would happen in this area except possibly as
> part of a re-import of the BSD stack. Just the re-import would be a
> big job, never mind changing the device driver interface. It may
> happen some day, most likely if/when somebody really needs maximum
> performance and is willing to pay for the work.
>   
In my case, the clients are spinning their own tcp/ip stack with zero 
memcpy and some FPGA help. I just wanted to provide a "reference" system 
for measurements, the fastest one I can get with minimal modifications.

Regards,
Edgar

-- 
Edgar Grimberg
System Developer
Zylin AS
Phone: (+47) 51 63 25 00


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-03-04  8:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-27 20:43 [ECOS] Avoiding memcpy in ethernet drivers Edgar Grimberg
2009-03-02 17:09 ` [ECOS] " Tarmo Kuuse
2009-03-03 18:23   ` Edgar Grimberg
2009-03-04  8:39 ` [ECOS] " Bart Veer
2009-03-04 11:34   ` [ECOS] " Grant Edwards
2009-03-04 12:14   ` [ECOS] " Edgar Grimberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).