[meta-freescale] [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header
Andy Duan
fugang.duan at nxp.com
Fri Sep 23 22:00:42 PDT 2016
From: Eric Nelson <eric at nelint.com> Sent: Saturday, September 24, 2016 9:44 AM
> To: meta-freescale at yoctoproject.org
> Cc: linux at arm.linux.org.uk; andrew at lunn.ch; Andy Duan
> <fugang.duan at nxp.com>; otavio at ossystems.com.br; Eric Nelson
> <eric at nelint.com>
> Subject: [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16
> to align IP header
>
> The i.MX6 UL and DQLS variants all support shifting the data payload of
> received packets by 16-bits, which aligns the IP header on a longword
> 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)
>
> With this patch, I am still seeing some alignment faults, but on the order of 10
> after a 100MiB transfer instead of the 72k shown above.
>
> 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/?h=fec-
> testing&id=70d8a8a
>
> Signed-off-by: Eric Nelson <eric at nelint.com>
> ---
> I've only tested this patch on i.MX6UL at the moment, an encourage others
> using 4.1.x to try it out.
>
> I did look at the RM for the i.MX6SX and updates will be needed for that
> machine because the bit appears to be in a different location.
>
> 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.h | 4 ++++
> drivers/net/ethernet/freescale/fec_main.c | 36
Test pass the patch on i.MX6UL.
But still have some comments as below.
> +++++++++++++++++++++++++------
> 2 files changed, 34 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/fec.h
> b/drivers/net/ethernet/freescale/fec.h
> index 65a3cd3..5ed0a5c 100644
> --- a/drivers/net/ethernet/freescale/fec.h
> +++ b/drivers/net/ethernet/freescale/fec.h
> @@ -436,6 +436,7 @@ struct bufdesc_ex {
> #define FEC_QUIRK_SINGLE_MDIO (1 << 11)
> /* Controller supports RACC register */
> #define FEC_QUIRK_HAS_RACC (1 << 12)
> +
> /*
> * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx &
> rx
> * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
> @@ -443,6 +444,9 @@ struct bufdesc_ex {
> */
> #define FEC_QUIRK_BUG_WAITMODE (1 << 13)
>
> +/* Controller has ability to offset rx packets */
> +#define FEC_QUIRK_RX_SHIFT16 (1 << 14)
> +
It is not necessary to define the quirk flag.
All SOCs with RACC register has the bit.
> struct fec_enet_stop_mode {
> struct regmap *gpr;
> u8 req_gpr;
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 0f9ed22..a58d5d0 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -103,7 +103,8 @@ static struct platform_device_id fec_devtype[] = {
> .driver_data = FEC_QUIRK_ENET_MAC |
> FEC_QUIRK_HAS_GBIT |
> FEC_QUIRK_HAS_BUFDESC_EX |
> FEC_QUIRK_HAS_CSUM |
> FEC_QUIRK_HAS_VLAN |
> FEC_QUIRK_ERR006358 |
> - FEC_QUIRK_HAS_RACC |
> FEC_QUIRK_BUG_WAITMODE,
> + FEC_QUIRK_HAS_RACC |
> FEC_QUIRK_BUG_WAITMODE |
> + FEC_QUIRK_RX_SHIFT16,
> }, {
> .name = "mvf600-fec",
> .driver_data = FEC_QUIRK_ENET_MAC |
> FEC_QUIRK_HAS_RACC, @@ -118,7 +119,8 @@ static struct
> platform_device_id fec_devtype[] = {
> .name = "imx6ul-fec",
> .driver_data = FEC_QUIRK_ENET_MAC |
> FEC_QUIRK_HAS_GBIT |
> FEC_QUIRK_HAS_BUFDESC_EX |
> FEC_QUIRK_HAS_CSUM |
> - FEC_QUIRK_HAS_VLAN,
> + FEC_QUIRK_HAS_VLAN |
> FEC_QUIRK_HAS_RACC |
> + FEC_QUIRK_RX_SHIFT16,
> }, {
> /* sentinel */
> }
> @@ -180,6 +182,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 +988,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);
> + if (fep->quirks & FEC_QUIRK_RX_SHIFT16)
> + val |= FEC_RACC_SHIFT16;
> if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
> + /* set RX checksum */
> val |= FEC_RACC_OPTIONS;
> else
> val &= ~FEC_RACC_OPTIONS;
> @@ -1387,6 +1392,7 @@ static bool fec_enet_copybreak(struct net_device
> *ndev, struct sk_buff **skb, {
> struct fec_enet_private *fep = netdev_priv(ndev);
> struct sk_buff *new_skb;
> + unsigned char *data = (*skb)->data;
>
> if (length > fep->rx_copybreak)
> return false;
> @@ -1395,13 +1401,25 @@ static bool fec_enet_copybreak(struct
> net_device *ndev, struct sk_buff **skb,
> if (!new_skb)
> return false;
>
> +#ifndef CONFIG_M5272
> + /*
> + * If we have enabled this feature, we need to discard
> + * the two bytes at the beginning of the packet before
> + * copying it.
> + */
> + if (fep->quirks & FEC_QUIRK_RX_SHIFT16) {
> + length -= 2;
> + data += 2;
> + }
> +#endif
> +
> dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
> FEC_ENET_RX_FRSIZE - fep->rx_align,
> DMA_FROM_DEVICE);
> if (!swap)
> - memcpy(new_skb->data, (*skb)->data, length);
> + memcpy(new_skb->data, data, length);
> else
> - swap_buffer2(new_skb->data, (*skb)->data, length);
> + swap_buffer2(new_skb->data, data, length);
> *skb = new_skb;
>
> return true;
> @@ -1420,7 +1438,6 @@ fec_enet_rx_queue(struct net_device *ndev, int
> budget, u16 queue_id)
> struct bufdesc *bdp;
> unsigned short status;
> struct sk_buff *skb_new = NULL;
> - struct sk_buff *skb;
> ushort pkt_len;
> __u8 *data;
> int pkt_received = 0;
> @@ -1443,6 +1460,7 @@ 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)) {
> + struct sk_buff *skb;
>
> if (pkt_received >= budget)
> break;
> @@ -1504,6 +1522,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 (!is_copybreak && (fep->quirks &
> FEC_QUIRK_RX_SHIFT16))
> + 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