1 /* Intel Ethernet Switch Host Interface Driver
2 * Copyright(c) 2013 - 2015 Intel Corporation.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * The full GNU General Public License is included in this distribution in
14 * the file called "COPYING".
16 * Contact Information:
17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
21 #include <linux/ptp_classify.h>
22 #include <linux/ptp_clock_kernel.h>
26 #define FM10K_TS_TX_TIMEOUT (HZ * 15)
28 void fm10k_systime_to_hwtstamp(struct fm10k_intfc
*interface
,
29 struct skb_shared_hwtstamps
*hwtstamp
,
34 read_lock_irqsave(&interface
->systime_lock
, flags
);
35 systime
+= interface
->ptp_adjust
;
36 read_unlock_irqrestore(&interface
->systime_lock
, flags
);
38 hwtstamp
->hwtstamp
= ns_to_ktime(systime
);
41 static struct sk_buff
*fm10k_ts_tx_skb(struct fm10k_intfc
*interface
,
44 struct sk_buff_head
*list
= &interface
->ts_tx_skb_queue
;
47 skb_queue_walk(list
, skb
) {
48 if (FM10K_CB(skb
)->fi
.w
.dglort
== dglort
)
55 void fm10k_ts_tx_enqueue(struct fm10k_intfc
*interface
, struct sk_buff
*skb
)
57 struct sk_buff_head
*list
= &interface
->ts_tx_skb_queue
;
58 struct sk_buff
*clone
;
61 /* create clone for us to return on the Tx path */
62 clone
= skb_clone_sk(skb
);
66 FM10K_CB(clone
)->ts_tx_timeout
= jiffies
+ FM10K_TS_TX_TIMEOUT
;
67 spin_lock_irqsave(&list
->lock
, flags
);
69 /* attempt to locate any buffers with the same dglort,
70 * if none are present then insert skb in tail of list
72 skb
= fm10k_ts_tx_skb(interface
, FM10K_CB(clone
)->fi
.w
.dglort
);
74 skb_shinfo(clone
)->tx_flags
|= SKBTX_IN_PROGRESS
;
75 __skb_queue_tail(list
, clone
);
78 spin_unlock_irqrestore(&list
->lock
, flags
);
80 /* if list is already has one then we just free the clone */
85 void fm10k_ts_tx_hwtstamp(struct fm10k_intfc
*interface
, __le16 dglort
,
88 struct skb_shared_hwtstamps shhwtstamps
;
89 struct sk_buff_head
*list
= &interface
->ts_tx_skb_queue
;
93 spin_lock_irqsave(&list
->lock
, flags
);
95 /* attempt to locate and pull the sk_buff out of the list */
96 skb
= fm10k_ts_tx_skb(interface
, dglort
);
98 __skb_unlink(skb
, list
);
100 spin_unlock_irqrestore(&list
->lock
, flags
);
102 /* if not found do nothing */
106 /* timestamp the sk_buff and free out copy */
107 fm10k_systime_to_hwtstamp(interface
, &shhwtstamps
, systime
);
108 skb_tstamp_tx(skb
, &shhwtstamps
);
109 dev_kfree_skb_any(skb
);
112 void fm10k_ts_tx_subtask(struct fm10k_intfc
*interface
)
114 struct sk_buff_head
*list
= &interface
->ts_tx_skb_queue
;
115 struct sk_buff
*skb
, *tmp
;
118 /* If we're down or resetting, just bail */
119 if (test_bit(__FM10K_DOWN
, &interface
->state
) ||
120 test_bit(__FM10K_RESETTING
, &interface
->state
))
123 spin_lock_irqsave(&list
->lock
, flags
);
125 /* walk though the list and flush any expired timestamp packets */
126 skb_queue_walk_safe(list
, skb
, tmp
) {
127 if (!time_is_after_jiffies(FM10K_CB(skb
)->ts_tx_timeout
))
129 __skb_unlink(skb
, list
);
131 interface
->tx_hwtstamp_timeouts
++;
134 spin_unlock_irqrestore(&list
->lock
, flags
);
137 static u64
fm10k_systime_read(struct fm10k_intfc
*interface
)
139 struct fm10k_hw
*hw
= &interface
->hw
;
141 return hw
->mac
.ops
.read_systime(hw
);
144 void fm10k_ts_reset(struct fm10k_intfc
*interface
)
146 s64 ns
= ktime_to_ns(ktime_get_real());
149 /* reinitialize the clock */
150 write_lock_irqsave(&interface
->systime_lock
, flags
);
151 interface
->ptp_adjust
= fm10k_systime_read(interface
) - ns
;
152 write_unlock_irqrestore(&interface
->systime_lock
, flags
);
155 void fm10k_ts_init(struct fm10k_intfc
*interface
)
157 /* Initialize lock protecting systime access */
158 rwlock_init(&interface
->systime_lock
);
160 /* Initialize skb queue for pending timestamp requests */
161 skb_queue_head_init(&interface
->ts_tx_skb_queue
);
163 /* reset the clock to current kernel time */
164 fm10k_ts_reset(interface
);
168 * fm10k_get_ts_config - get current hardware timestamping configuration
169 * @netdev: network interface device structure
172 * This function returns the current timestamping settings. Rather than
173 * attempt to deconstruct registers to fill in the values, simply keep a copy
174 * of the old settings around, and return a copy when requested.
176 int fm10k_get_ts_config(struct net_device
*netdev
, struct ifreq
*ifr
)
178 struct fm10k_intfc
*interface
= netdev_priv(netdev
);
179 struct hwtstamp_config
*config
= &interface
->ts_config
;
181 return copy_to_user(ifr
->ifr_data
, config
, sizeof(*config
)) ?
186 * fm10k_set_ts_config - control hardware time stamping
187 * @netdev: network interface device structure
190 * Outgoing time stamping can be enabled and disabled. Play nice and
191 * disable it when requested, although it shouldn't cause any overhead
192 * when no packet needs it. At most one packet in the queue may be
193 * marked for time stamping, otherwise it would be impossible to tell
194 * for sure to which packet the hardware time stamp belongs.
196 * Incoming time stamping has to be configured via the hardware
197 * filters. Not all combinations are supported, in particular event
198 * type has to be specified. Matching the kind of event packet is
199 * not supported, with the exception of "all V2 events regardless of
202 * Since hardware always timestamps Path delay packets when timestamping V2
203 * packets, regardless of the type specified in the register, only use V2
204 * Event mode. This more accurately tells the user what the hardware is going
207 int fm10k_set_ts_config(struct net_device
*netdev
, struct ifreq
*ifr
)
209 struct fm10k_intfc
*interface
= netdev_priv(netdev
);
210 struct hwtstamp_config ts_config
;
212 if (copy_from_user(&ts_config
, ifr
->ifr_data
, sizeof(ts_config
)))
215 /* reserved for future extensions */
219 switch (ts_config
.tx_type
) {
220 case HWTSTAMP_TX_OFF
:
223 /* we likely need some check here to see if this is supported */
229 switch (ts_config
.rx_filter
) {
230 case HWTSTAMP_FILTER_NONE
:
231 interface
->flags
&= ~FM10K_FLAG_RX_TS_ENABLED
;
233 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT
:
234 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC
:
235 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ
:
236 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT
:
237 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC
:
238 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ
:
239 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT
:
240 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC
:
241 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ
:
242 case HWTSTAMP_FILTER_PTP_V2_EVENT
:
243 case HWTSTAMP_FILTER_PTP_V2_SYNC
:
244 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ
:
245 case HWTSTAMP_FILTER_ALL
:
246 interface
->flags
|= FM10K_FLAG_RX_TS_ENABLED
;
247 ts_config
.rx_filter
= HWTSTAMP_FILTER_ALL
;
253 /* save these settings for future reference */
254 interface
->ts_config
= ts_config
;
256 return copy_to_user(ifr
->ifr_data
, &ts_config
, sizeof(ts_config
)) ?
260 static int fm10k_ptp_adjfreq(struct ptp_clock_info
*ptp
, s32 ppb
)
262 struct fm10k_intfc
*interface
;
266 interface
= container_of(ptp
, struct fm10k_intfc
, ptp_caps
);
269 err
= hw
->mac
.ops
.adjust_systime(hw
, ppb
);
271 /* the only error we should see is if the value is out of range */
272 return (err
== FM10K_ERR_PARAM
) ? -ERANGE
: err
;
275 static int fm10k_ptp_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
277 struct fm10k_intfc
*interface
;
280 interface
= container_of(ptp
, struct fm10k_intfc
, ptp_caps
);
282 write_lock_irqsave(&interface
->systime_lock
, flags
);
283 interface
->ptp_adjust
+= delta
;
284 write_unlock_irqrestore(&interface
->systime_lock
, flags
);
289 static int fm10k_ptp_gettime(struct ptp_clock_info
*ptp
, struct timespec64
*ts
)
291 struct fm10k_intfc
*interface
;
295 interface
= container_of(ptp
, struct fm10k_intfc
, ptp_caps
);
297 read_lock_irqsave(&interface
->systime_lock
, flags
);
298 now
= fm10k_systime_read(interface
) + interface
->ptp_adjust
;
299 read_unlock_irqrestore(&interface
->systime_lock
, flags
);
301 *ts
= ns_to_timespec64(now
);
306 static int fm10k_ptp_settime(struct ptp_clock_info
*ptp
,
307 const struct timespec64
*ts
)
309 struct fm10k_intfc
*interface
;
311 u64 ns
= timespec64_to_ns(ts
);
313 interface
= container_of(ptp
, struct fm10k_intfc
, ptp_caps
);
315 write_lock_irqsave(&interface
->systime_lock
, flags
);
316 interface
->ptp_adjust
= fm10k_systime_read(interface
) - ns
;
317 write_unlock_irqrestore(&interface
->systime_lock
, flags
);
322 static int fm10k_ptp_enable(struct ptp_clock_info
*ptp
,
323 struct ptp_clock_request
*rq
,
324 int __always_unused on
)
326 struct ptp_clock_time
*t
= &rq
->perout
.period
;
327 struct fm10k_intfc
*interface
;
332 /* we can only support periodic output */
333 if (rq
->type
!= PTP_CLK_REQ_PEROUT
)
336 /* verify the requested channel is there */
337 if (rq
->perout
.index
>= ptp
->n_per_out
)
340 /* we cannot enforce start time as there is no
341 * mechanism for that in the hardware, we can only control
345 /* we cannot support periods greater than 4 seconds due to reg limit */
346 if (t
->sec
> 4 || t
->sec
< 0)
349 interface
= container_of(ptp
, struct fm10k_intfc
, ptp_caps
);
352 /* we simply cannot support the operation if we don't have BAR4 */
356 /* convert to unsigned 64b ns, verify we can put it in a 32b register */
357 period
= t
->sec
* 1000000000LL + t
->nsec
;
359 /* determine the minimum size for period */
360 step
= 2 * (fm10k_read_reg(hw
, FM10K_SYSTIME_CFG
) &
361 FM10K_SYSTIME_CFG_STEP_MASK
);
363 /* verify the value is in range supported by hardware */
364 if ((period
&& (period
< step
)) || (period
> U32_MAX
))
367 /* notify hardware of request to being sending pulses */
368 fm10k_write_sw_reg(hw
, FM10K_SW_SYSTIME_PULSE(rq
->perout
.index
),
374 static struct ptp_pin_desc fm10k_ptp_pd
[2] = {
376 .name
= "IEEE1588_PULSE0",
378 .func
= PTP_PF_PEROUT
,
382 .name
= "IEEE1588_PULSE1",
384 .func
= PTP_PF_PEROUT
,
389 static int fm10k_ptp_verify(struct ptp_clock_info
*ptp
, unsigned int pin
,
390 enum ptp_pin_function func
, unsigned int chan
)
392 /* verify the requested pin is there */
393 if (pin
>= ptp
->n_pins
|| !ptp
->pin_config
)
396 /* enforce locked channels, no changing them */
397 if (chan
!= ptp
->pin_config
[pin
].chan
)
400 /* we want to keep the functions locked as well */
401 if (func
!= ptp
->pin_config
[pin
].func
)
407 void fm10k_ptp_register(struct fm10k_intfc
*interface
)
409 struct ptp_clock_info
*ptp_caps
= &interface
->ptp_caps
;
410 struct device
*dev
= &interface
->pdev
->dev
;
411 struct ptp_clock
*ptp_clock
;
413 snprintf(ptp_caps
->name
, sizeof(ptp_caps
->name
),
414 "%s", interface
->netdev
->name
);
415 ptp_caps
->owner
= THIS_MODULE
;
416 /* This math is simply the inverse of the math in
417 * fm10k_adjust_systime_pf applied to an adjustment value
418 * of 2^30 - 1 which is the maximum value of the register:
419 * max_ppb == ((2^30 - 1) * 5^9) / 2^31
421 ptp_caps
->max_adj
= 976562;
422 ptp_caps
->adjfreq
= fm10k_ptp_adjfreq
;
423 ptp_caps
->adjtime
= fm10k_ptp_adjtime
;
424 ptp_caps
->gettime64
= fm10k_ptp_gettime
;
425 ptp_caps
->settime64
= fm10k_ptp_settime
;
427 /* provide pins if BAR4 is accessible */
428 if (interface
->sw_addr
) {
429 /* enable periodic outputs */
430 ptp_caps
->n_per_out
= 2;
431 ptp_caps
->enable
= fm10k_ptp_enable
;
433 /* enable clock pins */
434 ptp_caps
->verify
= fm10k_ptp_verify
;
435 ptp_caps
->n_pins
= 2;
436 ptp_caps
->pin_config
= fm10k_ptp_pd
;
439 ptp_clock
= ptp_clock_register(ptp_caps
, dev
);
440 if (IS_ERR(ptp_clock
)) {
442 dev_err(dev
, "ptp_clock_register failed\n");
444 dev_info(dev
, "registered PHC device %s\n", ptp_caps
->name
);
447 interface
->ptp_clock
= ptp_clock
;
450 void fm10k_ptp_unregister(struct fm10k_intfc
*interface
)
452 struct ptp_clock
*ptp_clock
= interface
->ptp_clock
;
453 struct device
*dev
= &interface
->pdev
->dev
;
458 interface
->ptp_clock
= NULL
;
460 ptp_clock_unregister(ptp_clock
);
461 dev_info(dev
, "removed PHC %s\n", interface
->ptp_caps
.name
);