Commit 3ac72b7b authored by Eric Nelson's avatar Eric Nelson Committed by David S. Miller

net: fec: align IP header in hardware

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=70d8a8aSigned-off-by: default avatarEric Nelson <eric@nelint.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 97dc499c
...@@ -180,6 +180,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); ...@@ -180,6 +180,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
/* FEC receive acceleration */ /* FEC receive acceleration */
#define FEC_RACC_IPDIS (1 << 1) #define FEC_RACC_IPDIS (1 << 1)
#define FEC_RACC_PRODIS (1 << 2) #define FEC_RACC_PRODIS (1 << 2)
#define FEC_RACC_SHIFT16 BIT(7)
#define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS) #define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS)
/* /*
...@@ -945,9 +946,11 @@ fec_restart(struct net_device *ndev) ...@@ -945,9 +946,11 @@ fec_restart(struct net_device *ndev)
#if !defined(CONFIG_M5272) #if !defined(CONFIG_M5272)
if (fep->quirks & FEC_QUIRK_HAS_RACC) { if (fep->quirks & FEC_QUIRK_HAS_RACC) {
/* set RX checksum */
val = readl(fep->hwp + FEC_RACC); val = readl(fep->hwp + FEC_RACC);
/* align IP header */
val |= FEC_RACC_SHIFT16;
if (fep->csum_flags & FLAG_RX_CSUM_ENABLED) if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
/* set RX checksum */
val |= FEC_RACC_OPTIONS; val |= FEC_RACC_OPTIONS;
else else
val &= ~FEC_RACC_OPTIONS; val &= ~FEC_RACC_OPTIONS;
...@@ -1428,6 +1431,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) ...@@ -1428,6 +1431,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
prefetch(skb->data - NET_IP_ALIGN); prefetch(skb->data - NET_IP_ALIGN);
skb_put(skb, pkt_len - 4); skb_put(skb, pkt_len - 4);
data = skb->data; 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) if (!is_copybreak && need_swap)
swap_buffer(data, pkt_len); swap_buffer(data, pkt_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment