Lines Matching +full:scaled +full:- +full:sync
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2011-2013 Solarflare Communications Inc.
115 #define PTP_ADDR_ETHER {0x01, 0x1b, 0x19, 0, 0, 0} /* 01-1B-19-00-00-00 */
136 #define MC_NANOSECOND_MASK ((1 << MC_NANOSECOND_BITS) - 1)
137 #define MC_SECOND_MASK ((1 << (32 - MC_NANOSECOND_BITS)) - 1)
139 /* Maximum parts-per-billion adjustment that is acceptable */
154 * struct efx_ptp_match - Matching structure, stored in sk_buff's cb area.
157 * @state: The state of the packet - whether it is ready for processing or
166 * struct efx_ptp_event_rx - A PTP receive event (from MC)
182 * struct efx_ptp_timeset - Synchronisation between host and MC
198 u32 window; /* Derived: end - start, allowing for wrap */
202 * struct efx_ptp_rxfilter - Filter for PTP packets
220 * struct efx_ptp_data - Precision Time Protocol (PTP) state
240 * in packet prefix and last MCDI time sync event i.e. how much earlier than
241 * the last sync event time a packet timestamp can be.
243 * in packet prefix and last MCDI time sync event i.e. how much later than
244 * the last sync event time a packet timestamp can be.
246 * field in MCDI time sync event.
247 * @min_synchronisation_ns: Minimum acceptable corrected sync window
265 * @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
280 * @invalid_sync_windows: Number of sync windows with bad durations.
281 * @undersize_sync_windows: Number of corrected sync windows that are too small
282 * @oversize_sync_windows: Number of corrected sync windows that are too large
368 return efx_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_ptp_describe_stats()
412 if (!efx->ptp_data) in efx_ptp_update_stats()
419 stats[i] = *(unsigned int *)((char *)efx->ptp_data + in efx_ptp_update_stats()
446 #define NS_TO_S27_SHIFT (63 - S27_TO_NS_SHIFT)
450 * where the minor register only uses 27 bits in units of 2^-27s.
457 (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); in efx_ptp_ns_to_s27()
463 min -= S27_MINOR_MAX; in efx_ptp_ns_to_s27()
474 (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); in efx_ptp_s27_to_ktime()
485 nic_major--; in efx_ptp_s27_to_ktime_correction()
487 nic_minor -= S27_MINOR_MAX; in efx_ptp_s27_to_ktime_correction()
516 kt = ktime_sub_ns(kt, (u64)-correction); in efx_ptp_s_qns_to_ktime_correction()
522 return efx->ptp_data ? efx->ptp_data->channel : NULL; in efx_ptp_channel()
527 if (efx->ptp_data) in efx_ptp_update_channel()
528 efx->ptp_data->channel = channel; in efx_ptp_update_channel()
537 major = channel->sync_timestamp_major; in last_sync_timestamp_major()
542 * 48 bits long and provides meta-information in the top 2 bits.
562 * long as the difference between the (real) now and the sync in efx_ptp_mac_nic_to_ktime_correction()
569 * a - b = ((a mod k) - b) mod k in efx_ptp_mac_nic_to_ktime_correction()
571 * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know in efx_ptp_mac_nic_to_ktime_correction()
572 * (a mod k) and b, so can calculate the delta, a - b. in efx_ptp_mac_nic_to_ktime_correction()
580 * we can deal with the (unlikely) case of sync timestamps in efx_ptp_mac_nic_to_ktime_correction()
583 delta = nic_major - sync_timestamp; in efx_ptp_mac_nic_to_ktime_correction()
586 * to the (fully specified) sync time. in efx_ptp_mac_nic_to_ktime_correction()
590 kt = ptp->nic_to_kernel_time(nic_major, nic_minor, in efx_ptp_mac_nic_to_ktime_correction()
598 struct efx_nic *efx = tx_queue->efx; in efx_ptp_nic_to_kernel_time()
599 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_nic_to_kernel_time()
604 tx_queue->completed_timestamp_major, in efx_ptp_nic_to_kernel_time()
605 tx_queue->completed_timestamp_minor, in efx_ptp_nic_to_kernel_time()
606 ptp->ts_corrections.general_tx); in efx_ptp_nic_to_kernel_time()
608 kt = ptp->nic_to_kernel_time( in efx_ptp_nic_to_kernel_time()
609 tx_queue->completed_timestamp_major, in efx_ptp_nic_to_kernel_time()
610 tx_queue->completed_timestamp_minor, in efx_ptp_nic_to_kernel_time()
611 ptp->ts_corrections.general_tx); in efx_ptp_nic_to_kernel_time()
620 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_get_attributes()
635 } else if (rc == -EINVAL) { in efx_ptp_get_attributes()
637 } else if (rc == -EPERM) { in efx_ptp_get_attributes()
638 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_get_attributes()
648 ptp->ns_to_nic_time = efx_ptp_ns_to_s27; in efx_ptp_get_attributes()
649 ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction; in efx_ptp_get_attributes()
650 ptp->nic_time.minor_max = 1 << 27; in efx_ptp_get_attributes()
651 ptp->nic_time.sync_event_minor_shift = 19; in efx_ptp_get_attributes()
654 ptp->ns_to_nic_time = efx_ptp_ns_to_s_qns; in efx_ptp_get_attributes()
655 ptp->nic_to_kernel_time = efx_ptp_s_qns_to_ktime_correction; in efx_ptp_get_attributes()
656 ptp->nic_time.minor_max = 4000000000UL; in efx_ptp_get_attributes()
657 ptp->nic_time.sync_event_minor_shift = 24; in efx_ptp_get_attributes()
660 return -ERANGE; in efx_ptp_get_attributes()
664 * packet prefix and the last MCDI time sync event. We expect the in efx_ptp_get_attributes()
665 * packet prefix timestamp to be after of sync event by up to one in efx_ptp_get_attributes()
666 * sync event interval (0.25s) but we allow it to exceed this by a in efx_ptp_get_attributes()
669 ptp->nic_time.sync_event_diff_min = ptp->nic_time.minor_max in efx_ptp_get_attributes()
670 - (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
671 ptp->nic_time.sync_event_diff_max = (ptp->nic_time.minor_max / 4) in efx_ptp_get_attributes()
672 + (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
683 ptp->min_synchronisation_ns = in efx_ptp_get_attributes()
687 ptp->min_synchronisation_ns = DEFAULT_MIN_SYNCHRONISATION_NS; in efx_ptp_get_attributes()
691 ptp->capabilities = MCDI_DWORD(outbuf, in efx_ptp_get_attributes()
694 ptp->capabilities = 0; in efx_ptp_get_attributes()
697 * adjustments in parts-per-billion and the fixed-point in efx_ptp_get_attributes()
700 if (ptp->capabilities & (1 << MC_CMD_PTP_OUT_GET_ATTRIBUTES_FP44_FREQ_ADJ_LBN)) in efx_ptp_get_attributes()
701 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP44; in efx_ptp_get_attributes()
703 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP40; in efx_ptp_get_attributes()
726 efx->ptp_data->ts_corrections.ptp_tx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
728 efx->ptp_data->ts_corrections.ptp_rx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
730 efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
732 efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
736 efx->ptp_data->ts_corrections.general_tx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
739 efx->ptp_data->ts_corrections.general_rx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
743 efx->ptp_data->ts_corrections.general_tx = in efx_ptp_get_timestamp_corrections()
744 efx->ptp_data->ts_corrections.ptp_tx; in efx_ptp_get_timestamp_corrections()
745 efx->ptp_data->ts_corrections.general_rx = in efx_ptp_get_timestamp_corrections()
746 efx->ptp_data->ts_corrections.ptp_rx; in efx_ptp_get_timestamp_corrections()
748 } else if (rc == -EINVAL) { in efx_ptp_get_timestamp_corrections()
749 efx->ptp_data->ts_corrections.ptp_tx = 0; in efx_ptp_get_timestamp_corrections()
750 efx->ptp_data->ts_corrections.ptp_rx = 0; in efx_ptp_get_timestamp_corrections()
751 efx->ptp_data->ts_corrections.pps_out = 0; in efx_ptp_get_timestamp_corrections()
752 efx->ptp_data->ts_corrections.pps_in = 0; in efx_ptp_get_timestamp_corrections()
753 efx->ptp_data->ts_corrections.general_tx = 0; in efx_ptp_get_timestamp_corrections()
754 efx->ptp_data->ts_corrections.general_rx = 0; in efx_ptp_get_timestamp_corrections()
774 efx->ptp_data->channel ? in efx_ptp_enable()
775 efx->ptp_data->channel->channel : 0); in efx_ptp_enable()
776 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); in efx_ptp_enable()
780 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_enable()
790 * Note that this function should never rely on the presence of ptp_data -
803 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_disable()
807 if (rc == -ENOSYS || rc == -EPERM) in efx_ptp_disable()
808 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_disable()
829 netif_err(efx, drv, efx->net_dev, in efx_ptp_handle_no_channel()
830 "ERROR: PTP requires MSI-X and 1 additional interrupt" in efx_ptp_handle_no_channel()
842 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_send_times()
843 int *mc_running = ptp->start.addr; in efx_ptp_send_times()
867 efx->type->ptp_write_host_time(efx, host_time); in efx_ptp_send_times()
878 timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); in efx_ptp_read_timeset()
879 timeset->major = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MAJOR); in efx_ptp_read_timeset()
880 timeset->minor = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MINOR); in efx_ptp_read_timeset()
881 timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND), in efx_ptp_read_timeset()
882 timeset->wait = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); in efx_ptp_read_timeset()
885 start_ns = timeset->host_start & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
886 end_ns = timeset->host_end & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
891 timeset->window = end_ns - start_ns; in efx_ptp_read_timeset()
898 * too much greater than this are rejected - the machine is, perhaps, too
913 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_times()
920 return -EAGAIN; in efx_ptp_process_times()
922 /* Read the set of results and find the last good host-MC in efx_ptp_process_times()
935 &ptp->timeset[i]); in efx_ptp_process_times()
938 ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); in efx_ptp_process_times()
939 window = ptp->timeset[i].window; in efx_ptp_process_times()
940 corrected = window - wait.tv_nsec; in efx_ptp_process_times()
946 * Check that the corrected sync window is in a reasonable in efx_ptp_process_times()
952 ++ptp->invalid_sync_windows; in efx_ptp_process_times()
954 ++ptp->oversize_sync_windows; in efx_ptp_process_times()
955 } else if (corrected < ptp->min_synchronisation_ns) { in efx_ptp_process_times()
956 ++ptp->undersize_sync_windows; in efx_ptp_process_times()
964 netif_warn(efx, drv, efx->net_dev, in efx_ptp_process_times()
966 return -EAGAIN; in efx_ptp_process_times()
969 /* Calculate delay from last good sync (host time) to last_time. in efx_ptp_process_times()
975 start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; in efx_ptp_process_times()
976 last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; in efx_ptp_process_times()
979 netif_warn(efx, hw, efx->net_dev, in efx_ptp_process_times()
981 return -EAGAIN; in efx_ptp_process_times()
983 delta.tv_sec = (last_sec - start_sec) & 1; in efx_ptp_process_times()
985 last_time->ts_real.tv_nsec - in efx_ptp_process_times()
986 (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); in efx_ptp_process_times()
988 /* Convert the NIC time at last good sync into kernel time. in efx_ptp_process_times()
989 * No correction is required - this time is the output of a in efx_ptp_process_times()
992 mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, in efx_ptp_process_times()
993 ptp->timeset[last_good].minor, 0); in efx_ptp_process_times()
999 ptp->host_time_pps = *last_time; in efx_ptp_process_times()
1000 pps_sub_ts(&ptp->host_time_pps, delta); in efx_ptp_process_times()
1008 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_synchronize()
1015 int *start = ptp->start.addr; in efx_ptp_synchronize()
1022 ptp->start.dma_addr); in efx_ptp_synchronize()
1038 ++ptp->fast_syncs; in efx_ptp_synchronize()
1040 ++ptp->sync_timeouts; in efx_ptp_synchronize()
1054 ++ptp->good_syncs; in efx_ptp_synchronize()
1056 ++ptp->no_time_syncs; in efx_ptp_synchronize()
1063 ++ptp->bad_syncs; in efx_ptp_synchronize()
1071 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_queue()
1075 tx_queue = efx_channel_get_tx_queue(ptp_data->channel, type); in efx_ptp_xmit_skb_queue()
1076 if (tx_queue && tx_queue->timestamping) { in efx_ptp_xmit_skb_queue()
1090 * 1) The code invoked is mainly implemented for non-PTP in efx_ptp_xmit_skb_queue()
1119 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_mc()
1124 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT); in efx_ptp_xmit_skb_mc()
1125 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_PERIPH_ID, 0); in efx_ptp_xmit_skb_mc()
1126 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len); in efx_ptp_xmit_skb_mc()
1127 if (skb_shinfo(skb)->nr_frags != 0) { in efx_ptp_xmit_skb_mc()
1133 if (skb->ip_summed == CHECKSUM_PARTIAL) { in efx_ptp_xmit_skb_mc()
1139 MCDI_PTR(ptp_data->txbuf, in efx_ptp_xmit_skb_mc()
1141 skb->len); in efx_ptp_xmit_skb_mc()
1143 ptp_data->txbuf, MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len), in efx_ptp_xmit_skb_mc()
1149 timestamps.hwtstamp = ptp_data->nic_to_kernel_time( in efx_ptp_xmit_skb_mc()
1152 ptp_data->ts_corrections.ptp_tx); in efx_ptp_xmit_skb_mc()
1173 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_events()
1176 while ((skb = skb_dequeue(&ptp->rxq))) { in efx_ptp_process_events()
1179 match = (struct efx_ptp_match *)skb->cb; in efx_ptp_process_events()
1180 if (match->state == PTP_PACKET_STATE_MATCH_UNWANTED) { in efx_ptp_process_events()
1182 } else if (time_after(jiffies, match->expiry)) { in efx_ptp_process_events()
1183 match->state = PTP_PACKET_STATE_TIMED_OUT; in efx_ptp_process_events()
1184 ++ptp->rx_no_timestamp; in efx_ptp_process_events()
1188 skb_queue_head(&ptp->rxq, skb); in efx_ptp_process_events()
1208 if (rxfilter->ether_type == spec->ether_type && in efx_ptp_find_filter()
1209 rxfilter->loc_port == spec->loc_port && in efx_ptp_find_filter()
1210 !memcmp(rxfilter->loc_host, spec->loc_host, sizeof(spec->loc_host))) in efx_ptp_find_filter()
1221 rxfilter->handle); in efx_ptp_remove_one_filter()
1222 list_del(&rxfilter->list); in efx_ptp_remove_one_filter()
1238 struct efx_channel *channel = efx->ptp_data->channel; in efx_ptp_init_filter()
1250 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_filter()
1256 rxfilter->expiry = expiry; in efx_ptp_insert_filter()
1262 return -ENOMEM; in efx_ptp_insert_filter()
1268 rxfilter->handle = rc; in efx_ptp_insert_filter()
1269 rxfilter->ether_type = spec->ether_type; in efx_ptp_insert_filter()
1270 rxfilter->loc_port = spec->loc_port; in efx_ptp_insert_filter()
1271 memcpy(rxfilter->loc_host, spec->loc_host, sizeof(spec->loc_host)); in efx_ptp_insert_filter()
1272 rxfilter->expiry = expiry; in efx_ptp_insert_filter()
1273 list_add(&rxfilter->list, filter_list); in efx_ptp_insert_filter()
1275 queue_delayed_work(ptp->workwq, &ptp->cleanup_work, in efx_ptp_insert_filter()
1311 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_eth_multicast_filter()
1319 return efx_ptp_insert_filter(efx, &ptp->rxfilters_mcast, &spec, 0); in efx_ptp_insert_eth_multicast_filter()
1324 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_multicast_filters()
1327 if (!ptp->channel || !list_empty(&ptp->rxfilters_mcast)) in efx_ptp_insert_multicast_filters()
1331 * that there is no packet re-ordering. in efx_ptp_insert_multicast_filters()
1333 rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_mcast, in efx_ptp_insert_multicast_filters()
1339 rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_mcast, in efx_ptp_insert_multicast_filters()
1351 rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_mcast, in efx_ptp_insert_multicast_filters()
1356 rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_mcast, in efx_ptp_insert_multicast_filters()
1364 if (rc < 0 && rc != -EPROTONOSUPPORT) in efx_ptp_insert_multicast_filters()
1371 efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast); in efx_ptp_insert_multicast_filters()
1377 if (skb->protocol == htons(ETH_P_IP)) { in efx_ptp_valid_unicast_event_pkt()
1378 return ip_hdr(skb)->daddr != htonl(PTP_ADDR_IPV4) && in efx_ptp_valid_unicast_event_pkt()
1379 ip_hdr(skb)->protocol == IPPROTO_UDP && in efx_ptp_valid_unicast_event_pkt()
1380 udp_hdr(skb)->source == htons(PTP_EVENT_PORT); in efx_ptp_valid_unicast_event_pkt()
1381 } else if (skb->protocol == htons(ETH_P_IPV6)) { in efx_ptp_valid_unicast_event_pkt()
1384 return !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &mcast_addr) && in efx_ptp_valid_unicast_event_pkt()
1385 ipv6_hdr(skb)->nexthdr == IPPROTO_UDP && in efx_ptp_valid_unicast_event_pkt()
1386 udp_hdr(skb)->source == htons(PTP_EVENT_PORT); in efx_ptp_valid_unicast_event_pkt()
1394 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_unicast_filter()
1399 return -EINVAL; in efx_ptp_insert_unicast_filter()
1403 if (skb->protocol == htons(ETH_P_IP)) { in efx_ptp_insert_unicast_filter()
1404 __be32 addr = ip_hdr(skb)->saddr; in efx_ptp_insert_unicast_filter()
1406 rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_ucast, in efx_ptp_insert_unicast_filter()
1411 rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_ucast, in efx_ptp_insert_unicast_filter()
1415 struct in6_addr *addr = &ipv6_hdr(skb)->saddr; in efx_ptp_insert_unicast_filter()
1417 rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_ucast, in efx_ptp_insert_unicast_filter()
1422 rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_ucast, in efx_ptp_insert_unicast_filter()
1425 return -EOPNOTSUPP; in efx_ptp_insert_unicast_filter()
1434 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_start()
1437 ptp->reset_required = false; in efx_ptp_start()
1447 ptp->evt_frag_idx = 0; in efx_ptp_start()
1448 ptp->current_adjfreq = 0; in efx_ptp_start()
1453 efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast); in efx_ptp_start()
1459 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_stop()
1467 efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast); in efx_ptp_stop()
1468 efx_ptp_remove_filters(efx, &ptp->rxfilters_ucast); in efx_ptp_stop()
1471 efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq); in efx_ptp_stop()
1472 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_stop()
1479 if (efx->ptp_data && efx->ptp_data->enabled) in efx_ptp_restart()
1488 struct efx_nic *efx = ptp->efx; in efx_ptp_pps_worker()
1495 ptp_evt.pps_times = ptp->host_time_pps; in efx_ptp_pps_worker()
1496 ptp_clock_event(ptp->phc_clock, &ptp_evt); in efx_ptp_pps_worker()
1503 struct efx_nic *efx = ptp_data->efx; in efx_ptp_worker()
1507 if (ptp_data->reset_required) { in efx_ptp_worker()
1516 while ((skb = skb_dequeue(&ptp_data->txq))) in efx_ptp_worker()
1517 ptp_data->xmit_skb(efx, skb); in efx_ptp_worker()
1529 list_for_each_entry_safe(rxfilter, tmp, &ptp->rxfilters_ucast, list) { in efx_ptp_cleanup_worker()
1530 if (time_is_before_jiffies(rxfilter->expiry)) in efx_ptp_cleanup_worker()
1531 efx_ptp_remove_one_filter(ptp->efx, rxfilter); in efx_ptp_cleanup_worker()
1534 if (!list_empty(&ptp->rxfilters_ucast)) { in efx_ptp_cleanup_worker()
1535 queue_delayed_work(ptp->workwq, &ptp->cleanup_work, in efx_ptp_cleanup_worker()
1562 if (efx->ptp_data) { in efx_ptp_probe()
1563 efx->ptp_data->channel = channel; in efx_ptp_probe()
1568 efx->ptp_data = ptp; in efx_ptp_probe()
1569 if (!efx->ptp_data) in efx_ptp_probe()
1570 return -ENOMEM; in efx_ptp_probe()
1572 ptp->efx = efx; in efx_ptp_probe()
1573 ptp->channel = channel; in efx_ptp_probe()
1575 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); in efx_ptp_probe()
1579 skb_queue_head_init(&ptp->rxq); in efx_ptp_probe()
1580 skb_queue_head_init(&ptp->txq); in efx_ptp_probe()
1581 ptp->workwq = create_singlethread_workqueue("sfc_ptp"); in efx_ptp_probe()
1582 if (!ptp->workwq) { in efx_ptp_probe()
1583 rc = -ENOMEM; in efx_ptp_probe()
1588 ptp->xmit_skb = efx_ptp_xmit_skb_queue; in efx_ptp_probe()
1589 /* Request sync events on this channel. */ in efx_ptp_probe()
1590 channel->sync_events_state = SYNC_EVENTS_QUIESCENT; in efx_ptp_probe()
1592 ptp->xmit_skb = efx_ptp_xmit_skb_mc; in efx_ptp_probe()
1595 INIT_WORK(&ptp->work, efx_ptp_worker); in efx_ptp_probe()
1596 INIT_DELAYED_WORK(&ptp->cleanup_work, efx_ptp_cleanup_worker); in efx_ptp_probe()
1597 ptp->config.flags = 0; in efx_ptp_probe()
1598 ptp->config.tx_type = HWTSTAMP_TX_OFF; in efx_ptp_probe()
1599 ptp->config.rx_filter = HWTSTAMP_FILTER_NONE; in efx_ptp_probe()
1600 INIT_LIST_HEAD(&ptp->rxfilters_mcast); in efx_ptp_probe()
1601 INIT_LIST_HEAD(&ptp->rxfilters_ucast); in efx_ptp_probe()
1613 if (efx->mcdi->fn_flags & in efx_ptp_probe()
1615 ptp->phc_clock_info = efx_phc_clock_info; in efx_ptp_probe()
1616 ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, in efx_ptp_probe()
1617 &efx->pci_dev->dev); in efx_ptp_probe()
1618 if (IS_ERR(ptp->phc_clock)) { in efx_ptp_probe()
1619 rc = PTR_ERR(ptp->phc_clock); in efx_ptp_probe()
1621 } else if (ptp->phc_clock) { in efx_ptp_probe()
1622 INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); in efx_ptp_probe()
1623 ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); in efx_ptp_probe()
1624 if (!ptp->pps_workwq) { in efx_ptp_probe()
1625 rc = -ENOMEM; in efx_ptp_probe()
1630 ptp->nic_ts_enabled = false; in efx_ptp_probe()
1634 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_probe()
1637 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_probe()
1640 efx_nic_free_buffer(efx, &ptp->start); in efx_ptp_probe()
1643 kfree(efx->ptp_data); in efx_ptp_probe()
1644 efx->ptp_data = NULL; in efx_ptp_probe()
1656 struct efx_nic *efx = channel->efx; in efx_ptp_probe_channel()
1659 channel->irq_moderation_us = 0; in efx_ptp_probe_channel()
1660 channel->rx_queue.core_index = 0; in efx_ptp_probe_channel()
1668 if (rc && rc != -EPERM) in efx_ptp_probe_channel()
1669 netif_warn(efx, drv, efx->net_dev, in efx_ptp_probe_channel()
1676 if (!efx->ptp_data) in efx_ptp_remove()
1681 cancel_work_sync(&efx->ptp_data->work); in efx_ptp_remove()
1682 cancel_delayed_work_sync(&efx->ptp_data->cleanup_work); in efx_ptp_remove()
1683 if (efx->ptp_data->pps_workwq) in efx_ptp_remove()
1684 cancel_work_sync(&efx->ptp_data->pps_work); in efx_ptp_remove()
1686 skb_queue_purge(&efx->ptp_data->rxq); in efx_ptp_remove()
1687 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_remove()
1689 if (efx->ptp_data->phc_clock) { in efx_ptp_remove()
1690 destroy_workqueue(efx->ptp_data->pps_workwq); in efx_ptp_remove()
1691 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_remove()
1694 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_remove()
1696 efx_nic_free_buffer(efx, &efx->ptp_data->start); in efx_ptp_remove()
1697 kfree(efx->ptp_data); in efx_ptp_remove()
1698 efx->ptp_data = NULL; in efx_ptp_remove()
1703 efx_ptp_remove(channel->efx); in efx_ptp_remove_channel()
1709 snprintf(buf, len, "%s-ptp", channel->efx->name); in efx_ptp_get_channel_name()
1717 return efx->ptp_data && in efx_ptp_is_ptp_tx()
1718 efx->ptp_data->enabled && in efx_ptp_is_ptp_tx()
1719 skb->len >= PTP_MIN_LENGTH && in efx_ptp_is_ptp_tx()
1720 skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM && in efx_ptp_is_ptp_tx()
1721 likely(skb->protocol == htons(ETH_P_IP)) && in efx_ptp_is_ptp_tx()
1724 ip_hdr(skb)->protocol == IPPROTO_UDP && in efx_ptp_is_ptp_tx()
1727 udp_hdr(skb)->dest == htons(PTP_EVENT_PORT); in efx_ptp_is_ptp_tx()
1731 * the receive timestamp from the MC - this will probably occur after the
1736 struct efx_nic *efx = channel->efx; in efx_ptp_rx()
1737 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_rx()
1738 struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; in efx_ptp_rx()
1742 match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); in efx_ptp_rx()
1745 if (ptp->mode == MC_CMD_PTP_MODE_V1) { in efx_ptp_rx()
1749 data = skb->data; in efx_ptp_rx()
1758 data = skb->data; in efx_ptp_rx()
1767 match->state = PTP_PACKET_STATE_UNMATCHED; in efx_ptp_rx()
1775 match->state = PTP_PACKET_STATE_MATCH_UNWANTED; in efx_ptp_rx()
1778 skb_queue_tail(&ptp->rxq, skb); in efx_ptp_rx()
1779 queue_work(ptp->workwq, &ptp->work); in efx_ptp_rx()
1790 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_tx()
1792 skb_queue_tail(&ptp->txq, skb); in efx_ptp_tx()
1794 if ((udp_hdr(skb)->dest == htons(PTP_EVENT_PORT)) && in efx_ptp_tx()
1795 (skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM)) in efx_ptp_tx()
1797 queue_work(ptp->workwq, &ptp->work); in efx_ptp_tx()
1804 return efx->ptp_data->mode; in efx_ptp_get_mode()
1810 if ((enable_wanted != efx->ptp_data->enabled) || in efx_ptp_change_mode()
1811 (enable_wanted && (efx->ptp_data->mode != new_mode))) { in efx_ptp_change_mode()
1816 if (efx->ptp_data->enabled && in efx_ptp_change_mode()
1817 (efx->ptp_data->mode != new_mode)) { in efx_ptp_change_mode()
1818 efx->ptp_data->enabled = false; in efx_ptp_change_mode()
1828 efx->ptp_data->mode = new_mode; in efx_ptp_change_mode()
1829 if (netif_running(efx->net_dev)) in efx_ptp_change_mode()
1844 efx->ptp_data->enabled = enable_wanted; in efx_ptp_change_mode()
1854 if ((init->tx_type != HWTSTAMP_TX_OFF) && in efx_ptp_ts_init()
1855 (init->tx_type != HWTSTAMP_TX_ON)) in efx_ptp_ts_init()
1856 return -ERANGE; in efx_ptp_ts_init()
1858 rc = efx->type->ptp_set_ts_config(efx, init); in efx_ptp_ts_init()
1862 efx->ptp_data->config = *init; in efx_ptp_ts_init()
1868 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_get_ts_info()
1869 struct efx_nic *primary = efx->primary; in efx_ptp_get_ts_info()
1876 ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | in efx_ptp_get_ts_info()
1883 struct efx_ef10_nic_data *nic_data = efx->nic_data; in efx_ptp_get_ts_info()
1885 if (!(nic_data->licensed_features & in efx_ptp_get_ts_info()
1887 ts_info->so_timestamping &= in efx_ptp_get_ts_info()
1890 if (primary && primary->ptp_data && primary->ptp_data->phc_clock) in efx_ptp_get_ts_info()
1891 ts_info->phc_index = in efx_ptp_get_ts_info()
1892 ptp_clock_index(primary->ptp_data->phc_clock); in efx_ptp_get_ts_info()
1893 ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; in efx_ptp_get_ts_info()
1894 ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; in efx_ptp_get_ts_info()
1903 if (!efx->ptp_data) in efx_ptp_set_ts_config()
1904 return -EOPNOTSUPP; in efx_ptp_set_ts_config()
1906 if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) in efx_ptp_set_ts_config()
1907 return -EFAULT; in efx_ptp_set_ts_config()
1913 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) in efx_ptp_set_ts_config()
1914 ? -EFAULT : 0; in efx_ptp_set_ts_config()
1919 if (!efx->ptp_data) in efx_ptp_get_ts_config()
1920 return -EOPNOTSUPP; in efx_ptp_get_ts_config()
1922 return copy_to_user(ifr->ifr_data, &efx->ptp_data->config, in efx_ptp_get_ts_config()
1923 sizeof(efx->ptp_data->config)) ? -EFAULT : 0; in efx_ptp_get_ts_config()
1928 struct efx_ptp_data *ptp = efx->ptp_data; in ptp_event_failure()
1930 netif_err(efx, hw, efx->net_dev, in ptp_event_failure()
1932 ptp->evt_frag_idx, expected_frag_len); in ptp_event_failure()
1933 ptp->reset_required = true; in ptp_event_failure()
1934 queue_work(ptp->workwq, &ptp->work); in ptp_event_failure()
1939 int code = EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA); in ptp_event_fault()
1940 if (ptp->evt_frag_idx != 1) { in ptp_event_fault()
1945 netif_err(efx, hw, efx->net_dev, "PTP error %d\n", code); in ptp_event_fault()
1950 if (ptp->nic_ts_enabled) in ptp_event_pps()
1951 queue_work(ptp->pps_workwq, &ptp->pps_work); in ptp_event_pps()
1956 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_event()
1960 if (!efx->ptp_warned) { in efx_ptp_event()
1961 netif_warn(efx, drv, efx->net_dev, in efx_ptp_event()
1963 efx->ptp_warned = true; in efx_ptp_event()
1968 if (!ptp->enabled) in efx_ptp_event()
1971 if (ptp->evt_frag_idx == 0) { in efx_ptp_event()
1972 ptp->evt_code = code; in efx_ptp_event()
1973 } else if (ptp->evt_code != code) { in efx_ptp_event()
1974 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
1976 ptp->evt_frag_idx = 0; in efx_ptp_event()
1979 ptp->evt_frags[ptp->evt_frag_idx++] = *ev; in efx_ptp_event()
1990 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
1994 ptp->evt_frag_idx = 0; in efx_ptp_event()
1995 } else if (MAX_EVENT_FRAGS == ptp->evt_frag_idx) { in efx_ptp_event()
1996 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
1998 ptp->evt_frag_idx = 0; in efx_ptp_event()
2004 struct efx_nic *efx = channel->efx; in efx_time_sync_event()
2005 struct efx_ptp_data *ptp = efx->ptp_data; in efx_time_sync_event()
2007 /* When extracting the sync timestamp minor value, we should discard in efx_time_sync_event()
2009 * to reconstruct full-range timestamps and they are optionally used in efx_time_sync_event()
2011 * for sync events. in efx_time_sync_event()
2013 channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR); in efx_time_sync_event()
2014 channel->sync_timestamp_minor = in efx_time_sync_event()
2016 << ptp->nic_time.sync_event_minor_shift; in efx_time_sync_event()
2018 /* if sync events have been disabled then we want to silently ignore in efx_time_sync_event()
2021 (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED, in efx_time_sync_event()
2028 return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset)); in efx_rx_buf_timestamp_minor()
2030 const u8 *data = eh + efx->rx_packet_ts_offset; in efx_rx_buf_timestamp_minor()
2041 struct efx_nic *efx = channel->efx; in __efx_rx_skb_attach_timestamp()
2042 struct efx_ptp_data *ptp = efx->ptp_data; in __efx_rx_skb_attach_timestamp()
2047 if (channel->sync_events_state != SYNC_EVENTS_VALID) in __efx_rx_skb_attach_timestamp()
2052 /* get the difference between the packet and sync timestamps, in __efx_rx_skb_attach_timestamp()
2055 diff = pkt_timestamp_minor - channel->sync_timestamp_minor; in __efx_rx_skb_attach_timestamp()
2056 if (pkt_timestamp_minor < channel->sync_timestamp_minor) in __efx_rx_skb_attach_timestamp()
2057 diff += ptp->nic_time.minor_max; in __efx_rx_skb_attach_timestamp()
2060 carry = (channel->sync_timestamp_minor >= ptp->nic_time.minor_max - diff) ? in __efx_rx_skb_attach_timestamp()
2063 if (diff <= ptp->nic_time.sync_event_diff_max) { in __efx_rx_skb_attach_timestamp()
2064 /* packet is ahead of the sync event by a quarter of a second or in __efx_rx_skb_attach_timestamp()
2067 pkt_timestamp_major = channel->sync_timestamp_major + carry; in __efx_rx_skb_attach_timestamp()
2068 } else if (diff >= ptp->nic_time.sync_event_diff_min) { in __efx_rx_skb_attach_timestamp()
2069 /* packet is behind the sync event but within the fuzz factor. in __efx_rx_skb_attach_timestamp()
2070 * This means the RX packet and sync event crossed as they were in __efx_rx_skb_attach_timestamp()
2073 pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry; in __efx_rx_skb_attach_timestamp()
2076 * indicative of us missing sync events for some reason, so in __efx_rx_skb_attach_timestamp()
2080 netif_vdbg(efx, drv, efx->net_dev, in __efx_rx_skb_attach_timestamp()
2081 "packet timestamp %x too far from sync event %x:%x\n", in __efx_rx_skb_attach_timestamp()
2082 pkt_timestamp_minor, channel->sync_timestamp_major, in __efx_rx_skb_attach_timestamp()
2083 channel->sync_timestamp_minor); in __efx_rx_skb_attach_timestamp()
2089 timestamps->hwtstamp = in __efx_rx_skb_attach_timestamp()
2090 ptp->nic_to_kernel_time(pkt_timestamp_major, in __efx_rx_skb_attach_timestamp()
2092 ptp->ts_corrections.general_rx); in __efx_rx_skb_attach_timestamp()
2101 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjfine()
2108 else if (delta < -MAX_PPB) in efx_phc_adjfine()
2109 delta = -MAX_PPB; in efx_phc_adjfine()
2113 (1 << (ptp_data->adjfreq_ppb_shift - 1))) >> in efx_phc_adjfine()
2114 ptp_data->adjfreq_ppb_shift; in efx_phc_adjfine()
2126 ptp_data->current_adjfreq = adjustment_ns; in efx_phc_adjfine()
2136 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjtime()
2139 efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor); in efx_phc_adjtime()
2143 MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); in efx_phc_adjtime()
2155 struct efx_nic *efx = ptp_data->efx; in efx_phc_gettime()
2169 kt = ptp_data->nic_to_kernel_time( in efx_phc_gettime()
2207 if (request->type != PTP_CLK_REQ_PPS) in efx_phc_enable()
2208 return -EOPNOTSUPP; in efx_phc_enable()
2210 ptp_data->nic_ts_enabled = !!enable; in efx_phc_enable()
2231 efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = in efx_ptp_defer_probe_with_channel()
2238 netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); in efx_ptp_start_datapath()
2239 /* re-enable timestamping if it was previously enabled */ in efx_ptp_start_datapath()
2240 if (efx->type->ptp_set_ts_sync_events) in efx_ptp_start_datapath()
2241 efx->type->ptp_set_ts_sync_events(efx, true, true); in efx_ptp_start_datapath()
2247 if (efx->type->ptp_set_ts_sync_events) in efx_ptp_stop_datapath()
2248 efx->type->ptp_set_ts_sync_events(efx, false, true); in efx_ptp_stop_datapath()