diff options
Diffstat (limited to 'drivers/net/igb')
-rw-r--r-- | drivers/net/igb/e1000_82575.h | 1 | ||||
-rw-r--r-- | drivers/net/igb/e1000_defines.h | 1 | ||||
-rw-r--r-- | drivers/net/igb/e1000_regs.h | 40 | ||||
-rw-r--r-- | drivers/net/igb/igb.h | 4 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 266 |
5 files changed, 304 insertions, 8 deletions
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index dd50237c8cb0..e613d5a606d8 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h | |||
@@ -116,6 +116,7 @@ union e1000_adv_tx_desc { | |||
116 | }; | 116 | }; |
117 | 117 | ||
118 | /* Adv Transmit Descriptor Config Masks */ | 118 | /* Adv Transmit Descriptor Config Masks */ |
119 | #define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ | ||
119 | #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ | 120 | #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ |
120 | #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ | 121 | #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ |
121 | #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ | 122 | #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ |
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 5342e231c1d5..79168eeaaa09 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h | |||
@@ -104,6 +104,7 @@ | |||
104 | #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ | 104 | #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ |
105 | #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ | 105 | #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ |
106 | #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ | 106 | #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ |
107 | #define E1000_RXD_STAT_TS 0x10000 /* Pkt was time stamped */ | ||
107 | #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ | 108 | #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ |
108 | #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ | 109 | #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ |
109 | #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ | 110 | #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ |
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 64d95cd71f2e..1fb19ca081c6 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h | |||
@@ -78,9 +78,37 @@ | |||
78 | 78 | ||
79 | /* IEEE 1588 TIMESYNCH */ | 79 | /* IEEE 1588 TIMESYNCH */ |
80 | #define E1000_TSYNCTXCTL 0x0B614 | 80 | #define E1000_TSYNCTXCTL 0x0B614 |
81 | #define E1000_TSYNCTXCTL_VALID (1<<0) | ||
82 | #define E1000_TSYNCTXCTL_ENABLED (1<<4) | ||
81 | #define E1000_TSYNCRXCTL 0x0B620 | 83 | #define E1000_TSYNCRXCTL 0x0B620 |
84 | #define E1000_TSYNCRXCTL_VALID (1<<0) | ||
85 | #define E1000_TSYNCRXCTL_ENABLED (1<<4) | ||
86 | enum { | ||
87 | E1000_TSYNCRXCTL_TYPE_L2_V2 = 0, | ||
88 | E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<1), | ||
89 | E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<2), | ||
90 | E1000_TSYNCRXCTL_TYPE_ALL = (1<<3), | ||
91 | E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<3) | (1<<1), | ||
92 | }; | ||
82 | #define E1000_TSYNCRXCFG 0x05F50 | 93 | #define E1000_TSYNCRXCFG 0x05F50 |
94 | enum { | ||
95 | E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0<<0, | ||
96 | E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1<<0, | ||
97 | E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2<<0, | ||
98 | E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3<<0, | ||
99 | E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4<<0, | ||
83 | 100 | ||
101 | E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0<<8, | ||
102 | E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1<<8, | ||
103 | E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2<<8, | ||
104 | E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3<<8, | ||
105 | E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8<<8, | ||
106 | E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9<<8, | ||
107 | E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA<<8, | ||
108 | E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB<<8, | ||
109 | E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC<<8, | ||
110 | E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD<<8, | ||
111 | }; | ||
84 | #define E1000_SYSTIML 0x0B600 | 112 | #define E1000_SYSTIML 0x0B600 |
85 | #define E1000_SYSTIMH 0x0B604 | 113 | #define E1000_SYSTIMH 0x0B604 |
86 | #define E1000_TIMINCA 0x0B608 | 114 | #define E1000_TIMINCA 0x0B608 |
@@ -103,6 +131,18 @@ | |||
103 | #define E1000_ETQF6 0x05CC8 | 131 | #define E1000_ETQF6 0x05CC8 |
104 | #define E1000_ETQF7 0x05CCC | 132 | #define E1000_ETQF7 0x05CCC |
105 | 133 | ||
134 | /* Filtering Registers */ | ||
135 | #define E1000_SAQF(_n) (0x5980 + 4 * (_n)) | ||
136 | #define E1000_DAQF(_n) (0x59A0 + 4 * (_n)) | ||
137 | #define E1000_SPQF(_n) (0x59C0 + 4 * (_n)) | ||
138 | #define E1000_FTQF(_n) (0x59E0 + 4 * (_n)) | ||
139 | #define E1000_SAQF0 E1000_SAQF(0) | ||
140 | #define E1000_DAQF0 E1000_DAQF(0) | ||
141 | #define E1000_SPQF0 E1000_SPQF(0) | ||
142 | #define E1000_FTQF0 E1000_FTQF(0) | ||
143 | #define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ | ||
144 | #define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ | ||
145 | |||
106 | /* Split and Replication RX Control - RW */ | 146 | /* Split and Replication RX Control - RW */ |
107 | /* | 147 | /* |
108 | * Convenience macros | 148 | * Convenience macros |
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 797a9fe107ad..bb8c35cec1ab 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #include "e1000_82575.h" | 35 | #include "e1000_82575.h" |
36 | 36 | ||
37 | #include <linux/clocksource.h> | 37 | #include <linux/clocksource.h> |
38 | #include <linux/timecompare.h> | ||
39 | #include <linux/net_tstamp.h> | ||
38 | 40 | ||
39 | struct igb_adapter; | 41 | struct igb_adapter; |
40 | 42 | ||
@@ -255,6 +257,8 @@ struct igb_adapter { | |||
255 | struct net_device_stats net_stats; | 257 | struct net_device_stats net_stats; |
256 | struct cyclecounter cycles; | 258 | struct cyclecounter cycles; |
257 | struct timecounter clock; | 259 | struct timecounter clock; |
260 | struct timecompare compare; | ||
261 | struct hwtstamp_config hwtstamp_config; | ||
258 | 262 | ||
259 | /* structs defined in e1000_hw.h */ | 263 | /* structs defined in e1000_hw.h */ |
260 | struct e1000_hw hw; | 264 | struct e1000_hw hw; |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 90090bb26044..f9d576bfef90 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -250,7 +250,8 @@ static char *igb_get_time_str(struct igb_adapter *adapter, | |||
250 | delta = timespec_sub(nic, sys); | 250 | delta = timespec_sub(nic, sys); |
251 | 251 | ||
252 | sprintf(buffer, | 252 | sprintf(buffer, |
253 | "NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", | 253 | "HW %llu, NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", |
254 | hw, | ||
254 | (long)nic.tv_sec, nic.tv_nsec, | 255 | (long)nic.tv_sec, nic.tv_nsec, |
255 | (long)sys.tv_sec, sys.tv_nsec, | 256 | (long)sys.tv_sec, sys.tv_nsec, |
256 | (long)delta.tv_sec, delta.tv_nsec); | 257 | (long)delta.tv_sec, delta.tv_nsec); |
@@ -1400,6 +1401,18 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
1400 | &adapter->cycles, | 1401 | &adapter->cycles, |
1401 | ktime_to_ns(ktime_get_real())); | 1402 | ktime_to_ns(ktime_get_real())); |
1402 | 1403 | ||
1404 | /* | ||
1405 | * Synchronize our NIC clock against system wall clock. NIC | ||
1406 | * time stamp reading requires ~3us per sample, each sample | ||
1407 | * was pretty stable even under load => only require 10 | ||
1408 | * samples for each offset comparison. | ||
1409 | */ | ||
1410 | memset(&adapter->compare, 0, sizeof(adapter->compare)); | ||
1411 | adapter->compare.source = &adapter->clock; | ||
1412 | adapter->compare.target = ktime_get_real; | ||
1413 | adapter->compare.num_samples = 10; | ||
1414 | timecompare_update(&adapter->compare, 0); | ||
1415 | |||
1403 | #ifdef DEBUG | 1416 | #ifdef DEBUG |
1404 | { | 1417 | { |
1405 | char buffer[160]; | 1418 | char buffer[160]; |
@@ -2748,6 +2761,7 @@ set_itr_now: | |||
2748 | #define IGB_TX_FLAGS_VLAN 0x00000002 | 2761 | #define IGB_TX_FLAGS_VLAN 0x00000002 |
2749 | #define IGB_TX_FLAGS_TSO 0x00000004 | 2762 | #define IGB_TX_FLAGS_TSO 0x00000004 |
2750 | #define IGB_TX_FLAGS_IPV4 0x00000008 | 2763 | #define IGB_TX_FLAGS_IPV4 0x00000008 |
2764 | #define IGB_TX_FLAGS_TSTAMP 0x00000010 | ||
2751 | #define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 | 2765 | #define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 |
2752 | #define IGB_TX_FLAGS_VLAN_SHIFT 16 | 2766 | #define IGB_TX_FLAGS_VLAN_SHIFT 16 |
2753 | 2767 | ||
@@ -2975,6 +2989,9 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter, | |||
2975 | if (tx_flags & IGB_TX_FLAGS_VLAN) | 2989 | if (tx_flags & IGB_TX_FLAGS_VLAN) |
2976 | cmd_type_len |= E1000_ADVTXD_DCMD_VLE; | 2990 | cmd_type_len |= E1000_ADVTXD_DCMD_VLE; |
2977 | 2991 | ||
2992 | if (tx_flags & IGB_TX_FLAGS_TSTAMP) | ||
2993 | cmd_type_len |= E1000_ADVTXD_MAC_TSTAMP; | ||
2994 | |||
2978 | if (tx_flags & IGB_TX_FLAGS_TSO) { | 2995 | if (tx_flags & IGB_TX_FLAGS_TSO) { |
2979 | cmd_type_len |= E1000_ADVTXD_DCMD_TSE; | 2996 | cmd_type_len |= E1000_ADVTXD_DCMD_TSE; |
2980 | 2997 | ||
@@ -3065,6 +3082,7 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, | |||
3065 | unsigned int tx_flags = 0; | 3082 | unsigned int tx_flags = 0; |
3066 | u8 hdr_len = 0; | 3083 | u8 hdr_len = 0; |
3067 | int tso = 0; | 3084 | int tso = 0; |
3085 | union skb_shared_tx *shtx; | ||
3068 | 3086 | ||
3069 | if (test_bit(__IGB_DOWN, &adapter->state)) { | 3087 | if (test_bit(__IGB_DOWN, &adapter->state)) { |
3070 | dev_kfree_skb_any(skb); | 3088 | dev_kfree_skb_any(skb); |
@@ -3085,7 +3103,29 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb, | |||
3085 | /* this is a hard error */ | 3103 | /* this is a hard error */ |
3086 | return NETDEV_TX_BUSY; | 3104 | return NETDEV_TX_BUSY; |
3087 | } | 3105 | } |
3088 | skb_orphan(skb); | 3106 | |
3107 | /* | ||
3108 | * TODO: check that there currently is no other packet with | ||
3109 | * time stamping in the queue | ||
3110 | * | ||
3111 | * When doing time stamping, keep the connection to the socket | ||
3112 | * a while longer: it is still needed by skb_hwtstamp_tx(), | ||
3113 | * called either in igb_tx_hwtstamp() or by our caller when | ||
3114 | * doing software time stamping. | ||
3115 | */ | ||
3116 | shtx = skb_tx(skb); | ||
3117 | if (unlikely(shtx->hardware)) { | ||
3118 | shtx->in_progress = 1; | ||
3119 | tx_flags |= IGB_TX_FLAGS_TSTAMP; | ||
3120 | } else if (likely(!shtx->software)) { | ||
3121 | /* | ||
3122 | * TODO: can this be solved in dev.c:dev_hard_start_xmit()? | ||
3123 | * There are probably unmodified driver which do something | ||
3124 | * like this and thus don't work in combination with | ||
3125 | * SOF_TIMESTAMPING_TX_SOFTWARE. | ||
3126 | */ | ||
3127 | skb_orphan(skb); | ||
3128 | } | ||
3089 | 3129 | ||
3090 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { | 3130 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { |
3091 | tx_flags |= IGB_TX_FLAGS_VLAN; | 3131 | tx_flags |= IGB_TX_FLAGS_VLAN; |
@@ -3744,6 +3784,43 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget) | |||
3744 | } | 3784 | } |
3745 | 3785 | ||
3746 | /** | 3786 | /** |
3787 | * igb_hwtstamp - utility function which checks for TX time stamp | ||
3788 | * @adapter: board private structure | ||
3789 | * @skb: packet that was just sent | ||
3790 | * | ||
3791 | * If we were asked to do hardware stamping and such a time stamp is | ||
3792 | * available, then it must have been for this skb here because we only | ||
3793 | * allow only one such packet into the queue. | ||
3794 | */ | ||
3795 | static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb) | ||
3796 | { | ||
3797 | union skb_shared_tx *shtx = skb_tx(skb); | ||
3798 | struct e1000_hw *hw = &adapter->hw; | ||
3799 | |||
3800 | if (unlikely(shtx->hardware)) { | ||
3801 | u32 valid = rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID; | ||
3802 | if (valid) { | ||
3803 | u64 regval = rd32(E1000_TXSTMPL); | ||
3804 | u64 ns; | ||
3805 | struct skb_shared_hwtstamps shhwtstamps; | ||
3806 | |||
3807 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); | ||
3808 | regval |= (u64)rd32(E1000_TXSTMPH) << 32; | ||
3809 | ns = timecounter_cyc2time(&adapter->clock, | ||
3810 | regval); | ||
3811 | timecompare_update(&adapter->compare, ns); | ||
3812 | shhwtstamps.hwtstamp = ns_to_ktime(ns); | ||
3813 | shhwtstamps.syststamp = | ||
3814 | timecompare_transform(&adapter->compare, ns); | ||
3815 | skb_tstamp_tx(skb, &shhwtstamps); | ||
3816 | } | ||
3817 | |||
3818 | /* delayed orphaning: skb_tstamp_tx() needs the socket */ | ||
3819 | skb_orphan(skb); | ||
3820 | } | ||
3821 | } | ||
3822 | |||
3823 | /** | ||
3747 | * igb_clean_tx_irq - Reclaim resources after transmit completes | 3824 | * igb_clean_tx_irq - Reclaim resources after transmit completes |
3748 | * @adapter: board private structure | 3825 | * @adapter: board private structure |
3749 | * returns true if ring is completely cleaned | 3826 | * returns true if ring is completely cleaned |
@@ -3781,6 +3858,8 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring) | |||
3781 | skb->len; | 3858 | skb->len; |
3782 | total_packets += segs; | 3859 | total_packets += segs; |
3783 | total_bytes += bytecount; | 3860 | total_bytes += bytecount; |
3861 | |||
3862 | igb_tx_hwtstamp(adapter, skb); | ||
3784 | } | 3863 | } |
3785 | 3864 | ||
3786 | igb_unmap_and_free_tx_resource(adapter, buffer_info); | 3865 | igb_unmap_and_free_tx_resource(adapter, buffer_info); |
@@ -3914,6 +3993,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
3914 | { | 3993 | { |
3915 | struct igb_adapter *adapter = rx_ring->adapter; | 3994 | struct igb_adapter *adapter = rx_ring->adapter; |
3916 | struct net_device *netdev = adapter->netdev; | 3995 | struct net_device *netdev = adapter->netdev; |
3996 | struct e1000_hw *hw = &adapter->hw; | ||
3917 | struct pci_dev *pdev = adapter->pdev; | 3997 | struct pci_dev *pdev = adapter->pdev; |
3918 | union e1000_adv_rx_desc *rx_desc , *next_rxd; | 3998 | union e1000_adv_rx_desc *rx_desc , *next_rxd; |
3919 | struct igb_buffer *buffer_info , *next_buffer; | 3999 | struct igb_buffer *buffer_info , *next_buffer; |
@@ -4006,6 +4086,47 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
4006 | goto next_desc; | 4086 | goto next_desc; |
4007 | } | 4087 | } |
4008 | send_up: | 4088 | send_up: |
4089 | /* | ||
4090 | * If this bit is set, then the RX registers contain | ||
4091 | * the time stamp. No other packet will be time | ||
4092 | * stamped until we read these registers, so read the | ||
4093 | * registers to make them available again. Because | ||
4094 | * only one packet can be time stamped at a time, we | ||
4095 | * know that the register values must belong to this | ||
4096 | * one here and therefore we don't need to compare | ||
4097 | * any of the additional attributes stored for it. | ||
4098 | * | ||
4099 | * If nothing went wrong, then it should have a | ||
4100 | * skb_shared_tx that we can turn into a | ||
4101 | * skb_shared_hwtstamps. | ||
4102 | * | ||
4103 | * TODO: can time stamping be triggered (thus locking | ||
4104 | * the registers) without the packet reaching this point | ||
4105 | * here? In that case RX time stamping would get stuck. | ||
4106 | * | ||
4107 | * TODO: in "time stamp all packets" mode this bit is | ||
4108 | * not set. Need a global flag for this mode and then | ||
4109 | * always read the registers. Cannot be done without | ||
4110 | * a race condition. | ||
4111 | */ | ||
4112 | if (unlikely(staterr & E1000_RXD_STAT_TS)) { | ||
4113 | u64 regval; | ||
4114 | u64 ns; | ||
4115 | struct skb_shared_hwtstamps *shhwtstamps = | ||
4116 | skb_hwtstamps(skb); | ||
4117 | |||
4118 | WARN(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID), | ||
4119 | "igb: no RX time stamp available for time stamped packet"); | ||
4120 | regval = rd32(E1000_RXSTMPL); | ||
4121 | regval |= (u64)rd32(E1000_RXSTMPH) << 32; | ||
4122 | ns = timecounter_cyc2time(&adapter->clock, regval); | ||
4123 | timecompare_update(&adapter->compare, ns); | ||
4124 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); | ||
4125 | shhwtstamps->hwtstamp = ns_to_ktime(ns); | ||
4126 | shhwtstamps->syststamp = | ||
4127 | timecompare_transform(&adapter->compare, ns); | ||
4128 | } | ||
4129 | |||
4009 | if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { | 4130 | if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { |
4010 | dev_kfree_skb_irq(skb); | 4131 | dev_kfree_skb_irq(skb); |
4011 | goto next_desc; | 4132 | goto next_desc; |
@@ -4188,13 +4309,33 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | |||
4188 | * @ifreq: | 4309 | * @ifreq: |
4189 | * @cmd: | 4310 | * @cmd: |
4190 | * | 4311 | * |
4191 | * Currently cannot enable any kind of hardware time stamping, but | 4312 | * Outgoing time stamping can be enabled and disabled. Play nice and |
4192 | * supports SIOCSHWTSTAMP in general. | 4313 | * disable it when requested, although it shouldn't case any overhead |
4314 | * when no packet needs it. At most one packet in the queue may be | ||
4315 | * marked for time stamping, otherwise it would be impossible to tell | ||
4316 | * for sure to which packet the hardware time stamp belongs. | ||
4317 | * | ||
4318 | * Incoming time stamping has to be configured via the hardware | ||
4319 | * filters. Not all combinations are supported, in particular event | ||
4320 | * type has to be specified. Matching the kind of event packet is | ||
4321 | * not supported, with the exception of "all V2 events regardless of | ||
4322 | * level 2 or 4". | ||
4323 | * | ||
4193 | **/ | 4324 | **/ |
4194 | static int igb_hwtstamp_ioctl(struct net_device *netdev, | 4325 | static int igb_hwtstamp_ioctl(struct net_device *netdev, |
4195 | struct ifreq *ifr, int cmd) | 4326 | struct ifreq *ifr, int cmd) |
4196 | { | 4327 | { |
4328 | struct igb_adapter *adapter = netdev_priv(netdev); | ||
4329 | struct e1000_hw *hw = &adapter->hw; | ||
4197 | struct hwtstamp_config config; | 4330 | struct hwtstamp_config config; |
4331 | u32 tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED; | ||
4332 | u32 tsync_rx_ctl_bit = E1000_TSYNCRXCTL_ENABLED; | ||
4333 | u32 tsync_rx_ctl_type = 0; | ||
4334 | u32 tsync_rx_cfg = 0; | ||
4335 | int is_l4 = 0; | ||
4336 | int is_l2 = 0; | ||
4337 | short port = 319; /* PTP */ | ||
4338 | u32 regval; | ||
4198 | 4339 | ||
4199 | if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) | 4340 | if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) |
4200 | return -EFAULT; | 4341 | return -EFAULT; |
@@ -4203,11 +4344,120 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev, | |||
4203 | if (config.flags) | 4344 | if (config.flags) |
4204 | return -EINVAL; | 4345 | return -EINVAL; |
4205 | 4346 | ||
4206 | if (config.tx_type == HWTSTAMP_TX_OFF && | 4347 | switch (config.tx_type) { |
4207 | config.rx_filter == HWTSTAMP_FILTER_NONE) | 4348 | case HWTSTAMP_TX_OFF: |
4208 | return 0; | 4349 | tsync_tx_ctl_bit = 0; |
4350 | break; | ||
4351 | case HWTSTAMP_TX_ON: | ||
4352 | tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED; | ||
4353 | break; | ||
4354 | default: | ||
4355 | return -ERANGE; | ||
4356 | } | ||
4357 | |||
4358 | switch (config.rx_filter) { | ||
4359 | case HWTSTAMP_FILTER_NONE: | ||
4360 | tsync_rx_ctl_bit = 0; | ||
4361 | break; | ||
4362 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
4363 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
4364 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
4365 | case HWTSTAMP_FILTER_ALL: | ||
4366 | /* | ||
4367 | * register TSYNCRXCFG must be set, therefore it is not | ||
4368 | * possible to time stamp both Sync and Delay_Req messages | ||
4369 | * => fall back to time stamping all packets | ||
4370 | */ | ||
4371 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL; | ||
4372 | config.rx_filter = HWTSTAMP_FILTER_ALL; | ||
4373 | break; | ||
4374 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
4375 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1; | ||
4376 | tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; | ||
4377 | is_l4 = 1; | ||
4378 | break; | ||
4379 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
4380 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1; | ||
4381 | tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; | ||
4382 | is_l4 = 1; | ||
4383 | break; | ||
4384 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
4385 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
4386 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2; | ||
4387 | tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; | ||
4388 | is_l2 = 1; | ||
4389 | is_l4 = 1; | ||
4390 | config.rx_filter = HWTSTAMP_FILTER_SOME; | ||
4391 | break; | ||
4392 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
4393 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
4394 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2; | ||
4395 | tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; | ||
4396 | is_l2 = 1; | ||
4397 | is_l4 = 1; | ||
4398 | config.rx_filter = HWTSTAMP_FILTER_SOME; | ||
4399 | break; | ||
4400 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||
4401 | case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||
4402 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
4403 | tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2; | ||
4404 | config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; | ||
4405 | is_l2 = 1; | ||
4406 | break; | ||
4407 | default: | ||
4408 | return -ERANGE; | ||
4409 | } | ||
4410 | |||
4411 | /* enable/disable TX */ | ||
4412 | regval = rd32(E1000_TSYNCTXCTL); | ||
4413 | regval = (regval & ~E1000_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit; | ||
4414 | wr32(E1000_TSYNCTXCTL, regval); | ||
4415 | |||
4416 | /* enable/disable RX, define which PTP packets are time stamped */ | ||
4417 | regval = rd32(E1000_TSYNCRXCTL); | ||
4418 | regval = (regval & ~E1000_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit; | ||
4419 | regval = (regval & ~0xE) | tsync_rx_ctl_type; | ||
4420 | wr32(E1000_TSYNCRXCTL, regval); | ||
4421 | wr32(E1000_TSYNCRXCFG, tsync_rx_cfg); | ||
4422 | |||
4423 | /* | ||
4424 | * Ethertype Filter Queue Filter[0][15:0] = 0x88F7 | ||
4425 | * (Ethertype to filter on) | ||
4426 | * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter) | ||
4427 | * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping) | ||
4428 | */ | ||
4429 | wr32(E1000_ETQF0, is_l2 ? 0x440088f7 : 0); | ||
4430 | |||
4431 | /* L4 Queue Filter[0]: only filter by source and destination port */ | ||
4432 | wr32(E1000_SPQF0, htons(port)); | ||
4433 | wr32(E1000_IMIREXT(0), is_l4 ? | ||
4434 | ((1<<12) | (1<<19) /* bypass size and control flags */) : 0); | ||
4435 | wr32(E1000_IMIR(0), is_l4 ? | ||
4436 | (htons(port) | ||
4437 | | (0<<16) /* immediate interrupt disabled */ | ||
4438 | | 0 /* (1<<17) bit cleared: do not bypass | ||
4439 | destination port check */) | ||
4440 | : 0); | ||
4441 | wr32(E1000_FTQF0, is_l4 ? | ||
4442 | (0x11 /* UDP */ | ||
4443 | | (1<<15) /* VF not compared */ | ||
4444 | | (1<<27) /* Enable Timestamping */ | ||
4445 | | (7<<28) /* only source port filter enabled, | ||
4446 | source/target address and protocol | ||
4447 | masked */) | ||
4448 | : ((1<<15) | (15<<28) /* all mask bits set = filter not | ||
4449 | enabled */)); | ||
4450 | |||
4451 | wrfl(); | ||
4452 | |||
4453 | adapter->hwtstamp_config = config; | ||
4454 | |||
4455 | /* clear TX/RX time stamp registers, just to be sure */ | ||
4456 | regval = rd32(E1000_TXSTMPH); | ||
4457 | regval = rd32(E1000_RXSTMPH); | ||
4209 | 4458 | ||
4210 | return -ERANGE; | 4459 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? |
4460 | -EFAULT : 0; | ||
4211 | } | 4461 | } |
4212 | 4462 | ||
4213 | /** | 4463 | /** |