linux/drivers/net/ethernet/sfc/ptp.c

// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
 * Driver for Solarflare network controllers and boards
 * Copyright 2011-2013 Solarflare Communications Inc.
 */

/* Theory of operation:
 *
 * PTP support is assisted by firmware running on the MC, which provides
 * the hardware timestamping capabilities.  Both transmitted and received
 * PTP event packets are queued onto internal queues for subsequent processing;
 * this is because the MC operations are relatively long and would block
 * block NAPI/interrupt operation.
 *
 * Receive event processing:
 *	The event contains the packet's UUID and sequence number, together
 *	with the hardware timestamp.  The PTP receive packet queue is searched
 *	for this UUID/sequence number and, if found, put on a pending queue.
 *	Packets not matching are delivered without timestamps (MCDI events will
 *	always arrive after the actual packet).
 *	It is important for the operation of the PTP protocol that the ordering
 *	of packets between the event and general port is maintained.
 *
 * Work queue processing:
 *	If work waiting, synchronise host/hardware time
 *
 *	Transmit: send packet through MC, which returns the transmission time
 *	that is converted to an appropriate timestamp.
 *
 *	Receive: the packet's reception time is converted to an appropriate
 *	timestamp.
 */
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/pps_kernel.h>
#include <linux/ptp_clock_kernel.h>
#include "net_driver.h"
#include "efx.h"
#include "mcdi.h"
#include "mcdi_pcol.h"
#include "io.h"
#include "tx.h"
#include "nic.h" /* indirectly includes ptp.h */
#include "efx_channels.h"

/* Maximum number of events expected to make up a PTP event */
#define MAX_EVENT_FRAGS

/* Maximum delay, ms, to begin synchronisation */
#define MAX_SYNCHRONISE_WAIT_MS

/* How long, at most, to spend synchronising */
#define SYNCHRONISE_PERIOD_NS

/* How often to update the shared memory time */
#define SYNCHRONISATION_GRANULARITY_NS

/* Minimum permitted length of a (corrected) synchronisation time */
#define DEFAULT_MIN_SYNCHRONISATION_NS

/* Maximum permitted length of a (corrected) synchronisation time */
#define MAX_SYNCHRONISATION_NS

/* How many (MC) receive events that can be queued */
#define MAX_RECEIVE_EVENTS

/* Length of (modified) moving average. */
#define AVERAGE_LENGTH

/* How long an unmatched event or packet can be held */
#define PKT_EVENT_LIFETIME_MS

/* How long unused unicast filters can be held */
#define UCAST_FILTER_EXPIRY_JIFFIES

/* Offsets into PTP packet for identification.  These offsets are from the
 * start of the IP header, not the MAC header.  Note that neither PTP V1 nor
 * PTP V2 permit the use of IPV4 options.
 */
#define PTP_DPORT_OFFSET

#define PTP_V1_VERSION_LENGTH
#define PTP_V1_VERSION_OFFSET

#define PTP_V1_SEQUENCE_LENGTH
#define PTP_V1_SEQUENCE_OFFSET

/* The minimum length of a PTP V1 packet for offsets, etc. to be valid:
 * includes IP header.
 */
#define PTP_V1_MIN_LENGTH

#define PTP_V2_VERSION_LENGTH
#define PTP_V2_VERSION_OFFSET

#define PTP_V2_SEQUENCE_LENGTH
#define PTP_V2_SEQUENCE_OFFSET

/* The minimum length of a PTP V2 packet for offsets, etc. to be valid:
 * includes IP header.
 */
#define PTP_V2_MIN_LENGTH

#define PTP_MIN_LENGTH

#define PTP_ADDR_IPV4

/* ff0e::181 */
static const struct in6_addr ptp_addr_ipv6 =;

/* 01-1B-19-00-00-00 */
static const u8 ptp_addr_ether[ETH_ALEN] __aligned(2) =;

#define PTP_EVENT_PORT
#define PTP_GENERAL_PORT

/* Annoyingly the format of the version numbers are different between
 * versions 1 and 2 so it isn't possible to simply look for 1 or 2.
 */
#define PTP_VERSION_V1

#define PTP_VERSION_V2
#define PTP_VERSION_V2_MASK

enum ptp_packet_state {};

/* NIC synchronised with single word of time only comprising
 * partial seconds and full nanoseconds: 10^9 ~ 2^30 so 2 bits for seconds.
 */
#define MC_NANOSECOND_BITS
#define MC_NANOSECOND_MASK
#define MC_SECOND_MASK

/* Maximum parts-per-billion adjustment that is acceptable */
#define MAX_PPB

/* Precalculate scale word to avoid long long division at runtime */
/* This is equivalent to 2^66 / 10^9. */
#define PPB_SCALE_WORD

/* How much to shift down after scaling to convert to FP40 */
#define PPB_SHIFT_FP40
/* ... and FP44. */
#define PPB_SHIFT_FP44

#define PTP_SYNC_ATTEMPTS

/**
 * struct efx_ptp_match - Matching structure, stored in sk_buff's cb area.
 * @expiry: Time after which the packet should be delivered irrespective of
 *            event arrival.
 * @state: The state of the packet - whether it is ready for processing or
 *         whether that is of no interest.
 */
struct efx_ptp_match {};

/**
 * struct efx_ptp_event_rx - A PTP receive event (from MC)
 * @link: list of events
 * @seq0: First part of (PTP) UUID
 * @seq1: Second part of (PTP) UUID and sequence number
 * @hwtimestamp: Event timestamp
 * @expiry: Time which the packet arrived
 */
struct efx_ptp_event_rx {};

/**
 * struct efx_ptp_timeset - Synchronisation between host and MC
 * @host_start: Host time immediately before hardware timestamp taken
 * @major: Hardware timestamp, major
 * @minor: Hardware timestamp, minor
 * @host_end: Host time immediately after hardware timestamp taken
 * @wait: Number of NIC clock ticks between hardware timestamp being read and
 *          host end time being seen
 * @window: Difference of host_end and host_start
 * @valid: Whether this timeset is valid
 */
struct efx_ptp_timeset {};

/**
 * struct efx_ptp_rxfilter - Filter for PTP packets
 * @list: Node of the list where the filter is added
 * @ether_type: Network protocol of the filter (ETHER_P_IP / ETHER_P_IPV6)
 * @loc_port: UDP port of the filter (PTP_EVENT_PORT / PTP_GENERAL_PORT)
 * @loc_host: IPv4/v6 address of the filter
 * @expiry: time when the filter expires, in jiffies
 * @handle: Handle ID for the MCDI filters table
 */
struct efx_ptp_rxfilter {};

/**
 * struct efx_ptp_data - Precision Time Protocol (PTP) state
 * @efx: The NIC context
 * @channel: The PTP channel (for Medford and Medford2)
 * @rxq: Receive SKB queue (awaiting timestamps)
 * @txq: Transmit SKB queue
 * @workwq: Work queue for processing pending PTP operations
 * @work: Work task
 * @cleanup_work: Work task for periodic cleanup
 * @reset_required: A serious error has occurred and the PTP task needs to be
 *                  reset (disable, enable).
 * @rxfilters_mcast: Receive filters for multicast PTP packets
 * @rxfilters_ucast: Receive filters for unicast PTP packets
 * @config: Current timestamp configuration
 * @enabled: PTP operation enabled
 * @mode: Mode in which PTP operating (PTP version)
 * @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time
 * @nic_to_kernel_time: Function to convert from NIC to kernel time
 * @nic_time: contains time details
 * @nic_time.minor_max: Wrap point for NIC minor times
 * @nic_time.sync_event_diff_min: Minimum acceptable difference between time
 * in packet prefix and last MCDI time sync event i.e. how much earlier than
 * the last sync event time a packet timestamp can be.
 * @nic_time.sync_event_diff_max: Maximum acceptable difference between time
 * in packet prefix and last MCDI time sync event i.e. how much later than
 * the last sync event time a packet timestamp can be.
 * @nic_time.sync_event_minor_shift: Shift required to make minor time from
 * field in MCDI time sync event.
 * @min_synchronisation_ns: Minimum acceptable corrected sync window
 * @capabilities: Capabilities flags from the NIC
 * @ts_corrections: contains corrections details
 * @ts_corrections.ptp_tx: Required driver correction of PTP packet transmit
 *                         timestamps
 * @ts_corrections.ptp_rx: Required driver correction of PTP packet receive
 *                         timestamps
 * @ts_corrections.pps_out: PPS output error (information only)
 * @ts_corrections.pps_in: Required driver correction of PPS input timestamps
 * @ts_corrections.general_tx: Required driver correction of general packet
 *                             transmit timestamps
 * @ts_corrections.general_rx: Required driver correction of general packet
 *                             receive timestamps
 * @evt_frags: Partly assembled PTP events
 * @evt_frag_idx: Current fragment number
 * @evt_code: Last event code
 * @start: Address at which MC indicates ready for synchronisation
 * @host_time_pps: Host time at last PPS
 * @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
 * frequency adjustment into a fixed point fractional nanosecond format.
 * @current_adjfreq: Current ppb adjustment.
 * @phc_clock: Pointer to registered phc device (if primary function)
 * @phc_clock_info: Registration structure for phc device
 * @pps_work: pps work task for handling pps events
 * @pps_workwq: pps work queue
 * @nic_ts_enabled: Flag indicating if NIC generated TS events are handled
 * @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids
 *         allocations in main data path).
 * @good_syncs: Number of successful synchronisations.
 * @fast_syncs: Number of synchronisations requiring short delay
 * @bad_syncs: Number of failed synchronisations.
 * @sync_timeouts: Number of synchronisation timeouts
 * @no_time_syncs: Number of synchronisations with no good times.
 * @invalid_sync_windows: Number of sync windows with bad durations.
 * @undersize_sync_windows: Number of corrected sync windows that are too small
 * @oversize_sync_windows: Number of corrected sync windows that are too large
 * @rx_no_timestamp: Number of packets received without a timestamp.
 * @timeset: Last set of synchronisation statistics.
 * @xmit_skb: Transmit SKB function.
 */
struct efx_ptp_data {};

static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm);
static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta);
static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
static int efx_phc_settime(struct ptp_clock_info *ptp,
			   const struct timespec64 *e_ts);
static int efx_phc_enable(struct ptp_clock_info *ptp,
			  struct ptp_clock_request *request, int on);
static int efx_ptp_insert_unicast_filter(struct efx_nic *efx,
					 struct sk_buff *skb);

bool efx_ptp_use_mac_tx_timestamps(struct efx_nic *efx)
{}

/* PTP 'extra' channel is still a traffic channel, but we only create TX queues
 * if PTP uses MAC TX timestamps, not if PTP uses the MC directly to transmit.
 */
static bool efx_ptp_want_txqs(struct efx_channel *channel)
{}

#define PTP_SW_STAT(ext_name, field_name)
#define PTP_MC_STAT(ext_name, mcdi_name)
static const struct efx_hw_stat_desc efx_ptp_stat_desc[] =;
#define PTP_STAT_COUNT
static const unsigned long efx_ptp_stat_mask[] =;

size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings)
{}

size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats)
{}

/* To convert from s27 format to ns we multiply then divide by a power of 2.
 * For the conversion from ns to s27, the operation is also converted to a
 * multiply and shift.
 */
#define S27_TO_NS_SHIFT
#define NS_TO_S27_MULT
#define NS_TO_S27_SHIFT
#define S27_MINOR_MAX

/* For Huntington platforms NIC time is in seconds and fractions of a second
 * where the minor register only uses 27 bits in units of 2^-27s.
 */
static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor)
{}

static inline ktime_t efx_ptp_s27_to_ktime(u32 nic_major, u32 nic_minor)
{}

static ktime_t efx_ptp_s27_to_ktime_correction(u32 nic_major, u32 nic_minor,
					       s32 correction)
{}

/* For Medford2 platforms the time is in seconds and quarter nanoseconds. */
static void efx_ptp_ns_to_s_qns(s64 ns, u32 *nic_major, u32 *nic_minor)
{}

static ktime_t efx_ptp_s_qns_to_ktime_correction(u32 nic_major, u32 nic_minor,
						 s32 correction)
{}

struct efx_channel *efx_ptp_channel(struct efx_nic *efx)
{}

void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel)
{}

static u32 last_sync_timestamp_major(struct efx_nic *efx)
{}

/* The 8000 series and later can provide the time from the MAC, which is only
 * 48 bits long and provides meta-information in the top 2 bits.
 */
static ktime_t
efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx,
				    struct efx_ptp_data *ptp,
				    u32 nic_major, u32 nic_minor,
				    s32 correction)
{}

ktime_t efx_ptp_nic_to_kernel_time(struct efx_tx_queue *tx_queue)
{}

/* Get PTP attributes and set up time conversions */
static int efx_ptp_get_attributes(struct efx_nic *efx)
{}

/* Get PTP timestamp corrections */
static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx)
{}

/* Enable MCDI PTP support. */
static int efx_ptp_enable(struct efx_nic *efx)
{}

/* Disable MCDI PTP support.
 *
 * Note that this function should never rely on the presence of ptp_data -
 * may be called before that exists.
 */
static int efx_ptp_disable(struct efx_nic *efx)
{}

static void efx_ptp_deliver_rx_queue(struct sk_buff_head *q)
{}

static void efx_ptp_handle_no_channel(struct efx_nic *efx)
{}

/* Repeatedly send the host time to the MC which will capture the hardware
 * time.
 */
static void efx_ptp_send_times(struct efx_nic *efx,
			       struct pps_event_time *last_time)
{}

/* Read a timeset from the MC's results and partial process. */
static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data),
				 struct efx_ptp_timeset *timeset)
{}

/* Process times received from MC.
 *
 * Extract times from returned results, and establish the minimum value
 * seen.  The minimum value represents the "best" possible time and events
 * too much greater than this are rejected - the machine is, perhaps, too
 * busy. A number of readings are taken so that, hopefully, at least one good
 * synchronisation will be seen in the results.
 */
static int
efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
		      size_t response_length,
		      const struct pps_event_time *last_time)
{}

/* Synchronize times between the host and the MC */
static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
{}

/* Transmit a PTP packet via the dedicated hardware timestamped queue. */
static void efx_ptp_xmit_skb_queue(struct efx_nic *efx, struct sk_buff *skb)
{}

/* Transmit a PTP packet, via the MCDI interface, to the wire. */
static void efx_ptp_xmit_skb_mc(struct efx_nic *efx, struct sk_buff *skb)
{}

/* Process any queued receive events and corresponding packets
 *
 * q is returned with all the packets that are ready for delivery.
 */
static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q)
{}

/* Complete processing of a received packet */
static inline void efx_ptp_process_rx(struct efx_nic *efx, struct sk_buff *skb)
{}

static struct efx_ptp_rxfilter *
efx_ptp_find_filter(struct list_head *filter_list, struct efx_filter_spec *spec)
{}

static void efx_ptp_remove_one_filter(struct efx_nic *efx,
				      struct efx_ptp_rxfilter *rxfilter)
{}

static void efx_ptp_remove_filters(struct efx_nic *efx,
				   struct list_head *filter_list)
{}

static void efx_ptp_init_filter(struct efx_nic *efx,
				struct efx_filter_spec *rxfilter)
{}

static int efx_ptp_insert_filter(struct efx_nic *efx,
				 struct list_head *filter_list,
				 struct efx_filter_spec *spec,
				 unsigned long expiry)
{}

static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx,
				      struct list_head *filter_list,
				      __be32 addr, u16 port,
				      unsigned long expiry)
{}

static int efx_ptp_insert_ipv6_filter(struct efx_nic *efx,
				      struct list_head *filter_list,
				      const struct in6_addr *addr, u16 port,
				      unsigned long expiry)
{}

static int efx_ptp_insert_eth_multicast_filter(struct efx_nic *efx)
{}

static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
{}

static bool efx_ptp_valid_unicast_event_pkt(struct sk_buff *skb)
{}

static int efx_ptp_insert_unicast_filter(struct efx_nic *efx,
					 struct sk_buff *skb)
{}

static int efx_ptp_start(struct efx_nic *efx)
{}

static int efx_ptp_stop(struct efx_nic *efx)
{}

static int efx_ptp_restart(struct efx_nic *efx)
{}

static void efx_ptp_pps_worker(struct work_struct *work)
{}

static void efx_ptp_worker(struct work_struct *work)
{}

static void efx_ptp_cleanup_worker(struct work_struct *work)
{}

static const struct ptp_clock_info efx_phc_clock_info =;

/* Initialise PTP state. */
int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
{}

/* Initialise PTP channel.
 *
 * Setting core_index to zero causes the queue to be initialised and doesn't
 * overlap with 'rxq0' because ptp.c doesn't use skb_record_rx_queue.
 */
static int efx_ptp_probe_channel(struct efx_channel *channel)
{}

void efx_ptp_remove(struct efx_nic *efx)
{}

static void efx_ptp_remove_channel(struct efx_channel *channel)
{}

static void efx_ptp_get_channel_name(struct efx_channel *channel,
				     char *buf, size_t len)
{}

/* Determine whether this packet should be processed by the PTP module
 * or transmitted conventionally.
 */
bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
{}

/* Receive a PTP packet.  Packets are queued until the arrival of
 * the receive timestamp from the MC - this will probably occur after the
 * packet arrival because of the processing in the MC.
 */
static bool efx_ptp_rx(struct efx_channel *channel, struct sk_buff *skb)
{}

/* Transmit a PTP packet.  This has to be transmitted by the MC
 * itself, through an MCDI call.  MCDI calls aren't permitted
 * in the transmit path so defer the actual transmission to a suitable worker.
 */
int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
{}

int efx_ptp_get_mode(struct efx_nic *efx)
{}

int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
			unsigned int new_mode)
{}

static int efx_ptp_ts_init(struct efx_nic *efx, struct kernel_hwtstamp_config *init)
{}

void efx_ptp_get_ts_info(struct efx_nic *efx, struct kernel_ethtool_ts_info *ts_info)
{}

int efx_ptp_set_ts_config(struct efx_nic *efx,
			  struct kernel_hwtstamp_config *config,
			  struct netlink_ext_ack __always_unused *extack)
{}

int efx_ptp_get_ts_config(struct efx_nic *efx,
			  struct kernel_hwtstamp_config *config)
{}

static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len)
{}

static void ptp_event_fault(struct efx_nic *efx, struct efx_ptp_data *ptp)
{}

static void ptp_event_pps(struct efx_nic *efx, struct efx_ptp_data *ptp)
{}

void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev)
{}

void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev)
{}

static inline u32 efx_rx_buf_timestamp_minor(struct efx_nic *efx, const u8 *eh)
{}

void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
				   struct sk_buff *skb)
{}

static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{}

static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
{}

static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{}

static int efx_phc_settime(struct ptp_clock_info *ptp,
			   const struct timespec64 *e_ts)
{}

static int efx_phc_enable(struct ptp_clock_info *ptp,
			  struct ptp_clock_request *request,
			  int enable)
{}

static const struct efx_channel_type efx_ptp_channel_type =;

void efx_ptp_defer_probe_with_channel(struct efx_nic *efx)
{}

void efx_ptp_start_datapath(struct efx_nic *efx)
{}

void efx_ptp_stop_datapath(struct efx_nic *efx)
{}