]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/ethernet/intel/igc/igc_ptp.c
UBUNTU: SAUCE: igc: fix page fault when thunderbolt is unplugged
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / ethernet / intel / igc / igc_ptp.c
CommitLineData
5f295805
VCG
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019 Intel Corporation */
3
4#include "igc.h"
5
6#include <linux/module.h>
7#include <linux/device.h>
8#include <linux/pci.h>
9#include <linux/ptp_classify.h>
10#include <linux/clocksource.h>
b03c49cd 11#include <linux/ktime.h>
5f295805
VCG
12
13#define INCVALUE_MASK 0x7fffffff
14#define ISGN 0x80000000
15
16#define IGC_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9)
17#define IGC_PTP_TX_TIMEOUT (HZ * 15)
18
19/* SYSTIM read access for I225 */
fec49eb4 20void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts)
5f295805
VCG
21{
22 struct igc_hw *hw = &adapter->hw;
23 u32 sec, nsec;
24
e5f020ad 25 /* The timestamp is latched when SYSTIML is read. */
5f295805
VCG
26 nsec = rd32(IGC_SYSTIML);
27 sec = rd32(IGC_SYSTIMH);
28
29 ts->tv_sec = sec;
30 ts->tv_nsec = nsec;
31}
32
33static void igc_ptp_write_i225(struct igc_adapter *adapter,
34 const struct timespec64 *ts)
35{
36 struct igc_hw *hw = &adapter->hw;
37
5f295805
VCG
38 wr32(IGC_SYSTIML, ts->tv_nsec);
39 wr32(IGC_SYSTIMH, ts->tv_sec);
40}
41
42static int igc_ptp_adjfine_i225(struct ptp_clock_info *ptp, long scaled_ppm)
43{
44 struct igc_adapter *igc = container_of(ptp, struct igc_adapter,
45 ptp_caps);
46 struct igc_hw *hw = &igc->hw;
47 int neg_adj = 0;
48 u64 rate;
49 u32 inca;
50
51 if (scaled_ppm < 0) {
52 neg_adj = 1;
53 scaled_ppm = -scaled_ppm;
54 }
55 rate = scaled_ppm;
56 rate <<= 14;
57 rate = div_u64(rate, 78125);
58
59 inca = rate & INCVALUE_MASK;
60 if (neg_adj)
61 inca |= ISGN;
62
63 wr32(IGC_TIMINCA, inca);
64
65 return 0;
66}
67
68static int igc_ptp_adjtime_i225(struct ptp_clock_info *ptp, s64 delta)
69{
70 struct igc_adapter *igc = container_of(ptp, struct igc_adapter,
71 ptp_caps);
72 struct timespec64 now, then = ns_to_timespec64(delta);
73 unsigned long flags;
74
75 spin_lock_irqsave(&igc->tmreg_lock, flags);
76
fec49eb4 77 igc_ptp_read(igc, &now);
5f295805
VCG
78 now = timespec64_add(now, then);
79 igc_ptp_write_i225(igc, (const struct timespec64 *)&now);
80
81 spin_unlock_irqrestore(&igc->tmreg_lock, flags);
82
83 return 0;
84}
85
86static int igc_ptp_gettimex64_i225(struct ptp_clock_info *ptp,
87 struct timespec64 *ts,
88 struct ptp_system_timestamp *sts)
89{
90 struct igc_adapter *igc = container_of(ptp, struct igc_adapter,
91 ptp_caps);
92 struct igc_hw *hw = &igc->hw;
93 unsigned long flags;
94
95 spin_lock_irqsave(&igc->tmreg_lock, flags);
96
97 ptp_read_system_prets(sts);
5f295805
VCG
98 ts->tv_nsec = rd32(IGC_SYSTIML);
99 ts->tv_sec = rd32(IGC_SYSTIMH);
e5f020ad 100 ptp_read_system_postts(sts);
5f295805
VCG
101
102 spin_unlock_irqrestore(&igc->tmreg_lock, flags);
103
104 return 0;
105}
106
107static int igc_ptp_settime_i225(struct ptp_clock_info *ptp,
108 const struct timespec64 *ts)
109{
110 struct igc_adapter *igc = container_of(ptp, struct igc_adapter,
111 ptp_caps);
112 unsigned long flags;
113
114 spin_lock_irqsave(&igc->tmreg_lock, flags);
115
116 igc_ptp_write_i225(igc, ts);
117
118 spin_unlock_irqrestore(&igc->tmreg_lock, flags);
119
120 return 0;
121}
122
123static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
124 struct ptp_clock_request *rq, int on)
125{
126 return -EOPNOTSUPP;
127}
128
81b05520
VCG
129/**
130 * igc_ptp_systim_to_hwtstamp - convert system time value to HW timestamp
131 * @adapter: board private structure
132 * @hwtstamps: timestamp structure to update
133 * @systim: unsigned 64bit system time value
134 *
135 * We need to convert the system time value stored in the RX/TXSTMP registers
136 * into a hwtstamp which can be used by the upper level timestamping functions.
137 **/
138static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
139 struct skb_shared_hwtstamps *hwtstamps,
140 u64 systim)
141{
142 switch (adapter->hw.mac.type) {
143 case igc_i225:
144 memset(hwtstamps, 0, sizeof(*hwtstamps));
145 /* Upper 32 bits contain s, lower 32 bits contain ns. */
146 hwtstamps->hwtstamp = ktime_set(systim >> 32,
147 systim & 0xFFFFFFFF);
148 break;
149 default:
150 break;
151 }
152}
153
154/**
575e1917 155 * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer
81b05520
VCG
156 * @q_vector: Pointer to interrupt specific structure
157 * @va: Pointer to address containing Rx buffer
158 * @skb: Buffer containing timestamp and packet
159 *
575e1917
AG
160 * This function retrieves the timestamp saved in the beginning of packet
161 * buffer. While two timestamps are available, one in timer0 reference and the
162 * other in timer1 reference, this function considers only the timestamp in
163 * timer0 reference.
164 */
165void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
81b05520
VCG
166 struct sk_buff *skb)
167{
168 struct igc_adapter *adapter = q_vector->adapter;
575e1917
AG
169 u64 regval;
170 int adjust;
171
172 /* Timestamps are saved in little endian at the beginning of the packet
173 * buffer following the layout:
174 *
175 * DWORD: | 0 | 1 | 2 | 3 |
176 * Field: | Timer1 SYSTIML | Timer1 SYSTIMH | Timer0 SYSTIML | Timer0 SYSTIMH |
177 *
178 * SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds
179 * part of the timestamp.
81b05520 180 */
575e1917
AG
181 regval = le32_to_cpu(va[2]);
182 regval |= (u64)le32_to_cpu(va[3]) << 32;
183 igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
184
185 /* Adjust timestamp for the RX latency based on link speed */
186 switch (adapter->link_speed) {
187 case SPEED_10:
188 adjust = IGC_I225_RX_LATENCY_10;
189 break;
190 case SPEED_100:
191 adjust = IGC_I225_RX_LATENCY_100;
192 break;
193 case SPEED_1000:
194 adjust = IGC_I225_RX_LATENCY_1000;
195 break;
196 case SPEED_2500:
197 adjust = IGC_I225_RX_LATENCY_2500;
198 break;
199 default:
200 adjust = 0;
201 netdev_warn_once(adapter->netdev, "Imprecise timestamp\n");
202 break;
81b05520
VCG
203 }
204 skb_hwtstamps(skb)->hwtstamp =
205 ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust);
206}
207
3df7fd79
AG
208static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter)
209{
210 struct igc_hw *hw = &adapter->hw;
211 u32 val;
1cbedabf 212 int i;
3df7fd79
AG
213
214 wr32(IGC_TSYNCRXCTL, 0);
215
1cbedabf
AG
216 for (i = 0; i < adapter->num_rx_queues; i++) {
217 val = rd32(IGC_SRRCTL(i));
218 val &= ~IGC_SRRCTL_TIMESTAMP;
219 wr32(IGC_SRRCTL(i), val);
220 }
221
3df7fd79
AG
222 val = rd32(IGC_RXPBS);
223 val &= ~IGC_RXPBS_CFG_TS_EN;
224 wr32(IGC_RXPBS, val);
225}
226
227static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
228{
229 struct igc_hw *hw = &adapter->hw;
230 u32 val;
1cbedabf 231 int i;
3df7fd79
AG
232
233 val = rd32(IGC_RXPBS);
234 val |= IGC_RXPBS_CFG_TS_EN;
235 wr32(IGC_RXPBS, val);
236
1cbedabf
AG
237 for (i = 0; i < adapter->num_rx_queues; i++) {
238 val = rd32(IGC_SRRCTL(i));
239 /* FIXME: For now, only support retrieving RX timestamps from
240 * timer 0.
241 */
242 val |= IGC_SRRCTL_TIMER1SEL(0) | IGC_SRRCTL_TIMER0SEL(0) |
243 IGC_SRRCTL_TIMESTAMP;
244 wr32(IGC_SRRCTL(i), val);
245 }
3df7fd79
AG
246
247 val = IGC_TSYNCRXCTL_ENABLED | IGC_TSYNCRXCTL_TYPE_ALL |
248 IGC_TSYNCRXCTL_RXSYNSIG;
249 wr32(IGC_TSYNCRXCTL, val);
250}
251
252static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
253{
254 struct igc_hw *hw = &adapter->hw;
255
256 wr32(IGC_TSYNCTXCTL, 0);
257}
258
259static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter)
260{
261 struct igc_hw *hw = &adapter->hw;
262
263 wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG);
264
265 /* Read TXSTMP registers to discard any timestamp previously stored. */
266 rd32(IGC_TXSTMPL);
267 rd32(IGC_TXSTMPH);
268}
269
81b05520
VCG
270/**
271 * igc_ptp_set_timestamp_mode - setup hardware for timestamping
272 * @adapter: networking device structure
273 * @config: hwtstamp configuration
274 *
3b44d4c1 275 * Return: 0 in case of success, negative errno code otherwise.
81b05520 276 */
5f295805
VCG
277static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
278 struct hwtstamp_config *config)
279{
81b05520
VCG
280 /* reserved for future extensions */
281 if (config->flags)
282 return -EINVAL;
283
2c344ae2
VCG
284 switch (config->tx_type) {
285 case HWTSTAMP_TX_OFF:
3df7fd79
AG
286 igc_ptp_disable_tx_timestamp(adapter);
287 break;
2c344ae2 288 case HWTSTAMP_TX_ON:
3df7fd79 289 igc_ptp_enable_tx_timestamp(adapter);
2c344ae2
VCG
290 break;
291 default:
292 return -ERANGE;
293 }
294
81b05520
VCG
295 switch (config->rx_filter) {
296 case HWTSTAMP_FILTER_NONE:
3df7fd79 297 igc_ptp_disable_rx_timestamp(adapter);
81b05520
VCG
298 break;
299 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
81b05520 300 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
81b05520
VCG
301 case HWTSTAMP_FILTER_PTP_V2_EVENT:
302 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
303 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
304 case HWTSTAMP_FILTER_PTP_V2_SYNC:
305 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
306 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
307 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
308 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
309 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
81b05520
VCG
310 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
311 case HWTSTAMP_FILTER_NTP_ALL:
312 case HWTSTAMP_FILTER_ALL:
3df7fd79 313 igc_ptp_enable_rx_timestamp(adapter);
81b05520
VCG
314 config->rx_filter = HWTSTAMP_FILTER_ALL;
315 break;
81b05520 316 default:
81b05520
VCG
317 return -ERANGE;
318 }
319
5f295805
VCG
320 return 0;
321}
322
29b821fe
AG
323static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
324{
325 struct igc_hw *hw = &adapter->hw;
326
327 dev_kfree_skb_any(adapter->ptp_tx_skb);
328 adapter->ptp_tx_skb = NULL;
329 adapter->tx_hwtstamp_timeouts++;
330 clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
331 /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
332 rd32(IGC_TXSTMPH);
333 netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
334}
335
5f295805
VCG
336void igc_ptp_tx_hang(struct igc_adapter *adapter)
337{
338 bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
339 IGC_PTP_TX_TIMEOUT);
5f295805 340
5f295805
VCG
341 if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
342 return;
343
344 /* If we haven't received a timestamp within the timeout, it is
345 * reasonable to assume that it will never occur, so we can unlock the
346 * timestamp bit when this occurs.
347 */
348 if (timeout) {
349 cancel_work_sync(&adapter->ptp_tx_work);
29b821fe 350 igc_ptp_tx_timeout(adapter);
5f295805
VCG
351 }
352}
353
2c344ae2
VCG
354/**
355 * igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp
356 * @adapter: Board private structure
357 *
358 * If we were asked to do hardware stamping and such a time stamp is
359 * available, then it must have been for this skb here because we only
360 * allow only one such packet into the queue.
361 */
362static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
363{
364 struct sk_buff *skb = adapter->ptp_tx_skb;
365 struct skb_shared_hwtstamps shhwtstamps;
366 struct igc_hw *hw = &adapter->hw;
4406e977 367 int adjust = 0;
2c344ae2
VCG
368 u64 regval;
369
1801f8d9
AG
370 if (WARN_ON_ONCE(!skb))
371 return;
372
2c344ae2
VCG
373 regval = rd32(IGC_TXSTMPL);
374 regval |= (u64)rd32(IGC_TXSTMPH) << 32;
375 igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
376
4406e977
VCG
377 switch (adapter->link_speed) {
378 case SPEED_10:
379 adjust = IGC_I225_TX_LATENCY_10;
380 break;
381 case SPEED_100:
382 adjust = IGC_I225_TX_LATENCY_100;
383 break;
384 case SPEED_1000:
385 adjust = IGC_I225_TX_LATENCY_1000;
386 break;
387 case SPEED_2500:
388 adjust = IGC_I225_TX_LATENCY_2500;
389 break;
390 }
391
392 shhwtstamps.hwtstamp =
393 ktime_add_ns(shhwtstamps.hwtstamp, adjust);
394
2c344ae2
VCG
395 /* Clear the lock early before calling skb_tstamp_tx so that
396 * applications are not woken up before the lock bit is clear. We use
397 * a copy of the skb pointer to ensure other threads can't change it
398 * while we're notifying the stack.
399 */
400 adapter->ptp_tx_skb = NULL;
401 clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
402
403 /* Notify the stack and free the skb after we've unlocked */
404 skb_tstamp_tx(skb, &shhwtstamps);
405 dev_kfree_skb_any(skb);
406}
407
408/**
409 * igc_ptp_tx_work
410 * @work: pointer to work struct
411 *
412 * This work function polls the TSYNCTXCTL valid bit to determine when a
413 * timestamp has been taken for the current stored skb.
414 */
38db952b 415static void igc_ptp_tx_work(struct work_struct *work)
5f295805 416{
2c344ae2
VCG
417 struct igc_adapter *adapter = container_of(work, struct igc_adapter,
418 ptp_tx_work);
419 struct igc_hw *hw = &adapter->hw;
420 u32 tsynctxctl;
421
1801f8d9 422 if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
2c344ae2
VCG
423 return;
424
2c344ae2 425 tsynctxctl = rd32(IGC_TSYNCTXCTL);
530a763d
AG
426 if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
427 return;
428
429 igc_ptp_tx_hwtstamp(adapter);
5f295805
VCG
430}
431
432/**
433 * igc_ptp_set_ts_config - set hardware time stamping config
434 * @netdev: network interface device structure
b50f7bca 435 * @ifr: interface request data
5f295805
VCG
436 *
437 **/
438int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr)
439{
440 struct igc_adapter *adapter = netdev_priv(netdev);
441 struct hwtstamp_config config;
442 int err;
443
444 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
445 return -EFAULT;
446
447 err = igc_ptp_set_timestamp_mode(adapter, &config);
448 if (err)
449 return err;
450
451 /* save these settings for future reference */
452 memcpy(&adapter->tstamp_config, &config,
453 sizeof(adapter->tstamp_config));
454
455 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
456 -EFAULT : 0;
457}
458
459/**
460 * igc_ptp_get_ts_config - get hardware time stamping config
461 * @netdev: network interface device structure
b50f7bca 462 * @ifr: interface request data
5f295805
VCG
463 *
464 * Get the hwtstamp_config settings to return to the user. Rather than attempt
465 * to deconstruct the settings from the registers, just return a shadow copy
466 * of the last known settings.
467 **/
468int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
469{
470 struct igc_adapter *adapter = netdev_priv(netdev);
471 struct hwtstamp_config *config = &adapter->tstamp_config;
472
473 return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
474 -EFAULT : 0;
475}
476
477/**
478 * igc_ptp_init - Initialize PTP functionality
479 * @adapter: Board private structure
480 *
481 * This function is called at device probe to initialize the PTP
482 * functionality.
483 */
484void igc_ptp_init(struct igc_adapter *adapter)
485{
486 struct net_device *netdev = adapter->netdev;
487 struct igc_hw *hw = &adapter->hw;
488
489 switch (hw->mac.type) {
490 case igc_i225:
491 snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
492 adapter->ptp_caps.owner = THIS_MODULE;
493 adapter->ptp_caps.max_adj = 62499999;
494 adapter->ptp_caps.adjfine = igc_ptp_adjfine_i225;
495 adapter->ptp_caps.adjtime = igc_ptp_adjtime_i225;
496 adapter->ptp_caps.gettimex64 = igc_ptp_gettimex64_i225;
497 adapter->ptp_caps.settime64 = igc_ptp_settime_i225;
498 adapter->ptp_caps.enable = igc_ptp_feature_enable_i225;
499 break;
500 default:
501 adapter->ptp_clock = NULL;
502 return;
503 }
504
505 spin_lock_init(&adapter->tmreg_lock);
506 INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
507
508 adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
509 adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
510
b03c49cd
VCG
511 adapter->prev_ptp_time = ktime_to_timespec64(ktime_get_real());
512 adapter->ptp_reset_start = ktime_get();
513
5f295805
VCG
514 adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
515 &adapter->pdev->dev);
516 if (IS_ERR(adapter->ptp_clock)) {
517 adapter->ptp_clock = NULL;
916a3c65 518 netdev_err(netdev, "ptp_clock_register failed\n");
5f295805 519 } else if (adapter->ptp_clock) {
916a3c65 520 netdev_info(netdev, "PHC added\n");
5f295805
VCG
521 adapter->ptp_flags |= IGC_PTP_ENABLED;
522 }
523}
524
b03c49cd
VCG
525static void igc_ptp_time_save(struct igc_adapter *adapter)
526{
fec49eb4 527 igc_ptp_read(adapter, &adapter->prev_ptp_time);
b03c49cd
VCG
528 adapter->ptp_reset_start = ktime_get();
529}
530
531static void igc_ptp_time_restore(struct igc_adapter *adapter)
532{
533 struct timespec64 ts = adapter->prev_ptp_time;
534 ktime_t delta;
535
536 delta = ktime_sub(ktime_get(), adapter->ptp_reset_start);
537
538 timespec64_add_ns(&ts, ktime_to_ns(delta));
539
540 igc_ptp_write_i225(adapter, &ts);
541}
542
5f295805
VCG
543/**
544 * igc_ptp_suspend - Disable PTP work items and prepare for suspend
545 * @adapter: Board private structure
546 *
547 * This function stops the overflow check work and PTP Tx timestamp work, and
548 * will prepare the device for OS suspend.
549 */
a5136f76 550void igc_ptp_suspend(struct igc_adapter *adapter)
5f295805
VCG
551{
552 if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
553 return;
554
555 cancel_work_sync(&adapter->ptp_tx_work);
1801f8d9
AG
556 dev_kfree_skb_any(adapter->ptp_tx_skb);
557 adapter->ptp_tx_skb = NULL;
558 clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
b03c49cd 559
1f1bd65c
AM
560 if (pci_device_is_present(adapter->pdev))
561 igc_ptp_time_save(adapter);
5f295805
VCG
562}
563
564/**
565 * igc_ptp_stop - Disable PTP device and stop the overflow check.
566 * @adapter: Board private structure.
567 *
568 * This function stops the PTP support and cancels the delayed work.
569 **/
570void igc_ptp_stop(struct igc_adapter *adapter)
571{
572 igc_ptp_suspend(adapter);
573
574 if (adapter->ptp_clock) {
575 ptp_clock_unregister(adapter->ptp_clock);
916a3c65 576 netdev_info(adapter->netdev, "PHC removed\n");
5f295805
VCG
577 adapter->ptp_flags &= ~IGC_PTP_ENABLED;
578 }
579}
580
581/**
582 * igc_ptp_reset - Re-enable the adapter for PTP following a reset.
583 * @adapter: Board private structure.
584 *
585 * This function handles the reset work required to re-enable the PTP device.
586 **/
587void igc_ptp_reset(struct igc_adapter *adapter)
588{
589 struct igc_hw *hw = &adapter->hw;
590 unsigned long flags;
591
592 /* reset the tstamp_config */
593 igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config);
594
595 spin_lock_irqsave(&adapter->tmreg_lock, flags);
596
597 switch (adapter->hw.mac.type) {
598 case igc_i225:
599 wr32(IGC_TSAUXC, 0x0);
600 wr32(IGC_TSSDP, 0x0);
601 wr32(IGC_TSIM, IGC_TSICR_INTERRUPTS);
602 wr32(IGC_IMS, IGC_IMS_TS);
603 break;
604 default:
605 /* No work to do. */
606 goto out;
607 }
608
609 /* Re-initialize the timer. */
610 if (hw->mac.type == igc_i225) {
b03c49cd 611 igc_ptp_time_restore(adapter);
5f295805
VCG
612 } else {
613 timecounter_init(&adapter->tc, &adapter->cc,
614 ktime_to_ns(ktime_get_real()));
615 }
616out:
617 spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
618
619 wrfl();
620}