aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/phy/dp83640.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index f99937905bd..be381c24c4b 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -761,6 +761,41 @@ static void decode_status_frame(struct dp83640_private *dp83640,
761 } 761 }
762} 762}
763 763
764static int is_sync(struct sk_buff *skb, int type)
765{
766 u8 *data = skb->data, *msgtype;
767 unsigned int offset = 0;
768
769 switch (type) {
770 case PTP_CLASS_V1_IPV4:
771 case PTP_CLASS_V2_IPV4:
772 offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
773 break;
774 case PTP_CLASS_V1_IPV6:
775 case PTP_CLASS_V2_IPV6:
776 offset = OFF_PTP6;
777 break;
778 case PTP_CLASS_V2_L2:
779 offset = ETH_HLEN;
780 break;
781 case PTP_CLASS_V2_VLAN:
782 offset = ETH_HLEN + VLAN_HLEN;
783 break;
784 default:
785 return 0;
786 }
787
788 if (type & PTP_CLASS_V1)
789 offset += OFF_PTP_CONTROL;
790
791 if (skb->len < offset + 1)
792 return 0;
793
794 msgtype = data + offset;
795
796 return (*msgtype & 0xf) == 0;
797}
798
764static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) 799static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
765{ 800{
766 u16 *seqid; 801 u16 *seqid;
@@ -1010,16 +1045,10 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
1010 if (cfg.flags) /* reserved for future extensions */ 1045 if (cfg.flags) /* reserved for future extensions */
1011 return -EINVAL; 1046 return -EINVAL;
1012 1047
1013 switch (cfg.tx_type) { 1048 if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ONESTEP_SYNC)
1014 case HWTSTAMP_TX_OFF:
1015 dp83640->hwts_tx_en = 0;
1016 break;
1017 case HWTSTAMP_TX_ON:
1018 dp83640->hwts_tx_en = 1;
1019 break;
1020 default:
1021 return -ERANGE; 1049 return -ERANGE;
1022 } 1050
1051 dp83640->hwts_tx_en = cfg.tx_type;
1023 1052
1024 switch (cfg.rx_filter) { 1053 switch (cfg.rx_filter) {
1025 case HWTSTAMP_FILTER_NONE: 1054 case HWTSTAMP_FILTER_NONE:
@@ -1074,6 +1103,9 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
1074 if (dp83640->hwts_tx_en) 1103 if (dp83640->hwts_tx_en)
1075 txcfg0 |= TX_TS_EN; 1104 txcfg0 |= TX_TS_EN;
1076 1105
1106 if (dp83640->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC)
1107 txcfg0 |= SYNC_1STEP | CHK_1STEP;
1108
1077 if (dp83640->hwts_rx_en) 1109 if (dp83640->hwts_rx_en)
1078 rxcfg0 |= RX_TS_EN; 1110 rxcfg0 |= RX_TS_EN;
1079 1111
@@ -1156,12 +1188,24 @@ static void dp83640_txtstamp(struct phy_device *phydev,
1156{ 1188{
1157 struct dp83640_private *dp83640 = phydev->priv; 1189 struct dp83640_private *dp83640 = phydev->priv;
1158 1190
1159 if (!dp83640->hwts_tx_en) { 1191 switch (dp83640->hwts_tx_en) {
1192
1193 case HWTSTAMP_TX_ONESTEP_SYNC:
1194 if (is_sync(skb, type)) {
1195 kfree_skb(skb);
1196 return;
1197 }
1198 /* fall through */
1199 case HWTSTAMP_TX_ON:
1200 skb_queue_tail(&dp83640->tx_queue, skb);
1201 schedule_work(&dp83640->ts_work);
1202 break;
1203
1204 case HWTSTAMP_TX_OFF:
1205 default:
1160 kfree_skb(skb); 1206 kfree_skb(skb);
1161 return; 1207 break;
1162 } 1208 }
1163 skb_queue_tail(&dp83640->tx_queue, skb);
1164 schedule_work(&dp83640->ts_work);
1165} 1209}
1166 1210
1167static struct phy_driver dp83640_driver = { 1211static struct phy_driver dp83640_driver = {