[meta-freescale] [PATCH V3 4/4][linux-fslc][4.1-1.0.x-imx] net: fec: align IP
Eric Nelson
eric at nelint.com
Sat Sep 24 07:00:37 PDT 2016
The FEC receive accelerator (RACC) supports shifting the data payload of
received packets by 16-bits, which aligns the payload (IP header) on a
4-byte boundary, which is, if not required, at least strongly suggested
by the Linux networking layer.
Without this patch, a huge number of alignment faults will be taken by the
IP stack, as seen in /proc/cpu/alignment:
~/$ cat /proc/cpu/alignment
User: 0
System: 72645 (inet_gro_receive+0x104/0x27c)
Skipped: 0
Half: 0
Word: 0
DWord: 0
Multi: 72645
User faults: 3 (fixup+warn)
This patch was suggested by Andrew Lunn in this message to linux-netdev:
http://marc.info/?l=linux-arm-kernel&m=147465452108384&w=2
and adapted from a patch by Russell King from 2014:
http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?id=70d8a8a
Signed-off-by: Eric Nelson <eric at nelint.com>
---
V3 uses FEC_QUIRK_HAS_RACC to test for support, since all devices with the
receive accelerator support the SHIFT16 bit. It also removes support for
FEC_QUIRK_HAS_RACC from i.MX25 and i.MX27 which don't appear to support the
feature and separates the addition of the quirk for i.MX6UL into a separate
patch.
Note that I haven't found the reference manual for mvf600, so this should be
tested.
V2 removes code in fec_enet_copybreak() that strips the two bytes of padding
and breaks the alignment. The call to skb_pull_inline in the caller instructs
the IP stack to ignore these bytes. With V2, no alignment errors are seen.
I've only tested this patch on i.MX6UL at the moment, and encourage others using
4.1.x to try it out.
Note that there are lots of other patches in Russell's tree that deserve
some effort in bringing up-stream and I encourage others to make use of
his work.
drivers/net/ethernet/freescale/fec_main.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c196275..659e1c9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -180,6 +180,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
/* FEC receive acceleration */
#define FEC_RACC_IPDIS (1 << 1)
#define FEC_RACC_PRODIS (1 << 2)
+#define FEC_RACC_SHIFT16 BIT(7)
#define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS)
/*
@@ -985,9 +986,11 @@ fec_restart(struct net_device *ndev)
#if !defined(CONFIG_M5272)
if (fep->quirks & FEC_QUIRK_HAS_RACC) {
- /* set RX checksum */
val = readl(fep->hwp + FEC_RACC);
+ /* align IP header */
+ val |= FEC_RACC_SHIFT16;
if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
+ /* set RX checksum */
val |= FEC_RACC_OPTIONS;
else
val &= ~FEC_RACC_OPTIONS;
@@ -1443,7 +1446,6 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
bdp = rxq->cur_rx;
while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
-
if (pkt_received >= budget)
break;
pkt_received++;
@@ -1504,6 +1506,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
prefetch(skb->data - NET_IP_ALIGN);
skb_put(skb, pkt_len - 4);
data = skb->data;
+
+#if !defined(CONFIG_M5272)
+ if (fep->quirks & FEC_QUIRK_HAS_RACC)
+ data = skb_pull_inline(skb, 2);
+#endif
+
if (!is_copybreak && need_swap)
swap_buffer(data, pkt_len);
--
2.7.4
More information about the meta-freescale
mailing list