[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