Lines Matching +full:no +full:- +full:sync +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2011-2013 Solarflare Communications Inc.
143 #define MC_NANOSECOND_MASK ((1 << MC_NANOSECOND_BITS) - 1)
144 #define MC_SECOND_MASK ((1 << (32 - MC_NANOSECOND_BITS)) - 1)
146 /* Maximum parts-per-billion adjustment that is acceptable */
161 * struct efx_ptp_match - Matching structure, stored in sk_buff's cb area.
165 * @state: The state of the packet - whether it is ready for processing or
166 * whether that is of no interest.
175 * struct efx_ptp_event_rx - A PTP receive event (from MC)
191 * struct efx_ptp_timeset - Synchronisation between host and MC
207 u32 window; /* Derived: end - start, allowing for wrap */
211 * struct efx_ptp_data - Precision Time Protocol (PTP) state
231 * @mode: Mode in which PTP operating (PTP version)
237 * in packet prefix and last MCDI time sync event i.e. how much earlier than
238 * the last sync event time a packet timestamp can be.
240 * in packet prefix and last MCDI time sync event i.e. how much later than
241 * the last sync event time a packet timestamp can be.
243 * field in MCDI time sync event.
244 * @min_synchronisation_ns: Minimum acceptable corrected sync window
262 * @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
276 * @no_time_syncs: Number of synchronisations with no good times.
277 * @invalid_sync_windows: Number of sync windows with bad durations.
278 * @undersize_sync_windows: Number of corrected sync windows that are too small
279 * @oversize_sync_windows: Number of corrected sync windows that are too large
302 unsigned int mode; member
368 return efx_siena_ptp_use_mac_tx_timestamps(channel->efx); in efx_ptp_want_txqs()
393 [0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL,
398 if (!efx->ptp_data) in efx_siena_ptp_describe_stats()
412 if (!efx->ptp_data) in efx_siena_ptp_update_stats()
419 stats[i] = *(unsigned int *)((char *)efx->ptp_data + in efx_siena_ptp_update_stats()
455 kt = ktime_sub_ns(kt, (u64)-correction); in efx_ptp_s_ns_to_ktime_correction()
465 #define NS_TO_S27_SHIFT (63 - S27_TO_NS_SHIFT)
469 * where the minor register only uses 27 bits in units of 2^-27s.
476 (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); in efx_ptp_ns_to_s27()
482 min -= S27_MINOR_MAX; in efx_ptp_ns_to_s27()
493 (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); in efx_ptp_s27_to_ktime()
504 nic_major--; in efx_ptp_s27_to_ktime_correction()
506 nic_minor -= S27_MINOR_MAX; in efx_ptp_s27_to_ktime_correction()
535 kt = ktime_sub_ns(kt, (u64)-correction); in efx_ptp_s_qns_to_ktime_correction()
541 return efx->ptp_data ? efx->ptp_data->channel : NULL; in efx_siena_ptp_channel()
550 major = channel->sync_timestamp_major; in last_sync_timestamp_major()
555 * 48 bits long and provides meta-information in the top 2 bits.
575 * long as the difference between the (real) now and the sync in efx_ptp_mac_nic_to_ktime_correction()
582 * a - b = ((a mod k) - b) mod k in efx_ptp_mac_nic_to_ktime_correction()
584 * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know in efx_ptp_mac_nic_to_ktime_correction()
585 * (a mod k) and b, so can calculate the delta, a - b. in efx_ptp_mac_nic_to_ktime_correction()
593 * we can deal with the (unlikely) case of sync timestamps in efx_ptp_mac_nic_to_ktime_correction()
596 delta = nic_major - sync_timestamp; in efx_ptp_mac_nic_to_ktime_correction()
599 * to the (fully specified) sync time. in efx_ptp_mac_nic_to_ktime_correction()
603 kt = ptp->nic_to_kernel_time(nic_major, nic_minor, in efx_ptp_mac_nic_to_ktime_correction()
611 struct efx_nic *efx = tx_queue->efx; in efx_siena_ptp_nic_to_kernel_time()
612 struct efx_ptp_data *ptp = efx->ptp_data; in efx_siena_ptp_nic_to_kernel_time()
617 tx_queue->completed_timestamp_major, in efx_siena_ptp_nic_to_kernel_time()
618 tx_queue->completed_timestamp_minor, in efx_siena_ptp_nic_to_kernel_time()
619 ptp->ts_corrections.general_tx); in efx_siena_ptp_nic_to_kernel_time()
621 kt = ptp->nic_to_kernel_time( in efx_siena_ptp_nic_to_kernel_time()
622 tx_queue->completed_timestamp_major, in efx_siena_ptp_nic_to_kernel_time()
623 tx_queue->completed_timestamp_minor, in efx_siena_ptp_nic_to_kernel_time()
624 ptp->ts_corrections.general_tx); in efx_siena_ptp_nic_to_kernel_time()
633 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_get_attributes()
648 } else if (rc == -EINVAL) { in efx_ptp_get_attributes()
650 } else if (rc == -EPERM) { in efx_ptp_get_attributes()
651 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_get_attributes()
661 ptp->ns_to_nic_time = efx_ptp_ns_to_s27; in efx_ptp_get_attributes()
662 ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction; in efx_ptp_get_attributes()
663 ptp->nic_time.minor_max = 1 << 27; in efx_ptp_get_attributes()
664 ptp->nic_time.sync_event_minor_shift = 19; in efx_ptp_get_attributes()
667 ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; in efx_ptp_get_attributes()
668 ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction; in efx_ptp_get_attributes()
669 ptp->nic_time.minor_max = 1000000000; in efx_ptp_get_attributes()
670 ptp->nic_time.sync_event_minor_shift = 22; in efx_ptp_get_attributes()
673 ptp->ns_to_nic_time = efx_ptp_ns_to_s_qns; in efx_ptp_get_attributes()
674 ptp->nic_to_kernel_time = efx_ptp_s_qns_to_ktime_correction; in efx_ptp_get_attributes()
675 ptp->nic_time.minor_max = 4000000000UL; in efx_ptp_get_attributes()
676 ptp->nic_time.sync_event_minor_shift = 24; in efx_ptp_get_attributes()
679 return -ERANGE; in efx_ptp_get_attributes()
683 * packet prefix and the last MCDI time sync event. We expect the in efx_ptp_get_attributes()
684 * packet prefix timestamp to be after of sync event by up to one in efx_ptp_get_attributes()
685 * sync event interval (0.25s) but we allow it to exceed this by a in efx_ptp_get_attributes()
688 ptp->nic_time.sync_event_diff_min = ptp->nic_time.minor_max in efx_ptp_get_attributes()
689 - (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
690 ptp->nic_time.sync_event_diff_max = (ptp->nic_time.minor_max / 4) in efx_ptp_get_attributes()
691 + (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
702 ptp->min_synchronisation_ns = in efx_ptp_get_attributes()
706 ptp->min_synchronisation_ns = DEFAULT_MIN_SYNCHRONISATION_NS; in efx_ptp_get_attributes()
710 ptp->capabilities = MCDI_DWORD(outbuf, in efx_ptp_get_attributes()
713 ptp->capabilities = 0; in efx_ptp_get_attributes()
716 * adjustments in parts-per-billion and the fixed-point in efx_ptp_get_attributes()
719 if (ptp->capabilities & (1 << MC_CMD_PTP_OUT_GET_ATTRIBUTES_FP44_FREQ_ADJ_LBN)) in efx_ptp_get_attributes()
720 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP44; in efx_ptp_get_attributes()
722 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP40; in efx_ptp_get_attributes()
736 * not supported (older NICs) then no correction is required. in efx_ptp_get_timestamp_corrections()
745 efx->ptp_data->ts_corrections.ptp_tx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
747 efx->ptp_data->ts_corrections.ptp_rx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
749 efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
751 efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
755 efx->ptp_data->ts_corrections.general_tx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
758 efx->ptp_data->ts_corrections.general_rx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
762 efx->ptp_data->ts_corrections.general_tx = in efx_ptp_get_timestamp_corrections()
763 efx->ptp_data->ts_corrections.ptp_tx; in efx_ptp_get_timestamp_corrections()
764 efx->ptp_data->ts_corrections.general_rx = in efx_ptp_get_timestamp_corrections()
765 efx->ptp_data->ts_corrections.ptp_rx; in efx_ptp_get_timestamp_corrections()
767 } else if (rc == -EINVAL) { in efx_ptp_get_timestamp_corrections()
768 efx->ptp_data->ts_corrections.ptp_tx = 0; in efx_ptp_get_timestamp_corrections()
769 efx->ptp_data->ts_corrections.ptp_rx = 0; in efx_ptp_get_timestamp_corrections()
770 efx->ptp_data->ts_corrections.pps_out = 0; in efx_ptp_get_timestamp_corrections()
771 efx->ptp_data->ts_corrections.pps_in = 0; in efx_ptp_get_timestamp_corrections()
772 efx->ptp_data->ts_corrections.general_tx = 0; in efx_ptp_get_timestamp_corrections()
773 efx->ptp_data->ts_corrections.general_rx = 0; in efx_ptp_get_timestamp_corrections()
793 efx->ptp_data->channel ? in efx_ptp_enable()
794 efx->ptp_data->channel->channel : 0); in efx_ptp_enable()
795 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); in efx_ptp_enable()
799 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_enable()
809 * Note that this function should never rely on the presence of ptp_data -
822 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_disable()
826 if (rc == -ENOSYS || rc == -EPERM) in efx_ptp_disable()
827 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_disable()
848 netif_err(efx, drv, efx->net_dev, in efx_ptp_handle_no_channel()
849 "ERROR: PTP requires MSI-X and 1 additional interrupt" in efx_ptp_handle_no_channel()
861 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_send_times()
862 int *mc_running = ptp->start.addr; in efx_ptp_send_times()
886 efx->type->ptp_write_host_time(efx, host_time); in efx_ptp_send_times()
897 timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); in efx_ptp_read_timeset()
898 timeset->major = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MAJOR); in efx_ptp_read_timeset()
899 timeset->minor = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MINOR); in efx_ptp_read_timeset()
900 timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND); in efx_ptp_read_timeset()
901 timeset->wait = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); in efx_ptp_read_timeset()
904 start_ns = timeset->host_start & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
905 end_ns = timeset->host_end & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
910 timeset->window = end_ns - start_ns; in efx_ptp_read_timeset()
917 * too much greater than this are rejected - the machine is, perhaps, too
932 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_times()
939 return -EAGAIN; in efx_ptp_process_times()
941 /* Read the set of results and find the last good host-MC in efx_ptp_process_times()
954 &ptp->timeset[i]); in efx_ptp_process_times()
957 ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); in efx_ptp_process_times()
958 window = ptp->timeset[i].window; in efx_ptp_process_times()
959 corrected = window - wait.tv_nsec; in efx_ptp_process_times()
965 * Check that the corrected sync window is in a reasonable in efx_ptp_process_times()
971 ++ptp->invalid_sync_windows; in efx_ptp_process_times()
973 ++ptp->oversize_sync_windows; in efx_ptp_process_times()
974 } else if (corrected < ptp->min_synchronisation_ns) { in efx_ptp_process_times()
975 ++ptp->undersize_sync_windows; in efx_ptp_process_times()
983 netif_warn(efx, drv, efx->net_dev, in efx_ptp_process_times()
984 "PTP no suitable synchronisations\n"); in efx_ptp_process_times()
985 return -EAGAIN; in efx_ptp_process_times()
988 /* Calculate delay from last good sync (host time) to last_time. in efx_ptp_process_times()
994 start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; in efx_ptp_process_times()
995 last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; in efx_ptp_process_times()
998 netif_warn(efx, hw, efx->net_dev, in efx_ptp_process_times()
1000 return -EAGAIN; in efx_ptp_process_times()
1002 delta.tv_sec = (last_sec - start_sec) & 1; in efx_ptp_process_times()
1004 last_time->ts_real.tv_nsec - in efx_ptp_process_times()
1005 (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); in efx_ptp_process_times()
1007 /* Convert the NIC time at last good sync into kernel time. in efx_ptp_process_times()
1008 * No correction is required - this time is the output of a in efx_ptp_process_times()
1011 mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, in efx_ptp_process_times()
1012 ptp->timeset[last_good].minor, 0); in efx_ptp_process_times()
1018 ptp->host_time_pps = *last_time; in efx_ptp_process_times()
1019 pps_sub_ts(&ptp->host_time_pps, delta); in efx_ptp_process_times()
1027 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_synchronize()
1034 int *start = ptp->start.addr; in efx_ptp_synchronize()
1041 ptp->start.dma_addr); in efx_ptp_synchronize()
1057 ++ptp->fast_syncs; in efx_ptp_synchronize()
1059 ++ptp->sync_timeouts; in efx_ptp_synchronize()
1073 ++ptp->good_syncs; in efx_ptp_synchronize()
1075 ++ptp->no_time_syncs; in efx_ptp_synchronize()
1082 ++ptp->bad_syncs; in efx_ptp_synchronize()
1090 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_queue()
1094 tx_queue = efx_channel_get_tx_queue(ptp_data->channel, type); in efx_ptp_xmit_skb_queue()
1095 if (tx_queue && tx_queue->timestamping) { in efx_ptp_xmit_skb_queue()
1098 WARN_ONCE(1, "PTP channel has no timestamped tx queue\n"); in efx_ptp_xmit_skb_queue()
1106 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_mc()
1108 int rc = -EIO; in efx_ptp_xmit_skb_mc()
1112 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT); in efx_ptp_xmit_skb_mc()
1113 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_PERIPH_ID, 0); in efx_ptp_xmit_skb_mc()
1114 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len); in efx_ptp_xmit_skb_mc()
1115 if (skb_shinfo(skb)->nr_frags != 0) { in efx_ptp_xmit_skb_mc()
1121 if (skb->ip_summed == CHECKSUM_PARTIAL) { in efx_ptp_xmit_skb_mc()
1127 MCDI_PTR(ptp_data->txbuf, in efx_ptp_xmit_skb_mc()
1129 skb->len); in efx_ptp_xmit_skb_mc()
1130 rc = efx_siena_mcdi_rpc(efx, MC_CMD_PTP, ptp_data->txbuf, in efx_ptp_xmit_skb_mc()
1131 MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len), txtime, in efx_ptp_xmit_skb_mc()
1137 timestamps.hwtstamp = ptp_data->nic_to_kernel_time( in efx_ptp_xmit_skb_mc()
1140 ptp_data->ts_corrections.ptp_tx); in efx_ptp_xmit_skb_mc()
1154 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_drop_time_expired_events()
1158 if (ptp->rx_ts_inline) in efx_ptp_drop_time_expired_events()
1161 /* Drop time-expired events */ in efx_ptp_drop_time_expired_events()
1162 spin_lock_bh(&ptp->evt_lock); in efx_ptp_drop_time_expired_events()
1163 list_for_each_safe(cursor, next, &ptp->evt_list) { in efx_ptp_drop_time_expired_events()
1168 if (time_after(jiffies, evt->expiry)) { in efx_ptp_drop_time_expired_events()
1169 list_move(&evt->link, &ptp->evt_free_list); in efx_ptp_drop_time_expired_events()
1170 netif_warn(efx, hw, efx->net_dev, in efx_ptp_drop_time_expired_events()
1174 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_drop_time_expired_events()
1180 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_match_rx()
1187 WARN_ON_ONCE(ptp->rx_ts_inline); in efx_ptp_match_rx()
1189 spin_lock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1190 evts_waiting = !list_empty(&ptp->evt_list); in efx_ptp_match_rx()
1191 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1196 match = (struct efx_ptp_match *)skb->cb; in efx_ptp_match_rx()
1198 spin_lock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1199 list_for_each_safe(cursor, next, &ptp->evt_list) { in efx_ptp_match_rx()
1203 if ((evt->seq0 == match->words[0]) && in efx_ptp_match_rx()
1204 (evt->seq1 == match->words[1])) { in efx_ptp_match_rx()
1207 /* Match - add in hardware timestamp */ in efx_ptp_match_rx()
1209 timestamps->hwtstamp = evt->hwtimestamp; in efx_ptp_match_rx()
1211 match->state = PTP_PACKET_STATE_MATCHED; in efx_ptp_match_rx()
1213 list_move(&evt->link, &ptp->evt_free_list); in efx_ptp_match_rx()
1217 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1228 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_events()
1231 while ((skb = skb_dequeue(&ptp->rxq))) { in efx_ptp_process_events()
1234 match = (struct efx_ptp_match *)skb->cb; in efx_ptp_process_events()
1235 if (match->state == PTP_PACKET_STATE_MATCH_UNWANTED) { in efx_ptp_process_events()
1240 } else if (time_after(jiffies, match->expiry)) { in efx_ptp_process_events()
1241 match->state = PTP_PACKET_STATE_TIMED_OUT; in efx_ptp_process_events()
1242 ++ptp->rx_no_timestamp; in efx_ptp_process_events()
1246 skb_queue_head(&ptp->rxq, skb); in efx_ptp_process_events()
1262 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_remove_multicast_filters()
1264 if (ptp->rxfilter_installed) { in efx_ptp_remove_multicast_filters()
1266 ptp->rxfilter_general); in efx_ptp_remove_multicast_filters()
1268 ptp->rxfilter_event); in efx_ptp_remove_multicast_filters()
1269 ptp->rxfilter_installed = false; in efx_ptp_remove_multicast_filters()
1275 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_multicast_filters()
1279 if (!ptp->channel || ptp->rxfilter_installed) in efx_ptp_insert_multicast_filters()
1283 * that there is no packet re-ordering. in efx_ptp_insert_multicast_filters()
1287 efx_channel_get_rx_queue(ptp->channel))); in efx_ptp_insert_multicast_filters()
1297 ptp->rxfilter_event = rc; in efx_ptp_insert_multicast_filters()
1301 efx_channel_get_rx_queue(ptp->channel))); in efx_ptp_insert_multicast_filters()
1311 ptp->rxfilter_general = rc; in efx_ptp_insert_multicast_filters()
1313 ptp->rxfilter_installed = true; in efx_ptp_insert_multicast_filters()
1318 ptp->rxfilter_event); in efx_ptp_insert_multicast_filters()
1324 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_start()
1327 ptp->reset_required = false; in efx_ptp_start()
1337 ptp->evt_frag_idx = 0; in efx_ptp_start()
1338 ptp->current_adjfreq = 0; in efx_ptp_start()
1349 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_stop()
1362 efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq); in efx_ptp_stop()
1363 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_stop()
1366 spin_lock_bh(&efx->ptp_data->evt_lock); in efx_ptp_stop()
1367 list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { in efx_ptp_stop()
1368 list_move(cursor, &efx->ptp_data->evt_free_list); in efx_ptp_stop()
1370 spin_unlock_bh(&efx->ptp_data->evt_lock); in efx_ptp_stop()
1377 if (efx->ptp_data && efx->ptp_data->enabled) in efx_ptp_restart()
1386 struct efx_nic *efx = ptp->efx; in efx_ptp_pps_worker()
1393 ptp_evt.pps_times = ptp->host_time_pps; in efx_ptp_pps_worker()
1394 ptp_clock_event(ptp->phc_clock, &ptp_evt); in efx_ptp_pps_worker()
1401 struct efx_nic *efx = ptp_data->efx; in efx_ptp_worker()
1405 if (ptp_data->reset_required) { in efx_ptp_worker()
1416 while ((skb = skb_dequeue(&ptp_data->txq))) in efx_ptp_worker()
1417 ptp_data->xmit_skb(efx, skb); in efx_ptp_worker()
1447 efx->ptp_data = ptp; in efx_ptp_probe()
1448 if (!efx->ptp_data) in efx_ptp_probe()
1449 return -ENOMEM; in efx_ptp_probe()
1451 ptp->efx = efx; in efx_ptp_probe()
1452 ptp->channel = channel; in efx_ptp_probe()
1453 ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; in efx_ptp_probe()
1455 rc = efx_siena_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); in efx_ptp_probe()
1459 skb_queue_head_init(&ptp->rxq); in efx_ptp_probe()
1460 skb_queue_head_init(&ptp->txq); in efx_ptp_probe()
1461 ptp->workwq = create_singlethread_workqueue("sfc_siena_ptp"); in efx_ptp_probe()
1462 if (!ptp->workwq) { in efx_ptp_probe()
1463 rc = -ENOMEM; in efx_ptp_probe()
1468 ptp->xmit_skb = efx_ptp_xmit_skb_queue; in efx_ptp_probe()
1469 /* Request sync events on this channel. */ in efx_ptp_probe()
1470 channel->sync_events_state = SYNC_EVENTS_QUIESCENT; in efx_ptp_probe()
1472 ptp->xmit_skb = efx_ptp_xmit_skb_mc; in efx_ptp_probe()
1475 INIT_WORK(&ptp->work, efx_ptp_worker); in efx_ptp_probe()
1476 ptp->config.flags = 0; in efx_ptp_probe()
1477 ptp->config.tx_type = HWTSTAMP_TX_OFF; in efx_ptp_probe()
1478 ptp->config.rx_filter = HWTSTAMP_FILTER_NONE; in efx_ptp_probe()
1479 INIT_LIST_HEAD(&ptp->evt_list); in efx_ptp_probe()
1480 INIT_LIST_HEAD(&ptp->evt_free_list); in efx_ptp_probe()
1481 spin_lock_init(&ptp->evt_lock); in efx_ptp_probe()
1483 list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); in efx_ptp_probe()
1495 if (efx->mcdi->fn_flags & in efx_ptp_probe()
1497 ptp->phc_clock_info = efx_phc_clock_info; in efx_ptp_probe()
1498 ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, in efx_ptp_probe()
1499 &efx->pci_dev->dev); in efx_ptp_probe()
1500 if (IS_ERR(ptp->phc_clock)) { in efx_ptp_probe()
1501 rc = PTR_ERR(ptp->phc_clock); in efx_ptp_probe()
1503 } else if (ptp->phc_clock) { in efx_ptp_probe()
1504 INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); in efx_ptp_probe()
1505 ptp->pps_workwq = in efx_ptp_probe()
1507 if (!ptp->pps_workwq) { in efx_ptp_probe()
1508 rc = -ENOMEM; in efx_ptp_probe()
1513 ptp->nic_ts_enabled = false; in efx_ptp_probe()
1517 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_probe()
1520 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_probe()
1523 efx_siena_free_buffer(efx, &ptp->start); in efx_ptp_probe()
1526 kfree(efx->ptp_data); in efx_ptp_probe()
1527 efx->ptp_data = NULL; in efx_ptp_probe()
1539 struct efx_nic *efx = channel->efx; in efx_ptp_probe_channel()
1542 channel->irq_moderation_us = 0; in efx_ptp_probe_channel()
1543 channel->rx_queue.core_index = 0; in efx_ptp_probe_channel()
1551 if (rc && rc != -EPERM) in efx_ptp_probe_channel()
1552 netif_warn(efx, drv, efx->net_dev, in efx_ptp_probe_channel()
1559 if (!efx->ptp_data) in efx_ptp_remove()
1564 cancel_work_sync(&efx->ptp_data->work); in efx_ptp_remove()
1565 if (efx->ptp_data->pps_workwq) in efx_ptp_remove()
1566 cancel_work_sync(&efx->ptp_data->pps_work); in efx_ptp_remove()
1568 skb_queue_purge(&efx->ptp_data->rxq); in efx_ptp_remove()
1569 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_remove()
1571 if (efx->ptp_data->phc_clock) { in efx_ptp_remove()
1572 destroy_workqueue(efx->ptp_data->pps_workwq); in efx_ptp_remove()
1573 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_remove()
1576 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_remove()
1578 efx_siena_free_buffer(efx, &efx->ptp_data->start); in efx_ptp_remove()
1579 kfree(efx->ptp_data); in efx_ptp_remove()
1580 efx->ptp_data = NULL; in efx_ptp_remove()
1585 efx_ptp_remove(channel->efx); in efx_ptp_remove_channel()
1591 snprintf(buf, len, "%s-ptp", channel->efx->name); in efx_ptp_get_channel_name()
1599 return efx->ptp_data && in efx_siena_ptp_is_ptp_tx()
1600 efx->ptp_data->enabled && in efx_siena_ptp_is_ptp_tx()
1601 skb->len >= PTP_MIN_LENGTH && in efx_siena_ptp_is_ptp_tx()
1602 skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM && in efx_siena_ptp_is_ptp_tx()
1603 likely(skb->protocol == htons(ETH_P_IP)) && in efx_siena_ptp_is_ptp_tx()
1606 ip_hdr(skb)->protocol == IPPROTO_UDP && in efx_siena_ptp_is_ptp_tx()
1609 udp_hdr(skb)->dest == htons(PTP_EVENT_PORT); in efx_siena_ptp_is_ptp_tx()
1613 * the receive timestamp from the MC - this will probably occur after the
1618 struct efx_nic *efx = channel->efx; in efx_ptp_rx()
1619 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_rx()
1620 struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; in efx_ptp_rx()
1625 match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); in efx_ptp_rx()
1628 if (ptp->mode == MC_CMD_PTP_MODE_V1) { in efx_ptp_rx()
1632 data = skb->data; in efx_ptp_rx()
1647 data = skb->data; in efx_ptp_rx()
1653 /* The original V2 implementation uses bytes 2-7 of in efx_ptp_rx()
1657 * enhanced mode fixes this issue and uses bytes 0-2 in efx_ptp_rx()
1658 * and byte 5-7 of the UUID. in efx_ptp_rx()
1661 if (ptp->mode == MC_CMD_PTP_MODE_V2) { in efx_ptp_rx()
1665 BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); in efx_ptp_rx()
1671 match->state = PTP_PACKET_STATE_UNMATCHED; in efx_ptp_rx()
1680 match->words[0] = (match_data_012[0] | in efx_ptp_rx()
1684 match->words[1] = (match_data_345[1] | in efx_ptp_rx()
1687 PTP_V1_SEQUENCE_LENGTH - 1] << in efx_ptp_rx()
1690 match->state = PTP_PACKET_STATE_MATCH_UNWANTED; in efx_ptp_rx()
1693 skb_queue_tail(&ptp->rxq, skb); in efx_ptp_rx()
1694 queue_work(ptp->workwq, &ptp->work); in efx_ptp_rx()
1705 struct efx_ptp_data *ptp = efx->ptp_data; in efx_siena_ptp_tx()
1707 skb_queue_tail(&ptp->txq, skb); in efx_siena_ptp_tx()
1709 if ((udp_hdr(skb)->dest == htons(PTP_EVENT_PORT)) && in efx_siena_ptp_tx()
1710 (skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM)) in efx_siena_ptp_tx()
1712 queue_work(ptp->workwq, &ptp->work); in efx_siena_ptp_tx()
1719 return efx->ptp_data->mode; in efx_siena_ptp_get_mode()
1725 if ((enable_wanted != efx->ptp_data->enabled) || in efx_siena_ptp_change_mode()
1726 (enable_wanted && (efx->ptp_data->mode != new_mode))) { in efx_siena_ptp_change_mode()
1730 /* Change of mode requires disable */ in efx_siena_ptp_change_mode()
1731 if (efx->ptp_data->enabled && in efx_siena_ptp_change_mode()
1732 (efx->ptp_data->mode != new_mode)) { in efx_siena_ptp_change_mode()
1733 efx->ptp_data->enabled = false; in efx_siena_ptp_change_mode()
1739 /* Set new operating mode and establish in efx_siena_ptp_change_mode()
1743 efx->ptp_data->mode = new_mode; in efx_siena_ptp_change_mode()
1744 if (netif_running(efx->net_dev)) in efx_siena_ptp_change_mode()
1759 efx->ptp_data->enabled = enable_wanted; in efx_siena_ptp_change_mode()
1770 if ((init->tx_type != HWTSTAMP_TX_OFF) && in efx_ptp_ts_init()
1771 (init->tx_type != HWTSTAMP_TX_ON)) in efx_ptp_ts_init()
1772 return -ERANGE; in efx_ptp_ts_init()
1774 rc = efx->type->ptp_set_ts_config(efx, init); in efx_ptp_ts_init()
1778 efx->ptp_data->config = *init; in efx_ptp_ts_init()
1785 struct efx_ptp_data *ptp = efx->ptp_data; in efx_siena_ptp_get_ts_info()
1786 struct efx_nic *primary = efx->primary; in efx_siena_ptp_get_ts_info()
1793 ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | in efx_siena_ptp_get_ts_info()
1796 if (primary && primary->ptp_data && primary->ptp_data->phc_clock) in efx_siena_ptp_get_ts_info()
1797 ts_info->phc_index = in efx_siena_ptp_get_ts_info()
1798 ptp_clock_index(primary->ptp_data->phc_clock); in efx_siena_ptp_get_ts_info()
1799 ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; in efx_siena_ptp_get_ts_info()
1800 ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; in efx_siena_ptp_get_ts_info()
1808 if (!efx->ptp_data) in efx_siena_ptp_set_ts_config()
1809 return -EOPNOTSUPP; in efx_siena_ptp_set_ts_config()
1818 if (!efx->ptp_data) in efx_siena_ptp_get_ts_config()
1819 return -EOPNOTSUPP; in efx_siena_ptp_get_ts_config()
1821 *config = efx->ptp_data->config; in efx_siena_ptp_get_ts_config()
1827 struct efx_ptp_data *ptp = efx->ptp_data; in ptp_event_failure()
1829 netif_err(efx, hw, efx->net_dev, in ptp_event_failure()
1831 ptp->evt_frag_idx, expected_frag_len); in ptp_event_failure()
1832 ptp->reset_required = true; in ptp_event_failure()
1833 queue_work(ptp->workwq, &ptp->work); in ptp_event_failure()
1844 if (WARN_ON_ONCE(ptp->rx_ts_inline)) in ptp_event_rx()
1847 if (ptp->evt_frag_idx != 3) { in ptp_event_rx()
1852 spin_lock_bh(&ptp->evt_lock); in ptp_event_rx()
1853 if (!list_empty(&ptp->evt_free_list)) { in ptp_event_rx()
1854 evt = list_first_entry(&ptp->evt_free_list, in ptp_event_rx()
1856 list_del(&evt->link); in ptp_event_rx()
1858 evt->seq0 = EFX_QWORD_FIELD(ptp->evt_frags[2], MCDI_EVENT_DATA); in ptp_event_rx()
1859 evt->seq1 = (EFX_QWORD_FIELD(ptp->evt_frags[2], in ptp_event_rx()
1861 (EFX_QWORD_FIELD(ptp->evt_frags[1], in ptp_event_rx()
1863 (EFX_QWORD_FIELD(ptp->evt_frags[0], in ptp_event_rx()
1865 evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time( in ptp_event_rx()
1866 EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), in ptp_event_rx()
1867 EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA), in ptp_event_rx()
1868 ptp->ts_corrections.ptp_rx); in ptp_event_rx()
1869 evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); in ptp_event_rx()
1870 list_add_tail(&evt->link, &ptp->evt_list); in ptp_event_rx()
1872 queue_work(ptp->workwq, &ptp->work); in ptp_event_rx()
1874 /* Log a rate-limited warning message. */ in ptp_event_rx()
1875 netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); in ptp_event_rx()
1877 spin_unlock_bh(&ptp->evt_lock); in ptp_event_rx()
1882 int code = EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA); in ptp_event_fault()
1883 if (ptp->evt_frag_idx != 1) { in ptp_event_fault()
1888 netif_err(efx, hw, efx->net_dev, "PTP error %d\n", code); in ptp_event_fault()
1893 if (ptp->nic_ts_enabled) in ptp_event_pps()
1894 queue_work(ptp->pps_workwq, &ptp->pps_work); in ptp_event_pps()
1899 struct efx_ptp_data *ptp = efx->ptp_data; in efx_siena_ptp_event()
1903 if (!efx->ptp_warned) { in efx_siena_ptp_event()
1904 netif_warn(efx, drv, efx->net_dev, in efx_siena_ptp_event()
1906 efx->ptp_warned = true; in efx_siena_ptp_event()
1911 if (!ptp->enabled) in efx_siena_ptp_event()
1914 if (ptp->evt_frag_idx == 0) { in efx_siena_ptp_event()
1915 ptp->evt_code = code; in efx_siena_ptp_event()
1916 } else if (ptp->evt_code != code) { in efx_siena_ptp_event()
1917 netif_err(efx, hw, efx->net_dev, in efx_siena_ptp_event()
1919 ptp->evt_frag_idx = 0; in efx_siena_ptp_event()
1922 ptp->evt_frags[ptp->evt_frag_idx++] = *ev; in efx_siena_ptp_event()
1936 netif_err(efx, hw, efx->net_dev, in efx_siena_ptp_event()
1940 ptp->evt_frag_idx = 0; in efx_siena_ptp_event()
1941 } else if (MAX_EVENT_FRAGS == ptp->evt_frag_idx) { in efx_siena_ptp_event()
1942 netif_err(efx, hw, efx->net_dev, in efx_siena_ptp_event()
1944 ptp->evt_frag_idx = 0; in efx_siena_ptp_event()
1950 struct efx_nic *efx = channel->efx; in efx_siena_time_sync_event()
1951 struct efx_ptp_data *ptp = efx->ptp_data; in efx_siena_time_sync_event()
1953 /* When extracting the sync timestamp minor value, we should discard in efx_siena_time_sync_event()
1955 * to reconstruct full-range timestamps and they are optionally used in efx_siena_time_sync_event()
1957 * for sync events. in efx_siena_time_sync_event()
1959 channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR); in efx_siena_time_sync_event()
1960 channel->sync_timestamp_minor = in efx_siena_time_sync_event()
1962 << ptp->nic_time.sync_event_minor_shift; in efx_siena_time_sync_event()
1964 /* if sync events have been disabled then we want to silently ignore in efx_siena_time_sync_event()
1967 (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED, in efx_siena_time_sync_event()
1974 return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset)); in efx_rx_buf_timestamp_minor()
1976 const u8 *data = eh + efx->rx_packet_ts_offset; in efx_rx_buf_timestamp_minor()
1987 struct efx_nic *efx = channel->efx; in __efx_siena_rx_skb_attach_timestamp()
1988 struct efx_ptp_data *ptp = efx->ptp_data; in __efx_siena_rx_skb_attach_timestamp()
1993 if (channel->sync_events_state != SYNC_EVENTS_VALID) in __efx_siena_rx_skb_attach_timestamp()
1998 /* get the difference between the packet and sync timestamps, in __efx_siena_rx_skb_attach_timestamp()
2001 diff = pkt_timestamp_minor - channel->sync_timestamp_minor; in __efx_siena_rx_skb_attach_timestamp()
2002 if (pkt_timestamp_minor < channel->sync_timestamp_minor) in __efx_siena_rx_skb_attach_timestamp()
2003 diff += ptp->nic_time.minor_max; in __efx_siena_rx_skb_attach_timestamp()
2006 carry = (channel->sync_timestamp_minor >= ptp->nic_time.minor_max - diff) ? in __efx_siena_rx_skb_attach_timestamp()
2009 if (diff <= ptp->nic_time.sync_event_diff_max) { in __efx_siena_rx_skb_attach_timestamp()
2010 /* packet is ahead of the sync event by a quarter of a second or in __efx_siena_rx_skb_attach_timestamp()
2013 pkt_timestamp_major = channel->sync_timestamp_major + carry; in __efx_siena_rx_skb_attach_timestamp()
2014 } else if (diff >= ptp->nic_time.sync_event_diff_min) { in __efx_siena_rx_skb_attach_timestamp()
2015 /* packet is behind the sync event but within the fuzz factor. in __efx_siena_rx_skb_attach_timestamp()
2016 * This means the RX packet and sync event crossed as they were in __efx_siena_rx_skb_attach_timestamp()
2019 pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry; in __efx_siena_rx_skb_attach_timestamp()
2022 * indicative of us missing sync events for some reason, so in __efx_siena_rx_skb_attach_timestamp()
2026 netif_vdbg(efx, drv, efx->net_dev, in __efx_siena_rx_skb_attach_timestamp()
2027 "packet timestamp %x too far from sync event %x:%x\n", in __efx_siena_rx_skb_attach_timestamp()
2028 pkt_timestamp_minor, channel->sync_timestamp_major, in __efx_siena_rx_skb_attach_timestamp()
2029 channel->sync_timestamp_minor); in __efx_siena_rx_skb_attach_timestamp()
2035 timestamps->hwtstamp = in __efx_siena_rx_skb_attach_timestamp()
2036 ptp->nic_to_kernel_time(pkt_timestamp_major, in __efx_siena_rx_skb_attach_timestamp()
2038 ptp->ts_corrections.general_rx); in __efx_siena_rx_skb_attach_timestamp()
2047 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjfine()
2054 else if (delta < -MAX_PPB) in efx_phc_adjfine()
2055 delta = -MAX_PPB; in efx_phc_adjfine()
2059 (1 << (ptp_data->adjfreq_ppb_shift - 1))) >> in efx_phc_adjfine()
2060 ptp_data->adjfreq_ppb_shift; in efx_phc_adjfine()
2072 ptp_data->current_adjfreq = adjustment_ns; in efx_phc_adjfine()
2082 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjtime()
2085 efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor); in efx_phc_adjtime()
2089 MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); in efx_phc_adjtime()
2101 struct efx_nic *efx = ptp_data->efx; in efx_phc_gettime()
2115 kt = ptp_data->nic_to_kernel_time( in efx_phc_gettime()
2153 if (request->type != PTP_CLK_REQ_PPS) in efx_phc_enable()
2154 return -EOPNOTSUPP; in efx_phc_enable()
2156 ptp_data->nic_ts_enabled = !!enable; in efx_phc_enable()
2165 /* no copy operation; there is no need to reallocate this channel */
2177 efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = in efx_siena_ptp_defer_probe_with_channel()
2184 netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); in efx_siena_ptp_start_datapath()
2185 /* re-enable timestamping if it was previously enabled */ in efx_siena_ptp_start_datapath()
2186 if (efx->type->ptp_set_ts_sync_events) in efx_siena_ptp_start_datapath()
2187 efx->type->ptp_set_ts_sync_events(efx, true, true); in efx_siena_ptp_start_datapath()
2193 if (efx->type->ptp_set_ts_sync_events) in efx_siena_ptp_stop_datapath()
2194 efx->type->ptp_set_ts_sync_events(efx, false, true); in efx_siena_ptp_stop_datapath()