summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManfred Rudigier <Manfred.Rudigier@omicron.at>2016-01-20 11:22:28 +0100
committerSasha Levin <sasha.levin@oracle.com>2016-03-04 10:25:46 -0500
commit0c0c5254583eb9a77e62a4391094258907e08ea1 (patch)
tree1ee430e70f13a7e16abc71495a79116f15f2c88c
parent257ed6d440536351b9ceca7005ee89fbcc352b75 (diff)
downloadlinux-exynos-0c0c5254583eb9a77e62a4391094258907e08ea1.tar.gz
linux-exynos-0c0c5254583eb9a77e62a4391094258907e08ea1.tar.bz2
linux-exynos-0c0c5254583eb9a77e62a4391094258907e08ea1.zip
net: dp83640: Fix tx timestamp overflow handling.
[ Upstream commit 81e8f2e930fe76b9814c71b9d87c30760b5eb705 ] PHY status frames are not reliable, the PHY may not be able to send them during heavy receive traffic. This overflow condition is signaled by the PHY in the next status frame, but the driver did not make use of it. Instead it always reported wrong tx timestamps to user space after an overflow happened because it assigned newly received tx timestamps to old packets in the queue. This commit fixes this issue by clearing the tx timestamp queue every time an overflow happens, so that no timestamps are delivered for overflow packets. This way time stamping will continue correctly after an overflow. Signed-off-by: Manfred Rudigier <manfred.rudigier@omicron.at> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
-rw-r--r--drivers/net/phy/dp83640.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 00cb41e71312..c56cf0b86f2c 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -833,6 +833,11 @@ static void decode_rxts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps *shhwtstamps = NULL;
struct sk_buff *skb;
unsigned long flags;
+ u8 overflow;
+
+ overflow = (phy_rxts->ns_hi >> 14) & 0x3;
+ if (overflow)
+ pr_debug("rx timestamp queue overflow, count %d\n", overflow);
spin_lock_irqsave(&dp83640->rx_lock, flags);
@@ -875,6 +880,7 @@ static void decode_txts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff *skb;
u64 ns;
+ u8 overflow;
/* We must already have the skb that triggered this. */
@@ -884,6 +890,17 @@ static void decode_txts(struct dp83640_private *dp83640,
pr_debug("have timestamp but tx_queue empty\n");
return;
}
+
+ overflow = (phy_txts->ns_hi >> 14) & 0x3;
+ if (overflow) {
+ pr_debug("tx timestamp queue overflow, count %d\n", overflow);
+ while (skb) {
+ skb_complete_tx_timestamp(skb, NULL);
+ skb = skb_dequeue(&dp83640->tx_queue);
+ }
+ return;
+ }
+
ns = phy2txts(phy_txts);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(ns);