* [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.