Code Review
/
kvmfornfv.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git]
/
kernel
/
drivers
/
net
/
phy
/
dp83640.c
diff --git
a/kernel/drivers/net/phy/dp83640.c
b/kernel/drivers/net/phy/dp83640.c
index
00cb41e
..
e6cefd0
100644
(file)
--- a/
kernel/drivers/net/phy/dp83640.c
+++ b/
kernel/drivers/net/phy/dp83640.c
@@
-20,6
+20,7
@@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/ethtool.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@
-36,8
+37,6
@@
#define DP83640_PHY_ID 0x20005ce1
#define PAGESEL 0x13
#define DP83640_PHY_ID 0x20005ce1
#define PAGESEL 0x13
-#define LAYER4 0x02
-#define LAYER2 0x01
#define MAX_RXTS 64
#define N_EXT_TS 6
#define N_PER_OUT 7
#define MAX_RXTS 64
#define N_EXT_TS 6
#define N_PER_OUT 7
@@
-68,6
+67,8
@@
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
/* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16
+#define SKB_TIMESTAMP_TIMEOUT 2 /* jiffies */
+
#if defined(__BIG_ENDIAN)
#define ENDIAN_FLAG 0
#elif defined(__LITTLE_ENDIAN)
#if defined(__BIG_ENDIAN)
#define ENDIAN_FLAG 0
#elif defined(__LITTLE_ENDIAN)
@@
-110,7
+111,7
@@
struct dp83640_private {
struct list_head list;
struct dp83640_clock *clock;
struct phy_device *phydev;
struct list_head list;
struct dp83640_clock *clock;
struct phy_device *phydev;
- struct
work_struct
ts_work;
+ struct
delayed_work
ts_work;
int hwts_tx_en;
int hwts_rx_en;
int layer;
int hwts_tx_en;
int hwts_rx_en;
int layer;
@@
-284,7
+285,7
@@
static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
rxts->seqid = p->seqid;
rxts->msgtype = (p->msgtype >> 12) & 0xf;
rxts->hash = p->msgtype & 0x0fff;
rxts->seqid = p->seqid;
rxts->msgtype = (p->msgtype >> 12) & 0xf;
rxts->hash = p->msgtype & 0x0fff;
- rxts->tmo = jiffies +
2
;
+ rxts->tmo = jiffies +
SKB_TIMESTAMP_TIMEOUT
;
}
static u64 phy2txts(struct phy_txts *p)
}
static u64 phy2txts(struct phy_txts *p)
@@
-787,9
+788,12
@@
static int decode_evnt(struct dp83640_private *dp83640,
return parsed;
}
return parsed;
}
+#define DP83640_PACKET_HASH_OFFSET 20
+#define DP83640_PACKET_HASH_LEN 10
+
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
- u16 *seqid;
+ u16 *seqid
, hash
;
unsigned int offset = 0;
u8 *msgtype, *data = skb_mac_header(skb);
unsigned int offset = 0;
u8 *msgtype, *data = skb_mac_header(skb);
@@
-819,11
+823,19
@@
static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
msgtype = data + offset + OFF_PTP_CONTROL;
else
msgtype = data + offset;
msgtype = data + offset + OFF_PTP_CONTROL;
else
msgtype = data + offset;
+ if (rxts->msgtype != (*msgtype & 0xf))
+ return 0;
seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+ if (rxts->seqid != ntohs(*seqid))
+ return 0;
- return rxts->msgtype == (*msgtype & 0xf) &&
- rxts->seqid == ntohs(*seqid);
+ hash = ether_crc(DP83640_PACKET_HASH_LEN,
+ data + offset + DP83640_PACKET_HASH_OFFSET) >> 20;
+ if (rxts->hash != hash)
+ return 0;
+
+ return 1;
}
static void decode_rxts(struct dp83640_private *dp83640,
}
static void decode_rxts(struct dp83640_private *dp83640,
@@
-833,6
+845,11
@@
static void decode_rxts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps *shhwtstamps = NULL;
struct sk_buff *skb;
unsigned long flags;
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);
spin_lock_irqsave(&dp83640->rx_lock, flags);
@@
-875,6
+892,7
@@
static void decode_txts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff *skb;
u64 ns;
struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff *skb;
u64 ns;
+ u8 overflow;
/* We must already have the skb that triggered this. */
/* We must already have the skb that triggered this. */
@@
-884,6
+902,17
@@
static void decode_txts(struct dp83640_private *dp83640,
pr_debug("have timestamp but tx_queue empty\n");
return;
}
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);
ns = phy2txts(phy_txts);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(ns);
@@
-1103,7
+1132,7
@@
static int dp83640_probe(struct phy_device *phydev)
goto no_memory;
dp83640->phydev = phydev;
goto no_memory;
dp83640->phydev = phydev;
- INIT_WORK(&dp83640->ts_work, rx_timestamp_work);
+ INIT_
DELAYED_
WORK(&dp83640->ts_work, rx_timestamp_work);
INIT_LIST_HEAD(&dp83640->rxts);
INIT_LIST_HEAD(&dp83640->rxpool);
INIT_LIST_HEAD(&dp83640->rxts);
INIT_LIST_HEAD(&dp83640->rxpool);
@@
-1150,7
+1179,7
@@
static void dp83640_remove(struct phy_device *phydev)
return;
enable_status_frames(phydev, false);
return;
enable_status_frames(phydev, false);
- cancel_work_sync(&dp83640->ts_work);
+ cancel_
delayed_
work_sync(&dp83640->ts_work);
skb_queue_purge(&dp83640->rx_queue);
skb_queue_purge(&dp83640->tx_queue);
skb_queue_purge(&dp83640->rx_queue);
skb_queue_purge(&dp83640->tx_queue);
@@
-1282,29
+1311,29
@@
static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer =
LAYER
4;
- dp83640->version = 1;
+ dp83640->layer =
PTP_CLASS_L
4;
+ dp83640->version =
PTP_CLASS_V
1;
break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer =
LAYER
4;
- dp83640->version = 2;
+ dp83640->layer =
PTP_CLASS_L
4;
+ dp83640->version =
PTP_CLASS_V
2;
break;
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
break;
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer =
LAYER
2;
- dp83640->version = 2;
+ dp83640->layer =
PTP_CLASS_L
2;
+ dp83640->version =
PTP_CLASS_V
2;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
dp83640->hwts_rx_en = 1;
- dp83640->layer =
LAYER4|LAYER
2;
- dp83640->version = 2;
+ dp83640->layer =
PTP_CLASS_L4 | PTP_CLASS_L
2;
+ dp83640->version =
PTP_CLASS_V
2;
break;
default:
return -ERANGE;
break;
default:
return -ERANGE;
@@
-1313,11
+1342,11
@@
static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
- if (dp83640->layer &
LAYER
2) {
+ if (dp83640->layer &
PTP_CLASS_L
2) {
txcfg0 |= TX_L2_EN;
rxcfg0 |= RX_L2_EN;
}
txcfg0 |= TX_L2_EN;
rxcfg0 |= RX_L2_EN;
}
- if (dp83640->layer &
LAYER
4) {
+ if (dp83640->layer &
PTP_CLASS_L
4) {
txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
}
txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
}
@@
-1344,7
+1373,7
@@
static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
static void rx_timestamp_work(struct work_struct *work)
{
struct dp83640_private *dp83640 =
static void rx_timestamp_work(struct work_struct *work)
{
struct dp83640_private *dp83640 =
- container_of(work, struct dp83640_private, ts_work);
+ container_of(work, struct dp83640_private, ts_work
.work
);
struct sk_buff *skb;
/* Deliver expired packets. */
struct sk_buff *skb;
/* Deliver expired packets. */
@@
-1361,7
+1390,7
@@
static void rx_timestamp_work(struct work_struct *work)
}
if (!skb_queue_empty(&dp83640->rx_queue))
}
if (!skb_queue_empty(&dp83640->rx_queue))
- schedule_
work(&dp83640->ts_work
);
+ schedule_
delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT
);
}
static bool dp83640_rxtstamp(struct phy_device *phydev,
}
static bool dp83640_rxtstamp(struct phy_device *phydev,
@@
-1383,7
+1412,11
@@
static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!dp83640->hwts_rx_en)
return false;
if (!dp83640->hwts_rx_en)
return false;
+ if ((type & dp83640->version) == 0 || (type & dp83640->layer) == 0)
+ return false;
+
spin_lock_irqsave(&dp83640->rx_lock, flags);
spin_lock_irqsave(&dp83640->rx_lock, flags);
+ prune_rx_ts(dp83640);
list_for_each_safe(this, next, &dp83640->rxts) {
rxts = list_entry(this, struct rxts, list);
if (match(skb, type, rxts)) {
list_for_each_safe(this, next, &dp83640->rxts) {
rxts = list_entry(this, struct rxts, list);
if (match(skb, type, rxts)) {
@@
-1400,9
+1433,11
@@
static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!shhwtstamps) {
skb_info->ptp_type = type;
if (!shhwtstamps) {
skb_info->ptp_type = type;
- skb_info->tmo = jiffies +
2
;
+ skb_info->tmo = jiffies +
SKB_TIMESTAMP_TIMEOUT
;
skb_queue_tail(&dp83640->rx_queue, skb);
skb_queue_tail(&dp83640->rx_queue, skb);
- schedule_work(&dp83640->ts_work);
+ schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
+ } else {
+ netif_rx_ni(skb);
}
return true;
}
return true;
@@
-1449,17
+1484,9
@@
static int dp83640_ts_info(struct phy_device *dev, struct ethtool_ts_info *info)
info->rx_filters =
(1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
info->rx_filters =
(1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
- (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
- (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
- (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
- (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
- (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
- (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
- (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
- (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
- (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
return 0;
}
return 0;
}