From: Steve Chen <sc...@mvista.com>

The skb data allocated for packet data received is 4 byte aligned.

Unfortunately, this causes non-32bit aligned accesses in IP stack because
the MAC header is non-word aligned (14 bytes).

The result can be observed by looking at /proc/cpu/alignment while the
device is over network.

This issue is resolved by using a 2-byte extra offset in the packet buffer.

A quick performance test over lab network using iperf on DM6446 EVM showed
an increase in bandwidth from 60Mbits/s to 70Mbits/s.

Signed-off-by: Steve Chen <sc...@mvista.com>
Signed-off-by: Sekhar Nori <nsek...@ti.com>
---
 drivers/net/davinci_emac.c |   21 +++++++++++++++++----
 1 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 635e31f..471126a 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -349,6 +349,15 @@ static const char emac_version_string[] = "TI DaVinci EMAC 
Linux v6.0";
 #define EMAC_DM646X_MAC_EOI_C0_RXEN    (0x01)
 #define EMAC_DM646X_MAC_EOI_C0_TXEN    (0x02)
 
+/*
+ * L3 Alignment mechanism: The below given macro returns the number of
+ * bytes required to align the given size to a L3 frame 4 byte
+ * boundry. This is typically required to add 2 bytes to the ethernet
+ * frame start to make sure the IP header (L3) is aligned on a 4 byte
+ * boundry
+ */
+#define EMAC_L3_ALIGN(size)    ((2 - (size)) & 0x3)
+
 /** net_buf_obj: EMAC network bufferdata structure
  *
  * EMAC network buffer data structure
@@ -1560,7 +1569,8 @@ static void *emac_net_alloc_rx_buf(struct emac_priv 
*priv, int buf_size,
 
        /* set device pointer in skb and reserve space for extra bytes */
        p_skb->dev = ndev;
-       skb_reserve(p_skb, EMAC_DEF_EXTRA_RXBUF_SIZE);
+       skb_reserve(p_skb, EMAC_DEF_EXTRA_RXBUF_SIZE +
+                   EMAC_L3_ALIGN(EMAC_DEF_EXTRA_RXBUF_SIZE));
        *data_token = (void *) p_skb;
        EMAC_CACHE_WRITEBACK_INVALIDATE((unsigned long)p_skb->data, buf_size);
        return p_skb->data;
@@ -1990,8 +2000,9 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, 
u32 budget,
               (pkts_processed < budget)) {
 
                new_buffer = emac_net_alloc_rx_buf(priv,
-                                       EMAC_DEF_MAX_FRAME_SIZE,
-                                       &new_buf_token, EMAC_DEF_RX_CH);
+                               EMAC_DEF_MAX_FRAME_SIZE +
+                               EMAC_L3_ALIGN(EMAC_DEF_EXTRA_RXBUF_SIZE),
+                               &new_buf_token, EMAC_DEF_RX_CH);
                if (unlikely(NULL == new_buffer)) {
                        ++rxch->out_of_rx_buffers;
                        goto end_emac_rx_bdproc;
@@ -2411,7 +2422,9 @@ static int emac_dev_open(struct net_device *ndev)
                ndev->dev_addr[cnt] = priv->mac_addr[cnt];
 
        /* Configuration items */
-       priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + EMAC_DEF_EXTRA_RXBUF_SIZE;
+       priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE +
+                           EMAC_DEF_EXTRA_RXBUF_SIZE +
+                           EMAC_L3_ALIGN(EMAC_DEF_EXTRA_RXBUF_SIZE);
 
        /* Clear basic hardware */
        for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) {
-- 
1.6.0.3

_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to