From: Russell King - ARM Linux <hidden> Date: 2014-07-08 12:01:17
David,
Here's the third batch of patches for the Freescale FEC ethernet driver,
based upon the previous set of patches. This concludes the changes I
currently have prepared and have been reviewed for the next merge window
at this time.
Many thanks.
drivers/net/ethernet/freescale/fec.h | 9 +-
drivers/net/ethernet/freescale/fec_main.c | 139 ++++++++++++++----------------
2 files changed, 68 insertions(+), 80 deletions(-)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Russell King <hidden> Date: 2014-07-08 12:01:38
Using a (delayed) workqueue for ERR006358 is not correct - a work queue
is a single-trigger device. Once the work queue has been scheduled, it
can't be re-scheduled until it has been run. This can cause problems -
with an appropriate packet timing, we can end up with packets queued,
but not sent by the hardware, resulting in the transmit timeout firing.
Re-implement this as per the workaround detailed in the ERR006358
documentation - if there are packets waiting to be sent when we service
the transmit ring, and we see that the transmitter is not running,
kick the transmitter to run the pending entries in the ring.
Testing here with a 10Mbit half duplex link sees the resulting iperf
TCP bandwidth increase from between 1 to 2Mbps to between 8 to 9Mbps.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec.h | 1 -
drivers/net/ethernet/freescale/fec_main.c | 30 ++++--------------------------
2 files changed, 4 insertions(+), 27 deletions(-)
@@ -259,7 +259,6 @@ struct bufdesc_ex {structfec_enet_delayed_work{structdelayed_workdelay_work;booltimeout;-booltrig_tx;};/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
@@ -545,8 +529,6 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)status|=(BD_ENET_TX_READY|BD_ENET_TX_TC);bdp->cbd_sc=status;-fec_enet_submit_work(bdp,fep);-/* If this was the last BD in the ring, start at the beginning again. */bdp=fec_enet_get_nextdesc(last_bdp,fep);
@@ -735,8 +717,6 @@ static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev)/* Save skb pointer */fep->tx_skbuff[index]=skb;-fec_enet_submit_work(bdp,fep);-skb_tx_timestamp(skb);fep->cur_tx=bdp;
@@ -1166,7 +1141,10 @@ fec_enet_tx(struct net_device *ndev)netif_wake_queue(ndev);}}-return;++/* ERR006538: Keep the transmitter going */+if(bdp!=fep->cur_tx&&readl(fep->hwp+FEC_X_DES_ACTIVE)==0)+writel(0,fep->hwp+FEC_X_DES_ACTIVE);}/* During a receive, the cur_rx points to the current incoming buffer.
From: Russell King <hidden> Date: 2014-07-08 12:01:44
As of "better implementation of iMX6 ERR006358 quirk", we no longer have
a requirement for a delayed work. Moreover, the work is now only used
for timeout purposes, so the timeout flag is also pointless - we set it
each time we queue the work, and the work clears it.
Replace the fec_enet_delayed_work struct with a standard work_struct,
resulting in simplified timeout handling code.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec.h | 8 ++------
drivers/net/ethernet/freescale/fec_main.c | 34 +++++++++++++------------------
2 files changed, 16 insertions(+), 26 deletions(-)
From: Russell King <hidden> Date: 2014-07-08 12:01:49
Clear any pending receive interrupt before we process a pending packet.
This helps to avoid any spurious interrupts being raised after we have
fully cleaned the receive ring, while still allowing an interrupt to be
raised if we receive another packet.
The position of this is critical: we must do this prior to reading the
next packet status to avoid potentially dropping an interrupt when a
packet is still pending.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec_main.c | 2 ++
1 file changed, 2 insertions(+)
@@ -1184,6 +1184,8 @@ fec_enet_rx(struct net_device *ndev, int budget)if((status&BD_ENET_RX_LAST)==0)netdev_err(ndev,"rcv is not +last\n");+writel(FEC_ENET_RXF,fep->hwp+FEC_IEVENT);+/* Check for errors. */if(status&(BD_ENET_RX_LG|BD_ENET_RX_SH|BD_ENET_RX_NO|BD_ENET_RX_CR|BD_ENET_RX_OV)){
From: Russell King <hidden> Date: 2014-07-08 12:01:54
This allows us to merge two separate preprocessor conditionals together.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec_main.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
From: Russell King <hidden> Date: 2014-07-08 12:01:59
When we timeout on transmit, it would be useful to dump the transmit
ring, so we can see the ring state. This can be helpful to diagnose
the cause of transmit timeouts.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec_main.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
From: Russell King <hidden> Date: 2014-07-08 12:02:04
Remove a useless status check in the transmit reap path - we have
already checked that the BD_ENET_TX_READY bit is clear, and as the
hardware only ever clears this bit, there is no way this test can ever
be true.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec_main.c | 3 ---
1 file changed, 3 deletions(-)
@@ -1133,9 +1133,6 @@ fec_enet_tx(struct net_device *ndev)skb_tstamp_tx(skb,&shhwtstamps);}-if(status&BD_ENET_TX_READY)-netdev_err(ndev,"HEY! Enet xmit interrupt and TX_READY\n");-/* Deferred means some collisions occurred during transmit,*butweeventuallysentthepacketOK.*/
From: Russell King <hidden> Date: 2014-07-08 12:02:09
Both transmit and receive use the same infrastructure for calculating
the packet timestamp. Rather than duplicating the code, provide a
function to do this common work. Model this function in the Intel
e1000e version which avoids calling ns_to_ktime() within the spinlock;
the spinlock is critical for timecounter_cyc2time() but not
ns_to_ktime().
Acked-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec_main.c | 37 ++++++++++++++++---------------
1 file changed, 19 insertions(+), 18 deletions(-)
@@ -1288,18 +1298,9 @@ fec_enet_rx(struct net_device *ndev, int budget)skb->protocol=eth_type_trans(skb,ndev);/* Get receive timestamp from the skb */-if(fep->hwts_rx_en&&fep->bufdesc_ex){-structskb_shared_hwtstamps*shhwtstamps=-skb_hwtstamps(skb);-unsignedlongflags;--memset(shhwtstamps,0,sizeof(*shhwtstamps));--spin_lock_irqsave(&fep->tmreg_lock,flags);-shhwtstamps->hwtstamp=ns_to_ktime(-timecounter_cyc2time(&fep->tc,ebdp->ts));-spin_unlock_irqrestore(&fep->tmreg_lock,flags);-}+if(fep->hwts_rx_en&&fep->bufdesc_ex)+fec_enet_hwtstamp(fep,ebdp->ts,+skb_hwtstamps(skb));if(fep->bufdesc_ex&&(fep->csum_flags&FLAG_RX_CSUM_ENABLED)){
From: Russell King - ARM Linux <redacted>
Date: Tue, 8 Jul 2014 13:01:17 +0100
Here's the third batch of patches for the Freescale FEC ethernet driver,
based upon the previous set of patches. This concludes the changes I
currently have prepared and have been reviewed for the next merge window
at this time.
From: Russell King <hidden> Date: 2014-07-09 09:30:11
Using a (delayed) workqueue for ERR006358 is not correct - a work queue
is a single-trigger device. Once the work queue has been scheduled, it
can't be re-scheduled until it has been run. This can cause problems -
with an appropriate packet timing, we can end up with packets queued,
but not sent by the hardware, resulting in the transmit timeout firing.
Re-implement this as per the workaround detailed in the ERR006358
documentation - if there are packets waiting to be sent when we service
the transmit ring, and we see that the transmitter is not running,
kick the transmitter to run the pending entries in the ring.
Testing here with a 10Mbit half duplex link sees the resulting iperf
TCP bandwidth increase from between 1 to 2Mbps to between 8 to 9Mbps.
Acked-by: Fugang Duan <redacted>
Signed-off-by: Russell King <redacted>
---
drivers/net/ethernet/freescale/fec.h | 1 -
drivers/net/ethernet/freescale/fec_main.c | 30 ++++--------------------------
2 files changed, 4 insertions(+), 27 deletions(-)
@@ -259,7 +259,6 @@ struct bufdesc_ex {structfec_enet_delayed_work{structdelayed_workdelay_work;booltimeout;-booltrig_tx;};/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
@@ -545,8 +529,6 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)status|=(BD_ENET_TX_READY|BD_ENET_TX_TC);bdp->cbd_sc=status;-fec_enet_submit_work(bdp,fep);-/* If this was the last BD in the ring, start at the beginning again. */bdp=fec_enet_get_nextdesc(last_bdp,fep);
@@ -735,8 +717,6 @@ static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev)/* Save skb pointer */fep->tx_skbuff[index]=skb;-fec_enet_submit_work(bdp,fep);-skb_tx_timestamp(skb);fep->cur_tx=bdp;
@@ -1166,7 +1141,10 @@ fec_enet_tx(struct net_device *ndev)netif_wake_queue(ndev);}}-return;++/* ERR006538: Keep the transmitter going */+if(bdp!=fep->cur_tx&&readl(fep->hwp+FEC_X_DES_ACTIVE)==0)+writel(0,fep->hwp+FEC_X_DES_ACTIVE);}/* During a receive, the cur_rx points to the current incoming buffer.
From: Russell King - ARM Linux <hidden> Date: 2014-07-09 09:33:09
On Wed, Jul 09, 2014 at 10:30:11AM +0100, Russell King wrote:
Using a (delayed) workqueue for ERR006358 is not correct - a work queue
is a single-trigger device. Once the work queue has been scheduled, it
can't be re-scheduled until it has been run. This can cause problems -
with an appropriate packet timing, we can end up with packets queued,
but not sent by the hardware, resulting in the transmit timeout firing.
Oops, please ignore this patch; re-sent in error.
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.