Lines Matching +full:rx +full:- +full:num +full:- +full:evt
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2011-2013 Solarflare Communications Inc.
128 #define PTP_ADDR_ETHER {0x01, 0x1b, 0x19, 0, 0, 0} /* 01-1B-19-00-00-00 */
149 #define MC_NANOSECOND_MASK ((1 << MC_NANOSECOND_BITS) - 1)
150 #define MC_SECOND_MASK ((1 << (32 - MC_NANOSECOND_BITS)) - 1)
152 /* Maximum parts-per-billion adjustment that is acceptable */
167 * struct efx_ptp_match - Matching structure, stored in sk_buff's cb area.
171 * @state: The state of the packet - whether it is ready for processing or
181 * struct efx_ptp_event_rx - A PTP receive event (from MC)
197 * struct efx_ptp_timeset - Synchronisation between host and MC
213 u32 window; /* Derived: end - start, allowing for wrap */
217 * struct efx_ptp_data - Precision Time Protocol (PTP) state
220 * @rx_ts_inline: Flag for whether RX timestamps are inline (else they are
233 * @rxfilters_count: Num of installed rxfilters, should be == PTP_RXFILTERS_LEN
267 * @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
372 return efx_ptp_use_mac_tx_timestamps(channel->efx); in efx_ptp_want_txqs()
390 PTP_MC_STAT(ptp_rx_timestamp_packets, RX),
397 [0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL,
402 if (!efx->ptp_data) in efx_ptp_describe_stats()
416 if (!efx->ptp_data) in efx_ptp_update_stats()
423 stats[i] = *(unsigned int *)((char *)efx->ptp_data + in efx_ptp_update_stats()
459 kt = ktime_sub_ns(kt, (u64)-correction); in efx_ptp_s_ns_to_ktime_correction()
469 #define NS_TO_S27_SHIFT (63 - S27_TO_NS_SHIFT)
473 * where the minor register only uses 27 bits in units of 2^-27s.
480 (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); in efx_ptp_ns_to_s27()
486 min -= S27_MINOR_MAX; in efx_ptp_ns_to_s27()
497 (1ULL << (S27_TO_NS_SHIFT - 1))) >> S27_TO_NS_SHIFT); in efx_ptp_s27_to_ktime()
508 nic_major--; in efx_ptp_s27_to_ktime_correction()
510 nic_minor -= S27_MINOR_MAX; in efx_ptp_s27_to_ktime_correction()
539 kt = ktime_sub_ns(kt, (u64)-correction); in efx_ptp_s_qns_to_ktime_correction()
545 return efx->ptp_data ? efx->ptp_data->channel : NULL; in efx_ptp_channel()
550 if (efx->ptp_data) in efx_ptp_update_channel()
551 efx->ptp_data->channel = channel; in efx_ptp_update_channel()
560 major = channel->sync_timestamp_major; in last_sync_timestamp_major()
565 * 48 bits long and provides meta-information in the top 2 bits.
592 * a - b = ((a mod k) - b) mod k in efx_ptp_mac_nic_to_ktime_correction()
594 * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know in efx_ptp_mac_nic_to_ktime_correction()
595 * (a mod k) and b, so can calculate the delta, a - b. in efx_ptp_mac_nic_to_ktime_correction()
606 delta = nic_major - sync_timestamp; in efx_ptp_mac_nic_to_ktime_correction()
613 kt = ptp->nic_to_kernel_time(nic_major, nic_minor, in efx_ptp_mac_nic_to_ktime_correction()
621 struct efx_nic *efx = tx_queue->efx; in efx_ptp_nic_to_kernel_time()
622 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_nic_to_kernel_time()
627 tx_queue->completed_timestamp_major, in efx_ptp_nic_to_kernel_time()
628 tx_queue->completed_timestamp_minor, in efx_ptp_nic_to_kernel_time()
629 ptp->ts_corrections.general_tx); in efx_ptp_nic_to_kernel_time()
631 kt = ptp->nic_to_kernel_time( in efx_ptp_nic_to_kernel_time()
632 tx_queue->completed_timestamp_major, in efx_ptp_nic_to_kernel_time()
633 tx_queue->completed_timestamp_minor, in efx_ptp_nic_to_kernel_time()
634 ptp->ts_corrections.general_tx); in efx_ptp_nic_to_kernel_time()
643 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_get_attributes()
658 } else if (rc == -EINVAL) { in efx_ptp_get_attributes()
660 } else if (rc == -EPERM) { in efx_ptp_get_attributes()
661 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_get_attributes()
671 ptp->ns_to_nic_time = efx_ptp_ns_to_s27; in efx_ptp_get_attributes()
672 ptp->nic_to_kernel_time = efx_ptp_s27_to_ktime_correction; in efx_ptp_get_attributes()
673 ptp->nic_time.minor_max = 1 << 27; in efx_ptp_get_attributes()
674 ptp->nic_time.sync_event_minor_shift = 19; in efx_ptp_get_attributes()
677 ptp->ns_to_nic_time = efx_ptp_ns_to_s_ns; in efx_ptp_get_attributes()
678 ptp->nic_to_kernel_time = efx_ptp_s_ns_to_ktime_correction; in efx_ptp_get_attributes()
679 ptp->nic_time.minor_max = 1000000000; in efx_ptp_get_attributes()
680 ptp->nic_time.sync_event_minor_shift = 22; in efx_ptp_get_attributes()
683 ptp->ns_to_nic_time = efx_ptp_ns_to_s_qns; in efx_ptp_get_attributes()
684 ptp->nic_to_kernel_time = efx_ptp_s_qns_to_ktime_correction; in efx_ptp_get_attributes()
685 ptp->nic_time.minor_max = 4000000000UL; in efx_ptp_get_attributes()
686 ptp->nic_time.sync_event_minor_shift = 24; in efx_ptp_get_attributes()
689 return -ERANGE; in efx_ptp_get_attributes()
698 ptp->nic_time.sync_event_diff_min = ptp->nic_time.minor_max in efx_ptp_get_attributes()
699 - (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
700 ptp->nic_time.sync_event_diff_max = (ptp->nic_time.minor_max / 4) in efx_ptp_get_attributes()
701 + (ptp->nic_time.minor_max / 10); in efx_ptp_get_attributes()
712 ptp->min_synchronisation_ns = in efx_ptp_get_attributes()
716 ptp->min_synchronisation_ns = DEFAULT_MIN_SYNCHRONISATION_NS; in efx_ptp_get_attributes()
720 ptp->capabilities = MCDI_DWORD(outbuf, in efx_ptp_get_attributes()
723 ptp->capabilities = 0; in efx_ptp_get_attributes()
726 * adjustments in parts-per-billion and the fixed-point in efx_ptp_get_attributes()
729 if (ptp->capabilities & (1 << MC_CMD_PTP_OUT_GET_ATTRIBUTES_FP44_FREQ_ADJ_LBN)) in efx_ptp_get_attributes()
730 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP44; in efx_ptp_get_attributes()
732 ptp->adjfreq_ppb_shift = PPB_SHIFT_FP40; in efx_ptp_get_attributes()
755 efx->ptp_data->ts_corrections.ptp_tx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
757 efx->ptp_data->ts_corrections.ptp_rx = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
759 efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
761 efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf, in efx_ptp_get_timestamp_corrections()
765 efx->ptp_data->ts_corrections.general_tx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
768 efx->ptp_data->ts_corrections.general_rx = MCDI_DWORD( in efx_ptp_get_timestamp_corrections()
772 efx->ptp_data->ts_corrections.general_tx = in efx_ptp_get_timestamp_corrections()
773 efx->ptp_data->ts_corrections.ptp_tx; in efx_ptp_get_timestamp_corrections()
774 efx->ptp_data->ts_corrections.general_rx = in efx_ptp_get_timestamp_corrections()
775 efx->ptp_data->ts_corrections.ptp_rx; in efx_ptp_get_timestamp_corrections()
777 } else if (rc == -EINVAL) { in efx_ptp_get_timestamp_corrections()
778 efx->ptp_data->ts_corrections.ptp_tx = 0; in efx_ptp_get_timestamp_corrections()
779 efx->ptp_data->ts_corrections.ptp_rx = 0; in efx_ptp_get_timestamp_corrections()
780 efx->ptp_data->ts_corrections.pps_out = 0; in efx_ptp_get_timestamp_corrections()
781 efx->ptp_data->ts_corrections.pps_in = 0; in efx_ptp_get_timestamp_corrections()
782 efx->ptp_data->ts_corrections.general_tx = 0; in efx_ptp_get_timestamp_corrections()
783 efx->ptp_data->ts_corrections.general_rx = 0; in efx_ptp_get_timestamp_corrections()
803 efx->ptp_data->channel ? in efx_ptp_enable()
804 efx->ptp_data->channel->channel : 0); in efx_ptp_enable()
805 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); in efx_ptp_enable()
809 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_enable()
819 * Note that this function should never rely on the presence of ptp_data -
832 rc = (rc == -EALREADY) ? 0 : rc; in efx_ptp_disable()
836 if (rc == -ENOSYS || rc == -EPERM) in efx_ptp_disable()
837 pci_info(efx->pci_dev, "no PTP support\n"); in efx_ptp_disable()
858 netif_err(efx, drv, efx->net_dev, in efx_ptp_handle_no_channel()
859 "ERROR: PTP requires MSI-X and 1 additional interrupt" in efx_ptp_handle_no_channel()
871 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_send_times()
872 int *mc_running = ptp->start.addr; in efx_ptp_send_times()
896 efx->type->ptp_write_host_time(efx, host_time); in efx_ptp_send_times()
907 timeset->host_start = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTSTART); in efx_ptp_read_timeset()
908 timeset->major = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MAJOR); in efx_ptp_read_timeset()
909 timeset->minor = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_MINOR); in efx_ptp_read_timeset()
910 timeset->host_end = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_HOSTEND), in efx_ptp_read_timeset()
911 timeset->wait = MCDI_DWORD(data, PTP_OUT_SYNCHRONIZE_WAITNS); in efx_ptp_read_timeset()
914 start_ns = timeset->host_start & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
915 end_ns = timeset->host_end & MC_NANOSECOND_MASK; in efx_ptp_read_timeset()
920 timeset->window = end_ns - start_ns; in efx_ptp_read_timeset()
927 * too much greater than this are rejected - the machine is, perhaps, too
942 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_times()
949 return -EAGAIN; in efx_ptp_process_times()
951 /* Read the set of results and find the last good host-MC in efx_ptp_process_times()
964 &ptp->timeset[i]); in efx_ptp_process_times()
967 ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); in efx_ptp_process_times()
968 window = ptp->timeset[i].window; in efx_ptp_process_times()
969 corrected = window - wait.tv_nsec; in efx_ptp_process_times()
981 ++ptp->invalid_sync_windows; in efx_ptp_process_times()
983 ++ptp->oversize_sync_windows; in efx_ptp_process_times()
984 } else if (corrected < ptp->min_synchronisation_ns) { in efx_ptp_process_times()
985 ++ptp->undersize_sync_windows; in efx_ptp_process_times()
993 netif_warn(efx, drv, efx->net_dev, in efx_ptp_process_times()
995 return -EAGAIN; in efx_ptp_process_times()
1004 start_sec = ptp->timeset[last_good].host_start >> MC_NANOSECOND_BITS; in efx_ptp_process_times()
1005 last_sec = last_time->ts_real.tv_sec & MC_SECOND_MASK; in efx_ptp_process_times()
1008 netif_warn(efx, hw, efx->net_dev, in efx_ptp_process_times()
1010 return -EAGAIN; in efx_ptp_process_times()
1012 delta.tv_sec = (last_sec - start_sec) & 1; in efx_ptp_process_times()
1014 last_time->ts_real.tv_nsec - in efx_ptp_process_times()
1015 (ptp->timeset[last_good].host_start & MC_NANOSECOND_MASK); in efx_ptp_process_times()
1018 * No correction is required - this time is the output of a in efx_ptp_process_times()
1021 mc_time = ptp->nic_to_kernel_time(ptp->timeset[last_good].major, in efx_ptp_process_times()
1022 ptp->timeset[last_good].minor, 0); in efx_ptp_process_times()
1028 ptp->host_time_pps = *last_time; in efx_ptp_process_times()
1029 pps_sub_ts(&ptp->host_time_pps, delta); in efx_ptp_process_times()
1037 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_synchronize()
1044 int *start = ptp->start.addr; in efx_ptp_synchronize()
1051 ptp->start.dma_addr); in efx_ptp_synchronize()
1067 ++ptp->fast_syncs; in efx_ptp_synchronize()
1069 ++ptp->sync_timeouts; in efx_ptp_synchronize()
1083 ++ptp->good_syncs; in efx_ptp_synchronize()
1085 ++ptp->no_time_syncs; in efx_ptp_synchronize()
1092 ++ptp->bad_syncs; in efx_ptp_synchronize()
1100 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_queue()
1104 tx_queue = efx_channel_get_tx_queue(ptp_data->channel, type); in efx_ptp_xmit_skb_queue()
1105 if (tx_queue && tx_queue->timestamping) { in efx_ptp_xmit_skb_queue()
1113 * Although it is theoretically safe for current PTP TX/RX code in efx_ptp_xmit_skb_queue()
1117 * 1) The code invoked is mainly implemented for non-PTP in efx_ptp_xmit_skb_queue()
1138 struct efx_ptp_data *ptp_data = efx->ptp_data; in efx_ptp_xmit_skb_mc()
1140 int rc = -EIO; in efx_ptp_xmit_skb_mc()
1144 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT); in efx_ptp_xmit_skb_mc()
1145 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_PERIPH_ID, 0); in efx_ptp_xmit_skb_mc()
1146 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len); in efx_ptp_xmit_skb_mc()
1147 if (skb_shinfo(skb)->nr_frags != 0) { in efx_ptp_xmit_skb_mc()
1153 if (skb->ip_summed == CHECKSUM_PARTIAL) { in efx_ptp_xmit_skb_mc()
1159 MCDI_PTR(ptp_data->txbuf, in efx_ptp_xmit_skb_mc()
1161 skb->len); in efx_ptp_xmit_skb_mc()
1163 ptp_data->txbuf, MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len), in efx_ptp_xmit_skb_mc()
1169 timestamps.hwtstamp = ptp_data->nic_to_kernel_time( in efx_ptp_xmit_skb_mc()
1172 ptp_data->ts_corrections.ptp_tx); in efx_ptp_xmit_skb_mc()
1186 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_drop_time_expired_events()
1190 if (ptp->rx_ts_inline) in efx_ptp_drop_time_expired_events()
1193 /* Drop time-expired events */ in efx_ptp_drop_time_expired_events()
1194 spin_lock_bh(&ptp->evt_lock); in efx_ptp_drop_time_expired_events()
1195 list_for_each_safe(cursor, next, &ptp->evt_list) { in efx_ptp_drop_time_expired_events()
1196 struct efx_ptp_event_rx *evt; in efx_ptp_drop_time_expired_events() local
1198 evt = list_entry(cursor, struct efx_ptp_event_rx, in efx_ptp_drop_time_expired_events()
1200 if (time_after(jiffies, evt->expiry)) { in efx_ptp_drop_time_expired_events()
1201 list_move(&evt->link, &ptp->evt_free_list); in efx_ptp_drop_time_expired_events()
1202 netif_warn(efx, hw, efx->net_dev, in efx_ptp_drop_time_expired_events()
1203 "PTP rx event dropped\n"); in efx_ptp_drop_time_expired_events()
1206 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_drop_time_expired_events()
1212 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_match_rx()
1219 WARN_ON_ONCE(ptp->rx_ts_inline); in efx_ptp_match_rx()
1221 spin_lock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1222 evts_waiting = !list_empty(&ptp->evt_list); in efx_ptp_match_rx()
1223 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1228 match = (struct efx_ptp_match *)skb->cb; in efx_ptp_match_rx()
1230 spin_lock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1231 list_for_each_safe(cursor, next, &ptp->evt_list) { in efx_ptp_match_rx()
1232 struct efx_ptp_event_rx *evt; in efx_ptp_match_rx() local
1234 evt = list_entry(cursor, struct efx_ptp_event_rx, link); in efx_ptp_match_rx()
1235 if ((evt->seq0 == match->words[0]) && in efx_ptp_match_rx()
1236 (evt->seq1 == match->words[1])) { in efx_ptp_match_rx()
1239 /* Match - add in hardware timestamp */ in efx_ptp_match_rx()
1241 timestamps->hwtstamp = evt->hwtimestamp; in efx_ptp_match_rx()
1243 match->state = PTP_PACKET_STATE_MATCHED; in efx_ptp_match_rx()
1245 list_move(&evt->link, &ptp->evt_free_list); in efx_ptp_match_rx()
1249 spin_unlock_bh(&ptp->evt_lock); in efx_ptp_match_rx()
1260 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_process_events()
1263 while ((skb = skb_dequeue(&ptp->rxq))) { in efx_ptp_process_events()
1266 match = (struct efx_ptp_match *)skb->cb; in efx_ptp_process_events()
1267 if (match->state == PTP_PACKET_STATE_MATCH_UNWANTED) { in efx_ptp_process_events()
1272 } else if (time_after(jiffies, match->expiry)) { in efx_ptp_process_events()
1273 match->state = PTP_PACKET_STATE_TIMED_OUT; in efx_ptp_process_events()
1274 ++ptp->rx_no_timestamp; in efx_ptp_process_events()
1278 skb_queue_head(&ptp->rxq, skb); in efx_ptp_process_events()
1294 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_remove_multicast_filters()
1296 while (ptp->rxfilters_count) { in efx_ptp_remove_multicast_filters()
1297 ptp->rxfilters_count--; in efx_ptp_remove_multicast_filters()
1299 ptp->rxfilters[ptp->rxfilters_count]); in efx_ptp_remove_multicast_filters()
1306 struct efx_channel *channel = efx->ptp_data->channel; in efx_ptp_init_filter()
1316 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_filter()
1321 ptp->rxfilters[ptp->rxfilters_count] = rc; in efx_ptp_insert_filter()
1322 ptp->rxfilters_count++; in efx_ptp_insert_filter()
1360 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_insert_multicast_filters()
1363 if (!ptp->channel || ptp->rxfilters_count) in efx_ptp_insert_multicast_filters()
1367 * that there is no packet re-ordering. in efx_ptp_insert_multicast_filters()
1403 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_start()
1406 ptp->reset_required = false; in efx_ptp_start()
1416 ptp->evt_frag_idx = 0; in efx_ptp_start()
1417 ptp->current_adjfreq = 0; in efx_ptp_start()
1428 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_stop()
1440 /* Make sure RX packets are really delivered */ in efx_ptp_stop()
1441 efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq); in efx_ptp_stop()
1442 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_stop()
1445 spin_lock_bh(&efx->ptp_data->evt_lock); in efx_ptp_stop()
1446 list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) { in efx_ptp_stop()
1447 list_move(cursor, &efx->ptp_data->evt_free_list); in efx_ptp_stop()
1449 spin_unlock_bh(&efx->ptp_data->evt_lock); in efx_ptp_stop()
1456 if (efx->ptp_data && efx->ptp_data->enabled) in efx_ptp_restart()
1465 struct efx_nic *efx = ptp->efx; in efx_ptp_pps_worker()
1472 ptp_evt.pps_times = ptp->host_time_pps; in efx_ptp_pps_worker()
1473 ptp_clock_event(ptp->phc_clock, &ptp_evt); in efx_ptp_pps_worker()
1480 struct efx_nic *efx = ptp_data->efx; in efx_ptp_worker()
1484 if (ptp_data->reset_required) { in efx_ptp_worker()
1495 while ((skb = skb_dequeue(&ptp_data->txq))) in efx_ptp_worker()
1496 ptp_data->xmit_skb(efx, skb); in efx_ptp_worker()
1525 if (efx->ptp_data) { in efx_ptp_probe()
1526 efx->ptp_data->channel = channel; in efx_ptp_probe()
1531 efx->ptp_data = ptp; in efx_ptp_probe()
1532 if (!efx->ptp_data) in efx_ptp_probe()
1533 return -ENOMEM; in efx_ptp_probe()
1535 ptp->efx = efx; in efx_ptp_probe()
1536 ptp->channel = channel; in efx_ptp_probe()
1537 ptp->rx_ts_inline = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; in efx_ptp_probe()
1539 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); in efx_ptp_probe()
1543 skb_queue_head_init(&ptp->rxq); in efx_ptp_probe()
1544 skb_queue_head_init(&ptp->txq); in efx_ptp_probe()
1545 ptp->workwq = create_singlethread_workqueue("sfc_ptp"); in efx_ptp_probe()
1546 if (!ptp->workwq) { in efx_ptp_probe()
1547 rc = -ENOMEM; in efx_ptp_probe()
1552 ptp->xmit_skb = efx_ptp_xmit_skb_queue; in efx_ptp_probe()
1554 channel->sync_events_state = SYNC_EVENTS_QUIESCENT; in efx_ptp_probe()
1556 ptp->xmit_skb = efx_ptp_xmit_skb_mc; in efx_ptp_probe()
1559 INIT_WORK(&ptp->work, efx_ptp_worker); in efx_ptp_probe()
1560 ptp->config.flags = 0; in efx_ptp_probe()
1561 ptp->config.tx_type = HWTSTAMP_TX_OFF; in efx_ptp_probe()
1562 ptp->config.rx_filter = HWTSTAMP_FILTER_NONE; in efx_ptp_probe()
1563 INIT_LIST_HEAD(&ptp->evt_list); in efx_ptp_probe()
1564 INIT_LIST_HEAD(&ptp->evt_free_list); in efx_ptp_probe()
1565 spin_lock_init(&ptp->evt_lock); in efx_ptp_probe()
1567 list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list); in efx_ptp_probe()
1579 if (efx->mcdi->fn_flags & in efx_ptp_probe()
1581 ptp->phc_clock_info = efx_phc_clock_info; in efx_ptp_probe()
1582 ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, in efx_ptp_probe()
1583 &efx->pci_dev->dev); in efx_ptp_probe()
1584 if (IS_ERR(ptp->phc_clock)) { in efx_ptp_probe()
1585 rc = PTR_ERR(ptp->phc_clock); in efx_ptp_probe()
1587 } else if (ptp->phc_clock) { in efx_ptp_probe()
1588 INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); in efx_ptp_probe()
1589 ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); in efx_ptp_probe()
1590 if (!ptp->pps_workwq) { in efx_ptp_probe()
1591 rc = -ENOMEM; in efx_ptp_probe()
1596 ptp->nic_ts_enabled = false; in efx_ptp_probe()
1600 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_probe()
1603 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_probe()
1606 efx_nic_free_buffer(efx, &ptp->start); in efx_ptp_probe()
1609 kfree(efx->ptp_data); in efx_ptp_probe()
1610 efx->ptp_data = NULL; in efx_ptp_probe()
1622 struct efx_nic *efx = channel->efx; in efx_ptp_probe_channel()
1625 channel->irq_moderation_us = 0; in efx_ptp_probe_channel()
1626 channel->rx_queue.core_index = 0; in efx_ptp_probe_channel()
1634 if (rc && rc != -EPERM) in efx_ptp_probe_channel()
1635 netif_warn(efx, drv, efx->net_dev, in efx_ptp_probe_channel()
1642 if (!efx->ptp_data) in efx_ptp_remove()
1647 cancel_work_sync(&efx->ptp_data->work); in efx_ptp_remove()
1648 if (efx->ptp_data->pps_workwq) in efx_ptp_remove()
1649 cancel_work_sync(&efx->ptp_data->pps_work); in efx_ptp_remove()
1651 skb_queue_purge(&efx->ptp_data->rxq); in efx_ptp_remove()
1652 skb_queue_purge(&efx->ptp_data->txq); in efx_ptp_remove()
1654 if (efx->ptp_data->phc_clock) { in efx_ptp_remove()
1655 destroy_workqueue(efx->ptp_data->pps_workwq); in efx_ptp_remove()
1656 ptp_clock_unregister(efx->ptp_data->phc_clock); in efx_ptp_remove()
1659 destroy_workqueue(efx->ptp_data->workwq); in efx_ptp_remove()
1661 efx_nic_free_buffer(efx, &efx->ptp_data->start); in efx_ptp_remove()
1662 kfree(efx->ptp_data); in efx_ptp_remove()
1663 efx->ptp_data = NULL; in efx_ptp_remove()
1668 efx_ptp_remove(channel->efx); in efx_ptp_remove_channel()
1674 snprintf(buf, len, "%s-ptp", channel->efx->name); in efx_ptp_get_channel_name()
1682 return efx->ptp_data && in efx_ptp_is_ptp_tx()
1683 efx->ptp_data->enabled && in efx_ptp_is_ptp_tx()
1684 skb->len >= PTP_MIN_LENGTH && in efx_ptp_is_ptp_tx()
1685 skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM && in efx_ptp_is_ptp_tx()
1686 likely(skb->protocol == htons(ETH_P_IP)) && in efx_ptp_is_ptp_tx()
1689 ip_hdr(skb)->protocol == IPPROTO_UDP && in efx_ptp_is_ptp_tx()
1692 udp_hdr(skb)->dest == htons(PTP_EVENT_PORT); in efx_ptp_is_ptp_tx()
1696 * the receive timestamp from the MC - this will probably occur after the
1701 struct efx_nic *efx = channel->efx; in efx_ptp_rx()
1702 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_rx()
1703 struct efx_ptp_match *match = (struct efx_ptp_match *)skb->cb; in efx_ptp_rx()
1708 match->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); in efx_ptp_rx()
1711 if (ptp->mode == MC_CMD_PTP_MODE_V1) { in efx_ptp_rx()
1715 data = skb->data; in efx_ptp_rx()
1730 data = skb->data; in efx_ptp_rx()
1736 /* The original V2 implementation uses bytes 2-7 of in efx_ptp_rx()
1740 * enhanced mode fixes this issue and uses bytes 0-2 in efx_ptp_rx()
1741 * and byte 5-7 of the UUID. in efx_ptp_rx()
1744 if (ptp->mode == MC_CMD_PTP_MODE_V2) { in efx_ptp_rx()
1748 BUG_ON(ptp->mode != MC_CMD_PTP_MODE_V2_ENHANCED); in efx_ptp_rx()
1754 match->state = PTP_PACKET_STATE_UNMATCHED; in efx_ptp_rx()
1763 match->words[0] = (match_data_012[0] | in efx_ptp_rx()
1767 match->words[1] = (match_data_345[1] | in efx_ptp_rx()
1770 PTP_V1_SEQUENCE_LENGTH - 1] << in efx_ptp_rx()
1773 match->state = PTP_PACKET_STATE_MATCH_UNWANTED; in efx_ptp_rx()
1776 skb_queue_tail(&ptp->rxq, skb); in efx_ptp_rx()
1777 queue_work(ptp->workwq, &ptp->work); in efx_ptp_rx()
1788 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_tx()
1790 skb_queue_tail(&ptp->txq, skb); in efx_ptp_tx()
1792 if ((udp_hdr(skb)->dest == htons(PTP_EVENT_PORT)) && in efx_ptp_tx()
1793 (skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM)) in efx_ptp_tx()
1795 queue_work(ptp->workwq, &ptp->work); in efx_ptp_tx()
1802 return efx->ptp_data->mode; in efx_ptp_get_mode()
1808 if ((enable_wanted != efx->ptp_data->enabled) || in efx_ptp_change_mode()
1809 (enable_wanted && (efx->ptp_data->mode != new_mode))) { in efx_ptp_change_mode()
1814 if (efx->ptp_data->enabled && in efx_ptp_change_mode()
1815 (efx->ptp_data->mode != new_mode)) { in efx_ptp_change_mode()
1816 efx->ptp_data->enabled = false; in efx_ptp_change_mode()
1826 efx->ptp_data->mode = new_mode; in efx_ptp_change_mode()
1827 if (netif_running(efx->net_dev)) in efx_ptp_change_mode()
1842 efx->ptp_data->enabled = enable_wanted; in efx_ptp_change_mode()
1852 if ((init->tx_type != HWTSTAMP_TX_OFF) && in efx_ptp_ts_init()
1853 (init->tx_type != HWTSTAMP_TX_ON)) in efx_ptp_ts_init()
1854 return -ERANGE; in efx_ptp_ts_init()
1856 rc = efx->type->ptp_set_ts_config(efx, init); in efx_ptp_ts_init()
1860 efx->ptp_data->config = *init; in efx_ptp_ts_init()
1866 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_get_ts_info()
1867 struct efx_nic *primary = efx->primary; in efx_ptp_get_ts_info()
1874 ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | in efx_ptp_get_ts_info()
1881 struct efx_ef10_nic_data *nic_data = efx->nic_data; in efx_ptp_get_ts_info()
1883 if (!(nic_data->licensed_features & in efx_ptp_get_ts_info()
1885 ts_info->so_timestamping &= in efx_ptp_get_ts_info()
1888 if (primary && primary->ptp_data && primary->ptp_data->phc_clock) in efx_ptp_get_ts_info()
1889 ts_info->phc_index = in efx_ptp_get_ts_info()
1890 ptp_clock_index(primary->ptp_data->phc_clock); in efx_ptp_get_ts_info()
1891 ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; in efx_ptp_get_ts_info()
1892 ts_info->rx_filters = ptp->efx->type->hwtstamp_filters; in efx_ptp_get_ts_info()
1901 if (!efx->ptp_data) in efx_ptp_set_ts_config()
1902 return -EOPNOTSUPP; in efx_ptp_set_ts_config()
1904 if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) in efx_ptp_set_ts_config()
1905 return -EFAULT; in efx_ptp_set_ts_config()
1911 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) in efx_ptp_set_ts_config()
1912 ? -EFAULT : 0; in efx_ptp_set_ts_config()
1917 if (!efx->ptp_data) in efx_ptp_get_ts_config()
1918 return -EOPNOTSUPP; in efx_ptp_get_ts_config()
1920 return copy_to_user(ifr->ifr_data, &efx->ptp_data->config, in efx_ptp_get_ts_config()
1921 sizeof(efx->ptp_data->config)) ? -EFAULT : 0; in efx_ptp_get_ts_config()
1926 struct efx_ptp_data *ptp = efx->ptp_data; in ptp_event_failure()
1928 netif_err(efx, hw, efx->net_dev, in ptp_event_failure()
1930 ptp->evt_frag_idx, expected_frag_len); in ptp_event_failure()
1931 ptp->reset_required = true; in ptp_event_failure()
1932 queue_work(ptp->workwq, &ptp->work); in ptp_event_failure()
1941 struct efx_ptp_event_rx *evt = NULL; in ptp_event_rx() local
1943 if (WARN_ON_ONCE(ptp->rx_ts_inline)) in ptp_event_rx()
1946 if (ptp->evt_frag_idx != 3) { in ptp_event_rx()
1951 spin_lock_bh(&ptp->evt_lock); in ptp_event_rx()
1952 if (!list_empty(&ptp->evt_free_list)) { in ptp_event_rx()
1953 evt = list_first_entry(&ptp->evt_free_list, in ptp_event_rx()
1955 list_del(&evt->link); in ptp_event_rx()
1957 evt->seq0 = EFX_QWORD_FIELD(ptp->evt_frags[2], MCDI_EVENT_DATA); in ptp_event_rx()
1958 evt->seq1 = (EFX_QWORD_FIELD(ptp->evt_frags[2], in ptp_event_rx()
1960 (EFX_QWORD_FIELD(ptp->evt_frags[1], in ptp_event_rx()
1962 (EFX_QWORD_FIELD(ptp->evt_frags[0], in ptp_event_rx()
1964 evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time( in ptp_event_rx()
1965 EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA), in ptp_event_rx()
1966 EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA), in ptp_event_rx()
1967 ptp->ts_corrections.ptp_rx); in ptp_event_rx()
1968 evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS); in ptp_event_rx()
1969 list_add_tail(&evt->link, &ptp->evt_list); in ptp_event_rx()
1971 queue_work(ptp->workwq, &ptp->work); in ptp_event_rx()
1973 /* Log a rate-limited warning message. */ in ptp_event_rx()
1974 netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n"); in ptp_event_rx()
1976 spin_unlock_bh(&ptp->evt_lock); in ptp_event_rx()
1981 int code = EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA); in ptp_event_fault()
1982 if (ptp->evt_frag_idx != 1) { in ptp_event_fault()
1987 netif_err(efx, hw, efx->net_dev, "PTP error %d\n", code); in ptp_event_fault()
1992 if (ptp->nic_ts_enabled) in ptp_event_pps()
1993 queue_work(ptp->pps_workwq, &ptp->pps_work); in ptp_event_pps()
1998 struct efx_ptp_data *ptp = efx->ptp_data; in efx_ptp_event()
2002 if (!efx->ptp_warned) { in efx_ptp_event()
2003 netif_warn(efx, drv, efx->net_dev, in efx_ptp_event()
2005 efx->ptp_warned = true; in efx_ptp_event()
2010 if (!ptp->enabled) in efx_ptp_event()
2013 if (ptp->evt_frag_idx == 0) { in efx_ptp_event()
2014 ptp->evt_code = code; in efx_ptp_event()
2015 } else if (ptp->evt_code != code) { in efx_ptp_event()
2016 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
2018 ptp->evt_frag_idx = 0; in efx_ptp_event()
2021 ptp->evt_frags[ptp->evt_frag_idx++] = *ev; in efx_ptp_event()
2035 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
2039 ptp->evt_frag_idx = 0; in efx_ptp_event()
2040 } else if (MAX_EVENT_FRAGS == ptp->evt_frag_idx) { in efx_ptp_event()
2041 netif_err(efx, hw, efx->net_dev, in efx_ptp_event()
2043 ptp->evt_frag_idx = 0; in efx_ptp_event()
2049 struct efx_nic *efx = channel->efx; in efx_time_sync_event()
2050 struct efx_ptp_data *ptp = efx->ptp_data; in efx_time_sync_event()
2054 * to reconstruct full-range timestamps and they are optionally used in efx_time_sync_event()
2058 channel->sync_timestamp_major = MCDI_EVENT_FIELD(*ev, PTP_TIME_MAJOR); in efx_time_sync_event()
2059 channel->sync_timestamp_minor = in efx_time_sync_event()
2061 << ptp->nic_time.sync_event_minor_shift; in efx_time_sync_event()
2066 (void) cmpxchg(&channel->sync_events_state, SYNC_EVENTS_REQUESTED, in efx_time_sync_event()
2073 return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_ts_offset)); in efx_rx_buf_timestamp_minor()
2075 const u8 *data = eh + efx->rx_packet_ts_offset; in efx_rx_buf_timestamp_minor()
2086 struct efx_nic *efx = channel->efx; in __efx_rx_skb_attach_timestamp()
2087 struct efx_ptp_data *ptp = efx->ptp_data; in __efx_rx_skb_attach_timestamp()
2092 if (channel->sync_events_state != SYNC_EVENTS_VALID) in __efx_rx_skb_attach_timestamp()
2100 diff = pkt_timestamp_minor - channel->sync_timestamp_minor; in __efx_rx_skb_attach_timestamp()
2101 if (pkt_timestamp_minor < channel->sync_timestamp_minor) in __efx_rx_skb_attach_timestamp()
2102 diff += ptp->nic_time.minor_max; in __efx_rx_skb_attach_timestamp()
2105 carry = (channel->sync_timestamp_minor >= ptp->nic_time.minor_max - diff) ? in __efx_rx_skb_attach_timestamp()
2108 if (diff <= ptp->nic_time.sync_event_diff_max) { in __efx_rx_skb_attach_timestamp()
2112 pkt_timestamp_major = channel->sync_timestamp_major + carry; in __efx_rx_skb_attach_timestamp()
2113 } else if (diff >= ptp->nic_time.sync_event_diff_min) { in __efx_rx_skb_attach_timestamp()
2115 * This means the RX packet and sync event crossed as they were in __efx_rx_skb_attach_timestamp()
2118 pkt_timestamp_major = channel->sync_timestamp_major - 1 + carry; in __efx_rx_skb_attach_timestamp()
2125 netif_vdbg(efx, drv, efx->net_dev, in __efx_rx_skb_attach_timestamp()
2127 pkt_timestamp_minor, channel->sync_timestamp_major, in __efx_rx_skb_attach_timestamp()
2128 channel->sync_timestamp_minor); in __efx_rx_skb_attach_timestamp()
2134 timestamps->hwtstamp = in __efx_rx_skb_attach_timestamp()
2135 ptp->nic_to_kernel_time(pkt_timestamp_major, in __efx_rx_skb_attach_timestamp()
2137 ptp->ts_corrections.general_rx); in __efx_rx_skb_attach_timestamp()
2145 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjfreq()
2152 else if (delta < -MAX_PPB) in efx_phc_adjfreq()
2153 delta = -MAX_PPB; in efx_phc_adjfreq()
2157 (1 << (ptp_data->adjfreq_ppb_shift - 1))) >> in efx_phc_adjfreq()
2158 ptp_data->adjfreq_ppb_shift; in efx_phc_adjfreq()
2170 ptp_data->current_adjfreq = adjustment_ns; in efx_phc_adjfreq()
2180 struct efx_nic *efx = ptp_data->efx; in efx_phc_adjtime()
2183 efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor); in efx_phc_adjtime()
2187 MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq); in efx_phc_adjtime()
2199 struct efx_nic *efx = ptp_data->efx; in efx_phc_gettime()
2213 kt = ptp_data->nic_to_kernel_time( in efx_phc_gettime()
2251 if (request->type != PTP_CLK_REQ_PPS) in efx_phc_enable()
2252 return -EOPNOTSUPP; in efx_phc_enable()
2254 ptp_data->nic_ts_enabled = !!enable; in efx_phc_enable()
2275 efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] = in efx_ptp_defer_probe_with_channel()
2282 netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n"); in efx_ptp_start_datapath()
2283 /* re-enable timestamping if it was previously enabled */ in efx_ptp_start_datapath()
2284 if (efx->type->ptp_set_ts_sync_events) in efx_ptp_start_datapath()
2285 efx->type->ptp_set_ts_sync_events(efx, true, true); in efx_ptp_start_datapath()
2291 if (efx->type->ptp_set_ts_sync_events) in efx_ptp_stop_datapath()
2292 efx->type->ptp_set_ts_sync_events(efx, false, true); in efx_ptp_stop_datapath()