.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /**************************************************************************** |
---|
2 | 3 | * Driver for Solarflare network controllers and boards |
---|
3 | 4 | * Copyright 2011-2013 Solarflare Communications Inc. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License version 2 as published |
---|
7 | | - * by the Free Software Foundation, incorporated herein by reference. |
---|
8 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | /* Theory of operation: |
---|
.. | .. |
---|
38 | 35 | #include <linux/time.h> |
---|
39 | 36 | #include <linux/ktime.h> |
---|
40 | 37 | #include <linux/module.h> |
---|
41 | | -#include <linux/net_tstamp.h> |
---|
42 | 38 | #include <linux/pps_kernel.h> |
---|
43 | 39 | #include <linux/ptp_clock_kernel.h> |
---|
44 | 40 | #include "net_driver.h" |
---|
.. | .. |
---|
47 | 43 | #include "mcdi_pcol.h" |
---|
48 | 44 | #include "io.h" |
---|
49 | 45 | #include "farch_regs.h" |
---|
50 | | -#include "nic.h" |
---|
| 46 | +#include "tx.h" |
---|
| 47 | +#include "nic.h" /* indirectly includes ptp.h */ |
---|
| 48 | +#include "efx_channels.h" |
---|
51 | 49 | |
---|
52 | 50 | /* Maximum number of events expected to make up a PTP event */ |
---|
53 | 51 | #define MAX_EVENT_FRAGS 3 |
---|
.. | .. |
---|
176 | 174 | |
---|
177 | 175 | /** |
---|
178 | 176 | * struct efx_ptp_event_rx - A PTP receive event (from MC) |
---|
| 177 | + * @link: list of events |
---|
179 | 178 | * @seq0: First part of (PTP) UUID |
---|
180 | 179 | * @seq1: Second part of (PTP) UUID and sequence number |
---|
181 | 180 | * @hwtimestamp: Event timestamp |
---|
| 181 | + * @expiry: Time which the packet arrived |
---|
182 | 182 | */ |
---|
183 | 183 | struct efx_ptp_event_rx { |
---|
184 | 184 | struct list_head link; |
---|
.. | .. |
---|
226 | 226 | * reset (disable, enable). |
---|
227 | 227 | * @rxfilter_event: Receive filter when operating |
---|
228 | 228 | * @rxfilter_general: Receive filter when operating |
---|
| 229 | + * @rxfilter_installed: Receive filter installed |
---|
229 | 230 | * @config: Current timestamp configuration |
---|
230 | 231 | * @enabled: PTP operation enabled |
---|
231 | 232 | * @mode: Mode in which PTP operating (PTP version) |
---|
232 | 233 | * @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time |
---|
233 | 234 | * @nic_to_kernel_time: Function to convert from NIC to kernel time |
---|
| 235 | + * @nic_time: contains time details |
---|
234 | 236 | * @nic_time.minor_max: Wrap point for NIC minor times |
---|
235 | 237 | * @nic_time.sync_event_diff_min: Minimum acceptable difference between time |
---|
236 | 238 | * in packet prefix and last MCDI time sync event i.e. how much earlier than |
---|
.. | .. |
---|
242 | 244 | * field in MCDI time sync event. |
---|
243 | 245 | * @min_synchronisation_ns: Minimum acceptable corrected sync window |
---|
244 | 246 | * @capabilities: Capabilities flags from the NIC |
---|
| 247 | + * @ts_corrections: contains corrections details |
---|
245 | 248 | * @ts_corrections.ptp_tx: Required driver correction of PTP packet transmit |
---|
246 | 249 | * timestamps |
---|
247 | 250 | * @ts_corrections.ptp_rx: Required driver correction of PTP packet receive |
---|
.. | .. |
---|
329 | 332 | struct work_struct pps_work; |
---|
330 | 333 | struct workqueue_struct *pps_workwq; |
---|
331 | 334 | bool nic_ts_enabled; |
---|
332 | | - _MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX); |
---|
| 335 | + efx_dword_t txbuf[MCDI_TX_BUF_LEN(MC_CMD_PTP_IN_TRANSMIT_LENMAX)]; |
---|
333 | 336 | |
---|
334 | 337 | unsigned int good_syncs; |
---|
335 | 338 | unsigned int fast_syncs; |
---|
.. | .. |
---|
355 | 358 | |
---|
356 | 359 | bool efx_ptp_use_mac_tx_timestamps(struct efx_nic *efx) |
---|
357 | 360 | { |
---|
358 | | - struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
359 | | - |
---|
360 | | - return ((efx_nic_rev(efx) >= EFX_REV_HUNT_A0) && |
---|
361 | | - (nic_data->datapath_caps2 & |
---|
362 | | - (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_MAC_TIMESTAMPING_LBN) |
---|
363 | | - )); |
---|
| 361 | + return efx_has_cap(efx, TX_MAC_TIMESTAMPING); |
---|
364 | 362 | } |
---|
365 | 363 | |
---|
366 | 364 | /* PTP 'extra' channel is still a traffic channel, but we only create TX queues |
---|
.. | .. |
---|
542 | 540 | struct efx_channel *efx_ptp_channel(struct efx_nic *efx) |
---|
543 | 541 | { |
---|
544 | 542 | return efx->ptp_data ? efx->ptp_data->channel : NULL; |
---|
| 543 | +} |
---|
| 544 | + |
---|
| 545 | +void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel) |
---|
| 546 | +{ |
---|
| 547 | + if (efx->ptp_data) |
---|
| 548 | + efx->ptp_data->channel = channel; |
---|
545 | 549 | } |
---|
546 | 550 | |
---|
547 | 551 | static u32 last_sync_timestamp_major(struct efx_nic *efx) |
---|
.. | .. |
---|
1091 | 1095 | static void efx_ptp_xmit_skb_queue(struct efx_nic *efx, struct sk_buff *skb) |
---|
1092 | 1096 | { |
---|
1093 | 1097 | struct efx_ptp_data *ptp_data = efx->ptp_data; |
---|
| 1098 | + u8 type = efx_tx_csum_type_skb(skb); |
---|
1094 | 1099 | struct efx_tx_queue *tx_queue; |
---|
1095 | | - u8 type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0; |
---|
1096 | 1100 | |
---|
1097 | | - tx_queue = &ptp_data->channel->tx_queue[type]; |
---|
| 1101 | + tx_queue = efx_channel_get_tx_queue(ptp_data->channel, type); |
---|
1098 | 1102 | if (tx_queue && tx_queue->timestamping) { |
---|
| 1103 | + /* This code invokes normal driver TX code which is always |
---|
| 1104 | + * protected from softirqs when called from generic TX code, |
---|
| 1105 | + * which in turn disables preemption. Look at __dev_queue_xmit |
---|
| 1106 | + * which uses rcu_read_lock_bh disabling preemption for RCU |
---|
| 1107 | + * plus disabling softirqs. We do not need RCU reader |
---|
| 1108 | + * protection here. |
---|
| 1109 | + * |
---|
| 1110 | + * Although it is theoretically safe for current PTP TX/RX code |
---|
| 1111 | + * running without disabling softirqs, there are three good |
---|
| 1112 | + * reasond for doing so: |
---|
| 1113 | + * |
---|
| 1114 | + * 1) The code invoked is mainly implemented for non-PTP |
---|
| 1115 | + * packets and it is always executed with softirqs |
---|
| 1116 | + * disabled. |
---|
| 1117 | + * 2) This being a single PTP packet, better to not |
---|
| 1118 | + * interrupt its processing by softirqs which can lead |
---|
| 1119 | + * to high latencies. |
---|
| 1120 | + * 3) netdev_xmit_more checks preemption is disabled and |
---|
| 1121 | + * triggers a BUG_ON if not. |
---|
| 1122 | + */ |
---|
| 1123 | + local_bh_disable(); |
---|
1099 | 1124 | efx_enqueue_skb(tx_queue, skb); |
---|
| 1125 | + local_bh_enable(); |
---|
1100 | 1126 | } else { |
---|
1101 | 1127 | WARN_ONCE(1, "PTP channel has no timestamped tx queue\n"); |
---|
1102 | 1128 | dev_kfree_skb_any(skb); |
---|
.. | .. |
---|
1163 | 1189 | |
---|
1164 | 1190 | /* Drop time-expired events */ |
---|
1165 | 1191 | spin_lock_bh(&ptp->evt_lock); |
---|
1166 | | - if (!list_empty(&ptp->evt_list)) { |
---|
1167 | | - list_for_each_safe(cursor, next, &ptp->evt_list) { |
---|
1168 | | - struct efx_ptp_event_rx *evt; |
---|
| 1192 | + list_for_each_safe(cursor, next, &ptp->evt_list) { |
---|
| 1193 | + struct efx_ptp_event_rx *evt; |
---|
1169 | 1194 | |
---|
1170 | | - evt = list_entry(cursor, struct efx_ptp_event_rx, |
---|
1171 | | - link); |
---|
1172 | | - if (time_after(jiffies, evt->expiry)) { |
---|
1173 | | - list_move(&evt->link, &ptp->evt_free_list); |
---|
1174 | | - netif_warn(efx, hw, efx->net_dev, |
---|
1175 | | - "PTP rx event dropped\n"); |
---|
1176 | | - } |
---|
| 1195 | + evt = list_entry(cursor, struct efx_ptp_event_rx, |
---|
| 1196 | + link); |
---|
| 1197 | + if (time_after(jiffies, evt->expiry)) { |
---|
| 1198 | + list_move(&evt->link, &ptp->evt_free_list); |
---|
| 1199 | + netif_warn(efx, hw, efx->net_dev, |
---|
| 1200 | + "PTP rx event dropped\n"); |
---|
1177 | 1201 | } |
---|
1178 | 1202 | } |
---|
1179 | 1203 | spin_unlock_bh(&ptp->evt_lock); |
---|
.. | .. |
---|
1447 | 1471 | struct efx_ptp_data *ptp; |
---|
1448 | 1472 | int rc = 0; |
---|
1449 | 1473 | unsigned int pos; |
---|
| 1474 | + |
---|
| 1475 | + if (efx->ptp_data) { |
---|
| 1476 | + efx->ptp_data->channel = channel; |
---|
| 1477 | + return 0; |
---|
| 1478 | + } |
---|
1450 | 1479 | |
---|
1451 | 1480 | ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL); |
---|
1452 | 1481 | efx->ptp_data = ptp; |
---|
.. | .. |
---|
2184 | 2213 | .pre_probe = efx_ptp_probe_channel, |
---|
2185 | 2214 | .post_remove = efx_ptp_remove_channel, |
---|
2186 | 2215 | .get_name = efx_ptp_get_channel_name, |
---|
2187 | | - /* no copy operation; there is no need to reallocate this channel */ |
---|
| 2216 | + .copy = efx_copy_channel, |
---|
2188 | 2217 | .receive_skb = efx_ptp_rx, |
---|
2189 | 2218 | .want_txqs = efx_ptp_want_txqs, |
---|
2190 | 2219 | .keep_eventq = false, |
---|