Commit 85013ab5 authored by David S. Miller's avatar David S. Miller

Merge branch 'dp83640-fixes'

Stefan Sørensen says:

====================
dp83640 driver fixes

This series fixes a number of minor bugs in the dp83640 driver.
====================
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0561e8e8 a1f8723f
...@@ -20,6 +20,7 @@ ...@@ -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/ethtool.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -36,8 +37,6 @@ ...@@ -36,8 +37,6 @@
#define DP83640_PHY_ID 0x20005ce1 #define DP83640_PHY_ID 0x20005ce1
#define PAGESEL 0x13 #define PAGESEL 0x13
#define LAYER4 0x02
#define LAYER2 0x01
#define MAX_RXTS 64 #define MAX_RXTS 64
#define N_EXT_TS 6 #define N_EXT_TS 6
#define N_PER_OUT 7 #define N_PER_OUT 7
...@@ -68,6 +67,8 @@ ...@@ -68,6 +67,8 @@
/* phyter seems to miss the mark by 16 ns */ /* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16 #define ADJTIME_FIX 16
#define SKB_TIMESTAMP_TIMEOUT 2 /* jiffies */
#if defined(__BIG_ENDIAN) #if defined(__BIG_ENDIAN)
#define ENDIAN_FLAG 0 #define ENDIAN_FLAG 0
#elif defined(__LITTLE_ENDIAN) #elif defined(__LITTLE_ENDIAN)
...@@ -110,7 +111,7 @@ struct dp83640_private { ...@@ -110,7 +111,7 @@ struct dp83640_private {
struct list_head list; struct list_head list;
struct dp83640_clock *clock; struct dp83640_clock *clock;
struct phy_device *phydev; struct phy_device *phydev;
struct work_struct ts_work; struct delayed_work ts_work;
int hwts_tx_en; int hwts_tx_en;
int hwts_rx_en; int hwts_rx_en;
int layer; int layer;
...@@ -284,7 +285,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts) ...@@ -284,7 +285,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
rxts->seqid = p->seqid; rxts->seqid = p->seqid;
rxts->msgtype = (p->msgtype >> 12) & 0xf; rxts->msgtype = (p->msgtype >> 12) & 0xf;
rxts->hash = p->msgtype & 0x0fff; 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, ...@@ -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; unsigned int offset = 0;
u8 *msgtype, *data = skb_mac_header(skb); u8 *msgtype, *data = skb_mac_header(skb);
...@@ -819,11 +823,19 @@ static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) ...@@ -819,11 +823,19 @@ static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
msgtype = data + offset + OFF_PTP_CONTROL; msgtype = data + offset + OFF_PTP_CONTROL;
else else
msgtype = data + offset; 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;
hash = ether_crc(DP83640_PACKET_HASH_LEN,
data + offset + DP83640_PACKET_HASH_OFFSET) >> 20;
if (rxts->hash != hash)
return 0;
return rxts->msgtype == (*msgtype & 0xf) && return 1;
rxts->seqid == ntohs(*seqid);
} }
static void decode_rxts(struct dp83640_private *dp83640, static void decode_rxts(struct dp83640_private *dp83640,
...@@ -1103,7 +1115,7 @@ static int dp83640_probe(struct phy_device *phydev) ...@@ -1103,7 +1115,7 @@ static int dp83640_probe(struct phy_device *phydev)
goto no_memory; goto no_memory;
dp83640->phydev = phydev; 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->rxts);
INIT_LIST_HEAD(&dp83640->rxpool); INIT_LIST_HEAD(&dp83640->rxpool);
...@@ -1150,7 +1162,7 @@ static void dp83640_remove(struct phy_device *phydev) ...@@ -1150,7 +1162,7 @@ static void dp83640_remove(struct phy_device *phydev)
return; return;
enable_status_frames(phydev, false); 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->rx_queue);
skb_queue_purge(&dp83640->tx_queue); skb_queue_purge(&dp83640->tx_queue);
...@@ -1282,29 +1294,29 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) ...@@ -1282,29 +1294,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_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1; dp83640->hwts_rx_en = 1;
dp83640->layer = LAYER4; dp83640->layer = PTP_CLASS_L4;
dp83640->version = 1; dp83640->version = PTP_CLASS_V1;
break; break;
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
dp83640->hwts_rx_en = 1; dp83640->hwts_rx_en = 1;
dp83640->layer = LAYER4; dp83640->layer = PTP_CLASS_L4;
dp83640->version = 2; dp83640->version = PTP_CLASS_V2;
break; break;
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
dp83640->hwts_rx_en = 1; dp83640->hwts_rx_en = 1;
dp83640->layer = LAYER2; dp83640->layer = PTP_CLASS_L2;
dp83640->version = 2; dp83640->version = PTP_CLASS_V2;
break; break;
case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
dp83640->hwts_rx_en = 1; dp83640->hwts_rx_en = 1;
dp83640->layer = LAYER4|LAYER2; dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
dp83640->version = 2; dp83640->version = PTP_CLASS_V2;
break; break;
default: default:
return -ERANGE; return -ERANGE;
...@@ -1313,11 +1325,11 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) ...@@ -1313,11 +1325,11 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
txcfg0 = (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; rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT;
if (dp83640->layer & LAYER2) { if (dp83640->layer & PTP_CLASS_L2) {
txcfg0 |= TX_L2_EN; txcfg0 |= TX_L2_EN;
rxcfg0 |= RX_L2_EN; rxcfg0 |= RX_L2_EN;
} }
if (dp83640->layer & LAYER4) { if (dp83640->layer & PTP_CLASS_L4) {
txcfg0 |= TX_IPV6_EN | TX_IPV4_EN; txcfg0 |= TX_IPV6_EN | TX_IPV4_EN;
rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN; rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN;
} }
...@@ -1344,7 +1356,7 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) ...@@ -1344,7 +1356,7 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
static void rx_timestamp_work(struct work_struct *work) static void rx_timestamp_work(struct work_struct *work)
{ {
struct dp83640_private *dp83640 = 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; struct sk_buff *skb;
/* Deliver expired packets. */ /* Deliver expired packets. */
...@@ -1361,7 +1373,7 @@ static void rx_timestamp_work(struct work_struct *work) ...@@ -1361,7 +1373,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 +1395,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, ...@@ -1383,7 +1395,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!dp83640->hwts_rx_en) if (!dp83640->hwts_rx_en)
return false; 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) { list_for_each_safe(this, next, &dp83640->rxts) {
rxts = list_entry(this, struct rxts, list); rxts = list_entry(this, struct rxts, list);
if (match(skb, type, rxts)) { if (match(skb, type, rxts)) {
...@@ -1400,9 +1416,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, ...@@ -1400,9 +1416,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!shhwtstamps) { if (!shhwtstamps) {
skb_info->ptp_type = type; 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;
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
#define PTP_CLASS_VMASK 0x0f /* max protocol version is 15 */ #define PTP_CLASS_VMASK 0x0f /* max protocol version is 15 */
#define PTP_CLASS_IPV4 0x10 /* event in an IPV4 UDP packet */ #define PTP_CLASS_IPV4 0x10 /* event in an IPV4 UDP packet */
#define PTP_CLASS_IPV6 0x20 /* event in an IPV6 UDP packet */ #define PTP_CLASS_IPV6 0x20 /* event in an IPV6 UDP packet */
#define PTP_CLASS_L2 0x30 /* event in a L2 packet */ #define PTP_CLASS_L2 0x40 /* event in a L2 packet */
#define PTP_CLASS_PMASK 0x30 /* mask for the packet type field */ #define PTP_CLASS_PMASK 0x70 /* mask for the packet type field */
#define PTP_CLASS_VLAN 0x40 /* event in a VLAN tagged packet */ #define PTP_CLASS_VLAN 0x80 /* event in a VLAN tagged packet */
#define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4) #define PTP_CLASS_V1_IPV4 (PTP_CLASS_V1 | PTP_CLASS_IPV4)
#define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /* probably DNE */ #define PTP_CLASS_V1_IPV6 (PTP_CLASS_V1 | PTP_CLASS_IPV6) /* probably DNE */
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6) #define PTP_CLASS_V2_IPV6 (PTP_CLASS_V2 | PTP_CLASS_IPV6)
#define PTP_CLASS_V2_L2 (PTP_CLASS_V2 | PTP_CLASS_L2) #define PTP_CLASS_V2_L2 (PTP_CLASS_V2 | PTP_CLASS_L2)
#define PTP_CLASS_V2_VLAN (PTP_CLASS_V2 | PTP_CLASS_VLAN) #define PTP_CLASS_V2_VLAN (PTP_CLASS_V2 | PTP_CLASS_VLAN)
#define PTP_CLASS_L4 (PTP_CLASS_IPV4 | PTP_CLASS_IPV6)
#define PTP_EV_PORT 319 #define PTP_EV_PORT 319
#define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */ #define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
* jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these
* ldh [18] ; reload payload * ldh [18] ; reload payload
* and #0xf ; mask PTP_CLASS_VMASK * and #0xf ; mask PTP_CLASS_VMASK
* or #0x70 ; PTP_CLASS_VLAN|PTP_CLASS_L2 * or #0xc0 ; PTP_CLASS_VLAN|PTP_CLASS_L2
* ret a ; return PTP class * ret a ; return PTP class
* *
* ; PTP over UDP over IPv4 over 802.1Q over Ethernet * ; PTP over UDP over IPv4 over 802.1Q over Ethernet
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
* jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ? * jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ?
* ldh [x + 26] ; load payload * ldh [x + 26] ; load payload
* and #0xf ; mask PTP_CLASS_VMASK * and #0xf ; mask PTP_CLASS_VMASK
* or #0x50 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4 * or #0x90 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4
* ret a ; return PTP class * ret a ; return PTP class
* drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE * drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE
* *
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
* jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ? * jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ?
* ldh [66] ; load payload * ldh [66] ; load payload
* and #0xf ; mask PTP_CLASS_VMASK * and #0xf ; mask PTP_CLASS_VMASK
* or #0x60 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6 * or #0xa0 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6
* ret a ; return PTP class * ret a ; return PTP class
* drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE * drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE
* *
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
* jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these
* ldh [14] ; reload payload * ldh [14] ; reload payload
* and #0xf ; mask PTP_CLASS_VMASK * and #0xf ; mask PTP_CLASS_VMASK
* or #0x30 ; PTP_CLASS_L2 * or #0x40 ; PTP_CLASS_L2
* ret a ; return PTP class * ret a ; return PTP class
* drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE * drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE
*/ */
...@@ -150,7 +150,7 @@ void __init ptp_classifier_init(void) ...@@ -150,7 +150,7 @@ void __init ptp_classifier_init(void)
{ 0x15, 0, 35, 0x00000000 }, { 0x15, 0, 35, 0x00000000 },
{ 0x28, 0, 0, 0x00000012 }, { 0x28, 0, 0, 0x00000012 },
{ 0x54, 0, 0, 0x0000000f }, { 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000070 }, { 0x44, 0, 0, 0x000000c0 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x15, 0, 12, 0x00000800 }, { 0x15, 0, 12, 0x00000800 },
{ 0x30, 0, 0, 0x0000001b }, { 0x30, 0, 0, 0x0000001b },
...@@ -162,7 +162,7 @@ void __init ptp_classifier_init(void) ...@@ -162,7 +162,7 @@ void __init ptp_classifier_init(void)
{ 0x15, 0, 4, 0x0000013f }, { 0x15, 0, 4, 0x0000013f },
{ 0x48, 0, 0, 0x0000001a }, { 0x48, 0, 0, 0x0000001a },
{ 0x54, 0, 0, 0x0000000f }, { 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000050 }, { 0x44, 0, 0, 0x00000090 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 }, { 0x06, 0, 0, 0x00000000 },
{ 0x15, 0, 8, 0x000086dd }, { 0x15, 0, 8, 0x000086dd },
...@@ -172,7 +172,7 @@ void __init ptp_classifier_init(void) ...@@ -172,7 +172,7 @@ void __init ptp_classifier_init(void)
{ 0x15, 0, 4, 0x0000013f }, { 0x15, 0, 4, 0x0000013f },
{ 0x28, 0, 0, 0x00000042 }, { 0x28, 0, 0, 0x00000042 },
{ 0x54, 0, 0, 0x0000000f }, { 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000060 }, { 0x44, 0, 0, 0x000000a0 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 }, { 0x06, 0, 0, 0x00000000 },
{ 0x15, 0, 7, 0x000088f7 }, { 0x15, 0, 7, 0x000088f7 },
...@@ -181,7 +181,7 @@ void __init ptp_classifier_init(void) ...@@ -181,7 +181,7 @@ void __init ptp_classifier_init(void)
{ 0x15, 0, 4, 0x00000000 }, { 0x15, 0, 4, 0x00000000 },
{ 0x28, 0, 0, 0x0000000e }, { 0x28, 0, 0, 0x0000000e },
{ 0x54, 0, 0, 0x0000000f }, { 0x54, 0, 0, 0x0000000f },
{ 0x44, 0, 0, 0x00000030 }, { 0x44, 0, 0, 0x00000040 },
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 }, { 0x06, 0, 0, 0x00000000 },
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment