All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Simek <michal.simek@xilinx.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 10/12] net: emaclite: Use indirect access in emaclite_recv
Date: Thu, 17 Dec 2015 12:24:32 +0100	[thread overview]
Message-ID: <56729B70.3090603@xilinx.com> (raw)
In-Reply-To: <CANr=Z=aB5-Q0-qufu-LUA4L+dbO_K2rNpBy00O5qV11g3U9J5g@mail.gmail.com>

On 15.12.2015 23:20, Joe Hershberger wrote:
> On Fri, Dec 11, 2015 at 6:03 AM, Michal Simek <michal.simek@xilinx.com> wrote:
>> When IP is configured with pong buffers, IP is receiving packets to ping
>> and then to pong buffer and than ping again.
>> Origin logic in the driver remains there that when ping buffer is
> 
> Origin -> Original

fixed

> 
>> free, pong buffer is checked too and return if both are free.
>>
>> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
>> ---
>>
>> Do you know macros which I could use for addressing certain fields in
>> ethernet and IP packet? The code is there because copying huge amount of
>> data is causing performance penalty.
> 
> So you're saying the IP will not tell you the length of the frame
> received? You have to pull it out of the packet data?

Unfortunately yes. Linux driver uses the same logic.
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/xilinx/xilinx_emaclite.c#n414

> 
>> ---
>>  drivers/net/xilinx_emaclite.c | 90 ++++++++++++++++++++++++-------------------
>>  1 file changed, 51 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
>> index e97ce2ce31f3..b5ff4f099251 100644
>> --- a/drivers/net/xilinx_emaclite.c
>> +++ b/drivers/net/xilinx_emaclite.c
>> @@ -22,11 +22,6 @@
>>
>>  #define ENET_ADDR_LENGTH       6
> 
> Use ARP_HLEN from include/net.h
> 
>>
>> -/* EmacLite constants */
>> -#define XEL_BUFFER_OFFSET      0x0800  /* Next buffer's offset */
>> -#define XEL_RSR_OFFSET         0x17FC  /* Rx status */
>> -#define XEL_RXBUFF_OFFSET      0x1000  /* Receive Buffer */
>> -
>>  /* Xmit complete */
>>  #define XEL_TSR_XMIT_BUSY_MASK         0x00000001UL
>>  /* Xmit interrupt enable bit */
>> @@ -86,7 +81,7 @@ struct emaclite_regs {
>>  };
>>
>>  struct xemaclite {
>> -       u32 nextrxbuffertouse;  /* Next RX buffer to read from */
>> +       bool nextrxbuffertouse; /* Next RX buffer to read from */
> 
> When using a boolean for this sort of thing it is good to give it a
> more clear name, such as "use_rx_pong_buffer_next".

done.

> 
>>         u32 txpp;               /* TX ping pong buffer */
>>         u32 rxpp;               /* RX ping pong buffer */
>>         int phyaddr;
>> @@ -455,45 +450,63 @@ static int emaclite_recv(struct eth_device *dev)
>>  {
>>         u32 length;
>>         u32 reg;
>> -       u32 baseaddress;
>> +       u32 *addr, *ack;
>>         struct xemaclite *emaclite = dev->priv;
>> -
>> -       baseaddress = dev->iobase + emaclite->nextrxbuffertouse;
>> -       reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
>> -       debug("Testing data at address 0x%x\n", baseaddress);
>> -       if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
>> -               if (emaclite->rxpp)
>> -                       emaclite->nextrxbuffertouse ^= XEL_BUFFER_OFFSET;
>> +       struct emaclite_regs *regs = emaclite->regs;
>> +       u32 attempt = 0;
>> +
>> +try_again:
>> +       if (!emaclite->nextrxbuffertouse) {
>> +               reg = in_be32(&regs->rx_ping_rsr);
>> +               debug("Testing data at rx_ping\n");
>> +               if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
>> +                       debug("Data found in rx_ping buffer\n");
>> +                       addr = &regs->rx_ping;
>> +                       ack = &regs->rx_ping_rsr;
>> +               } else {
>> +                       debug("Data not found in rx_ping buffer\n");
>> +                       /* Pong buffer is not available - return immediatelly */
> 
> immediatelly -> immediately

fixed.

> 
>> +                       if (!emaclite->rxpp)
>> +                               return -1;
>> +
>> +                       /* Try pong buffer if this is first attempt */
>> +                       if (attempt++)
>> +                               return -1;
>> +                       emaclite->nextrxbuffertouse =
>> +                                                 !emaclite->nextrxbuffertouse;
>> +                       goto try_again;
>> +               }
>>         } else {
>> -
>> -               if (!emaclite->rxpp) {
>> -                       debug("No data was available - address 0x%x\n",
>> -                                                               baseaddress);
>> -                       return 0;
>> +               reg = in_be32(&regs->rx_pong_rsr);
>> +               debug("Testing data at rx_pong\n");
>> +               if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
>> +                       debug("Data found in rx_pong buffer\n");
>> +                       addr = &regs->rx_pong;
>> +                       ack = &regs->rx_pong_rsr;
>>                 } else {
>> -                       baseaddress ^= XEL_BUFFER_OFFSET;
>> -                       reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
>> -                       if ((reg & XEL_RSR_RECV_DONE_MASK) !=
>> -                                               XEL_RSR_RECV_DONE_MASK) {
>> -                               debug("No data was available - address 0x%x\n",
>> -                                               baseaddress);
>> -                               return 0;
>> -                       }
>> +                       debug("Data not found in rx_pong buffer\n");
>> +                       /* Try ping buffer if this is first attempt */
>> +                       if (attempt++)
>> +                               return -1;
>> +                       emaclite->nextrxbuffertouse =
>> +                                                 !emaclite->nextrxbuffertouse;
>> +                       goto try_again;
>>                 }
>>         }
>> +
>> +#define        ETH_TYPE_OFFSET         3
> 
> This is offset in count of 32-bit words.

yep

> 
>> +#define        IP_LENGTH_OFFSET        4
>>         /* Get the length of the frame that arrived */
>> -       switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) &
>> -                       0xFFFF0000 ) >> 16) {
>> +       switch (((ntohl(in_be32(addr + ETH_TYPE_OFFSET))) & 0xFFFF0000) >> 16) {
> 
> Why not read 16 bits? Not possible in hardware?

There are a lot of versions of this IP.
It is BE/LE driver and there could be HW issues too. But look below.

> 
>>                 case 0x806:
> 
> Use PROT_ARP from include/net.h

done.

> 
>>                         length = 42 + 20; /* FIXME size of ARP */
> 
> Not sure what this is trying to include, but that seems like it is too big.
> 
> From net.h:
> #define ETHER_HDR_SIZE  (sizeof(struct ethernet_hdr))
> which equals 14 bytes.
> #define ARP_HDR_SIZE    (8+20)
> 
> So it should add up to 14 + 8 + 20 = 42;
> 
> I would use:
> 
>                          length = ETHER_HDR_SIZE + ARP_HDR_SIZE;

Based on
http://image.slidesharecdn.com/arp-140623072259-phpapp01/95/arp-6-638.jpg?cb=1403508219

+ 10 padding and +4 crc.
I see that tsec driver does something with crc but maybe crc are
completely ignored by U-Boot

On the other hand linux is using just ETH_FCS_LEN (4).
I have added +4 for now.


> 
>> -                       debug("ARP Packet\n");
>> +                       debug("ARP Packet %x\n", length);
>>                         break;
>>                 case 0x800:
> 
> Use PROT_IP from include/net.h

fixed.

> 
>>                         length = 14 + 14 +
>> -                       (((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET +
>> -                                               0x10))) & 0xFFFF0000) >> 16);
>> -                       /* FIXME size of IP packet */
>> -                       debug ("IP Packet\n");
>> +                             (((ntohl(in_be32(addr + IP_LENGTH_OFFSET))) &
>> +                              0xFFFF0000) >> 16);
> 
> Why not read 16 bits?

look below.

> 
> If this is reading the total_length field, it seems that it will not
> handle packet fragments well.

Isn't it fragmentation done on one layer up? IP packet header is there
all the time.


>> +                       debug("IP Packet %x\n", length);
>>                         break;
> 
> Can you afford to read the first to read the first 5 words of the
> packet into a buffer and use the structs in net.h to overlay the
> buffer to access the data? That would be a lot cleaner to look at.

I have tried it and it is working fine. I am not reading just 5 words
but I think it is better to read the full align ARP packet size and then
do another read for the rest.
Please look at v2 with this change I think you will like it more than
this one.


> You also need to somehow track fragmented packets. Not sure how to do
> it universally. You sure there's no way to get the frame size from the
> hardware? That seems very limiting.

I haven't seen any problem like this and I expect none has played with
it too.

Thanks,
Michal

  reply	other threads:[~2015-12-17 11:24 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-11 12:03 [U-Boot] [PATCH 00/12] Moving Emaclite to DM + MDIO support Michal Simek
2015-12-11 12:03 ` [U-Boot] [PATCH 01/12] net: emaclite: Remove ancient OF probe function Michal Simek
2015-12-15 21:08   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 02/12] net: emaclite: Add MDIO support to driver Michal Simek
2015-12-15 21:22   ` Joe Hershberger
2015-12-16  8:30     ` Michal Simek
2015-12-11 12:03 ` [U-Boot] [PATCH 03/12] net: emaclite: Convert MDIO to use register offset Michal Simek
2015-12-15 21:32   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 04/12] net: emaclite: Use indirect register access for tx_ping/pong Michal Simek
2015-12-15 21:36   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 05/12] " Michal Simek
2015-12-15 21:36   ` Joe Hershberger
2015-12-16 10:08     ` Michal Simek
2015-12-11 12:03 ` [U-Boot] [PATCH 06/12] net: emaclite: Use indirect register access for TX reset Michal Simek
2015-12-15 21:37   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 07/12] net: emaclite: Fix logic around available TX buffers Michal Simek
2015-12-15 21:38   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 08/12] net: emaclite: Remove XEL_TSR_XMIT_ACTIVE_MASK flag Michal Simek
2015-12-11 12:03 ` [U-Boot] [PATCH 09/12] net: emaclite: Use indirect reg access in send Michal Simek
2015-12-15 21:44   ` Joe Hershberger
2015-12-11 12:03 ` [U-Boot] [PATCH 10/12] net: emaclite: Use indirect access in emaclite_recv Michal Simek
2015-12-15 22:20   ` Joe Hershberger
2015-12-17 11:24     ` Michal Simek [this message]
2015-12-11 12:03 ` [U-Boot] [PATCH 11/12] net: emaclite: Move driver to DM Michal Simek
2015-12-15 22:34   ` Joe Hershberger
2015-12-16  9:52     ` Michal Simek
2015-12-11 12:03 ` [U-Boot] [PATCH 12/12] net: emaclite: Move emaclite to Kconfig Michal Simek
2015-12-15 22:35   ` Joe Hershberger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56729B70.3090603@xilinx.com \
    --to=michal.simek@xilinx.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.