diff options
author | Jacob Keller <jacob.e.keller@intel.com> | 2012-08-24 03:46:54 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-10-03 10:57:04 -0400 |
commit | db0677fa29862d29e9956980d9fab43c52179e34 (patch) | |
tree | 8c96754fbc9507c860e246f55d7ac1710eb3beae | |
parent | 8208367371b7f581dd13fe8bf28f8d7f17f4bf32 (diff) |
ixgbe: (PTP) Fix PPS interrupt code
Driver was enabling PPS interrupt even when user wasn't enabling it via the
ptp core. This patch fixes the PPS so that it is only enabled explicitly, and
moves the interrupt enabling code into the correct location in the driver
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Cc: Stable <stable@vger.kernel.org> [3.5]
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 96 |
2 files changed, 48 insertions, 61 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 868af6938219..c407b2f0f0f9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -2322,6 +2322,12 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, | |||
2322 | default: | 2322 | default: |
2323 | break; | 2323 | break; |
2324 | } | 2324 | } |
2325 | |||
2326 | #ifdef CONFIG_IXGBE_PTP | ||
2327 | if (adapter->hw.mac.type == ixgbe_mac_X540) | ||
2328 | mask |= IXGBE_EIMS_TIMESYNC; | ||
2329 | #endif | ||
2330 | |||
2325 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && | 2331 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && |
2326 | !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) | 2332 | !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) |
2327 | mask |= IXGBE_EIMS_FLOW_DIR; | 2333 | mask |= IXGBE_EIMS_FLOW_DIR; |
@@ -2385,8 +2391,10 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) | |||
2385 | } | 2391 | } |
2386 | 2392 | ||
2387 | ixgbe_check_fan_failure(adapter, eicr); | 2393 | ixgbe_check_fan_failure(adapter, eicr); |
2394 | |||
2388 | #ifdef CONFIG_IXGBE_PTP | 2395 | #ifdef CONFIG_IXGBE_PTP |
2389 | ixgbe_ptp_check_pps_event(adapter, eicr); | 2396 | if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) |
2397 | ixgbe_ptp_check_pps_event(adapter, eicr); | ||
2390 | #endif | 2398 | #endif |
2391 | 2399 | ||
2392 | /* re-enable the original interrupt state, no lsc, no queues */ | 2400 | /* re-enable the original interrupt state, no lsc, no queues */ |
@@ -2580,7 +2588,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) | |||
2580 | 2588 | ||
2581 | ixgbe_check_fan_failure(adapter, eicr); | 2589 | ixgbe_check_fan_failure(adapter, eicr); |
2582 | #ifdef CONFIG_IXGBE_PTP | 2590 | #ifdef CONFIG_IXGBE_PTP |
2583 | ixgbe_ptp_check_pps_event(adapter, eicr); | 2591 | if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) |
2592 | ixgbe_ptp_check_pps_event(adapter, eicr); | ||
2584 | #endif | 2593 | #endif |
2585 | 2594 | ||
2586 | /* would disable interrupts here but EIAM disabled it */ | 2595 | /* would disable interrupts here but EIAM disabled it */ |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 58d930dc6766..d9291316ee9f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | |||
@@ -106,39 +106,43 @@ static struct sock_filter ptp_filter[] = { | |||
106 | }; | 106 | }; |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * ixgbe_ptp_enable_sdp | 109 | * ixgbe_ptp_setup_sdp |
110 | * @hw: the hardware private structure | 110 | * @hw: the hardware private structure |
111 | * @shift: the clock shift for calculating nanoseconds | ||
112 | * | 111 | * |
113 | * this function enables the clock out feature on the sdp0 for the | 112 | * this function enables or disables the clock out feature on SDP0 for |
114 | * X540 device. It will create a 1second periodic output that can be | 113 | * the X540 device. It will create a 1second periodic output that can |
115 | * used as the PPS (via an interrupt). | 114 | * be used as the PPS (via an interrupt). |
116 | * | 115 | * |
117 | * It calculates when the systime will be on an exact second, and then | 116 | * It calculates when the systime will be on an exact second, and then |
118 | * aligns the start of the PPS signal to that value. The shift is | 117 | * aligns the start of the PPS signal to that value. The shift is |
119 | * necessary because it can change based on the link speed. | 118 | * necessary because it can change based on the link speed. |
120 | */ | 119 | */ |
121 | static void ixgbe_ptp_enable_sdp(struct ixgbe_adapter *adapter) | 120 | static void ixgbe_ptp_setup_sdp(struct ixgbe_adapter *adapter) |
122 | { | 121 | { |
123 | struct ixgbe_hw *hw = &adapter->hw; | 122 | struct ixgbe_hw *hw = &adapter->hw; |
124 | int shift = adapter->cc.shift; | 123 | int shift = adapter->cc.shift; |
125 | u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; | 124 | u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; |
126 | u64 ns = 0, clock_edge = 0; | 125 | u64 ns = 0, clock_edge = 0; |
127 | 126 | ||
128 | switch (hw->mac.type) { | 127 | if ((adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED) && |
129 | case ixgbe_mac_X540: | 128 | (hw->mac.type == ixgbe_mac_X540)) { |
129 | |||
130 | /* disable the pin first */ | ||
131 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); | ||
132 | IXGBE_WRITE_FLUSH(hw); | ||
133 | |||
130 | esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | 134 | esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); |
131 | 135 | ||
132 | /* | 136 | /* |
133 | * enable the SDP0 pin as output, and connected to the native | 137 | * enable the SDP0 pin as output, and connected to the |
134 | * function for Timesync (ClockOut) | 138 | * native function for Timesync (ClockOut) |
135 | */ | 139 | */ |
136 | esdp |= (IXGBE_ESDP_SDP0_DIR | | 140 | esdp |= (IXGBE_ESDP_SDP0_DIR | |
137 | IXGBE_ESDP_SDP0_NATIVE); | 141 | IXGBE_ESDP_SDP0_NATIVE); |
138 | 142 | ||
139 | /* | 143 | /* |
140 | * enable the Clock Out feature on SDP0, and allow interrupts | 144 | * enable the Clock Out feature on SDP0, and allow |
141 | * to occur when the pin changes | 145 | * interrupts to occur when the pin changes |
142 | */ | 146 | */ |
143 | tsauxc = (IXGBE_TSAUXC_EN_CLK | | 147 | tsauxc = (IXGBE_TSAUXC_EN_CLK | |
144 | IXGBE_TSAUXC_SYNCLK | | 148 | IXGBE_TSAUXC_SYNCLK | |
@@ -171,25 +175,10 @@ static void ixgbe_ptp_enable_sdp(struct ixgbe_adapter *adapter) | |||
171 | 175 | ||
172 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | 176 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); |
173 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); | 177 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); |
174 | 178 | } else { | |
175 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC); | 179 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); |
176 | IXGBE_WRITE_FLUSH(hw); | ||
177 | break; | ||
178 | default: | ||
179 | break; | ||
180 | } | 180 | } |
181 | } | ||
182 | 181 | ||
183 | /** | ||
184 | * ixgbe_ptp_disable_sdp | ||
185 | * @hw: the private hardware structure | ||
186 | * | ||
187 | * this function disables the auxiliary SDP clock out feature | ||
188 | */ | ||
189 | static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw) | ||
190 | { | ||
191 | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC); | ||
192 | IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0); | ||
193 | IXGBE_WRITE_FLUSH(hw); | 182 | IXGBE_WRITE_FLUSH(hw); |
194 | } | 183 | } |
195 | 184 | ||
@@ -275,7 +264,6 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) | |||
275 | unsigned long flags; | 264 | unsigned long flags; |
276 | u64 now; | 265 | u64 now; |
277 | 266 | ||
278 | ixgbe_ptp_disable_sdp(&adapter->hw); | ||
279 | spin_lock_irqsave(&adapter->tmreg_lock, flags); | 267 | spin_lock_irqsave(&adapter->tmreg_lock, flags); |
280 | 268 | ||
281 | now = timecounter_read(&adapter->tc); | 269 | now = timecounter_read(&adapter->tc); |
@@ -287,7 +275,8 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) | |||
287 | now); | 275 | now); |
288 | 276 | ||
289 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | 277 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
290 | ixgbe_ptp_enable_sdp(adapter); | 278 | |
279 | ixgbe_ptp_setup_sdp(adapter); | ||
291 | 280 | ||
292 | return 0; | 281 | return 0; |
293 | } | 282 | } |
@@ -337,14 +326,12 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, | |||
337 | ns = ts->tv_sec * 1000000000ULL; | 326 | ns = ts->tv_sec * 1000000000ULL; |
338 | ns += ts->tv_nsec; | 327 | ns += ts->tv_nsec; |
339 | 328 | ||
340 | ixgbe_ptp_disable_sdp(&adapter->hw); | ||
341 | |||
342 | /* reset the timecounter */ | 329 | /* reset the timecounter */ |
343 | spin_lock_irqsave(&adapter->tmreg_lock, flags); | 330 | spin_lock_irqsave(&adapter->tmreg_lock, flags); |
344 | timecounter_init(&adapter->tc, &adapter->cc, ns); | 331 | timecounter_init(&adapter->tc, &adapter->cc, ns); |
345 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | 332 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
346 | 333 | ||
347 | ixgbe_ptp_enable_sdp(adapter); | 334 | ixgbe_ptp_setup_sdp(adapter); |
348 | return 0; | 335 | return 0; |
349 | } | 336 | } |
350 | 337 | ||
@@ -375,8 +362,9 @@ static int ixgbe_ptp_enable(struct ptp_clock_info *ptp, | |||
375 | if (on) | 362 | if (on) |
376 | adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED; | 363 | adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED; |
377 | else | 364 | else |
378 | adapter->flags2 &= | 365 | adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED; |
379 | ~IXGBE_FLAG2_PTP_PPS_ENABLED; | 366 | |
367 | ixgbe_ptp_setup_sdp(adapter); | ||
380 | return 0; | 368 | return 0; |
381 | default: | 369 | default: |
382 | break; | 370 | break; |
@@ -399,21 +387,12 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) | |||
399 | struct ixgbe_hw *hw = &adapter->hw; | 387 | struct ixgbe_hw *hw = &adapter->hw; |
400 | struct ptp_clock_event event; | 388 | struct ptp_clock_event event; |
401 | 389 | ||
402 | event.type = PTP_CLOCK_PPS; | 390 | switch (hw->mac.type) { |
403 | 391 | case ixgbe_mac_X540: | |
404 | /* Make sure ptp clock is valid, and PPS event enabled */ | 392 | ptp_clock_event(adapter->ptp_clock, &event); |
405 | if (!adapter->ptp_clock || | 393 | break; |
406 | !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) | 394 | default: |
407 | return; | 395 | break; |
408 | |||
409 | if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) { | ||
410 | switch (hw->mac.type) { | ||
411 | case ixgbe_mac_X540: | ||
412 | ptp_clock_event(adapter->ptp_clock, &event); | ||
413 | break; | ||
414 | default: | ||
415 | break; | ||
416 | } | ||
417 | } | 396 | } |
418 | } | 397 | } |
419 | 398 | ||
@@ -831,9 +810,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) | |||
831 | if (adapter->cycle_speed == cycle_speed && timinca) | 810 | if (adapter->cycle_speed == cycle_speed && timinca) |
832 | return; | 811 | return; |
833 | 812 | ||
834 | /* disable the SDP clock out */ | ||
835 | ixgbe_ptp_disable_sdp(hw); | ||
836 | |||
837 | /** | 813 | /** |
838 | * Scale the NIC cycle counter by a large factor so that | 814 | * Scale the NIC cycle counter by a large factor so that |
839 | * relatively small corrections to the frequency can be added | 815 | * relatively small corrections to the frequency can be added |
@@ -907,10 +883,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) | |||
907 | 883 | ||
908 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | 884 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
909 | 885 | ||
910 | /* Now that the shift has been calculated and the systime | 886 | /* |
887 | * Now that the shift has been calculated and the systime | ||
911 | * registers reset, (re-)enable the Clock out feature | 888 | * registers reset, (re-)enable the Clock out feature |
912 | */ | 889 | */ |
913 | ixgbe_ptp_enable_sdp(adapter); | 890 | ixgbe_ptp_setup_sdp(adapter); |
914 | } | 891 | } |
915 | 892 | ||
916 | /** | 893 | /** |
@@ -989,10 +966,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) | |||
989 | */ | 966 | */ |
990 | void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) | 967 | void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) |
991 | { | 968 | { |
992 | ixgbe_ptp_disable_sdp(&adapter->hw); | ||
993 | |||
994 | /* stop the overflow check task */ | 969 | /* stop the overflow check task */ |
995 | adapter->flags2 &= ~IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; | 970 | adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED | |
971 | IXGBE_FLAG2_PTP_PPS_ENABLED); | ||
972 | |||
973 | ixgbe_ptp_setup_sdp(adapter); | ||
996 | 974 | ||
997 | if (adapter->ptp_clock) { | 975 | if (adapter->ptp_clock) { |
998 | ptp_clock_unregister(adapter->ptp_clock); | 976 | ptp_clock_unregister(adapter->ptp_clock); |