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