All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header
@ 2016-09-24  1:44 Eric Nelson
  2016-09-24  5:00 ` Andy Duan
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Nelson @ 2016-09-24  1:44 UTC (permalink / raw)
  To: meta-freescale; +Cc: andrew, linux, fugang.duan, otavio

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@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 +++++++++++++++++++++++++------
 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)
+
 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



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header
  2016-09-24  1:44 [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header Eric Nelson
@ 2016-09-24  5:00 ` Andy Duan
  2016-09-24 12:46   ` Eric Nelson
  0 siblings, 1 reply; 3+ messages in thread
From: Andy Duan @ 2016-09-24  5:00 UTC (permalink / raw)
  To: Eric Nelson, meta-freescale; +Cc: andrew, linux, otavio

From: Eric Nelson <eric@nelint.com> Sent: Saturday, September 24, 2016 9:44 AM
> To: meta-freescale@yoctoproject.org
> Cc: linux@arm.linux.org.uk; andrew@lunn.ch; Andy Duan
> <fugang.duan@nxp.com>; otavio@ossystems.com.br; Eric Nelson
> <eric@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@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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header
  2016-09-24  5:00 ` Andy Duan
@ 2016-09-24 12:46   ` Eric Nelson
  0 siblings, 0 replies; 3+ messages in thread
From: Eric Nelson @ 2016-09-24 12:46 UTC (permalink / raw)
  To: Andy Duan, meta-freescale; +Cc: andrew, linux, otavio

Hi Andy,

On 09/23/2016 10:00 PM, Andy Duan wrote:
> From: Eric Nelson <eric@nelint.com> Sent: Saturday, September 24, 2016 9:44 AM
>> To: meta-freescale@yoctoproject.org
>> Cc: linux@arm.linux.org.uk; andrew@lunn.ch; Andy Duan
>> <fugang.duan@nxp.com>; otavio@ossystems.com.br; Eric Nelson
>> <eric@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@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.   
> 

I just checked, and I was wrong in my comment about the SoloX
using a different bit. I think I was looking at the bitfield in the
ENETx_TACC register.

Okay. I'll re-work this for a V3 on linux-fslc.



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-09-24 13:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-24  1:44 [PATCH][linux-fslc][4.1-1.0.x-imx] net: fec: support RRACC_SHIFT16 to align IP header Eric Nelson
2016-09-24  5:00 ` Andy Duan
2016-09-24 12:46   ` Eric Nelson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.