Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2611df7a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sfc-support-PTP-on-8000-and-X2000-series-NICs'



Edward Cree says:

====================
sfc: support PTP on 8000 and X2000 series NICs

Starting from the 8000-series (Medford 1), SFC NICs can timestamp TX packets
 sent through an ordinary DMA queue, rather than a special control-plane
 operation as in the 7000-series.  Patches 2-8 implement support for this.
The X2000-series (Medford 2) changes the format of timestamps, from seconds+
 (2^27)ths to seconds + quarter nanoseconds, as well as changing the shift
 of the frequency adjustment for increased precision.  Patches 9-12
 implement support for these changes.
Patch #1 is an unrelated fix for NAPI budget handling, needed in order for
 TX completion changes in the later patches to apply cleanly.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fb07a820 88a4fb5f
Loading
Loading
Loading
Loading
+125 −33
Original line number Diff line number Diff line
@@ -322,6 +322,25 @@ static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
	return 0;
}

static void efx_ef10_read_licensed_features(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_LICENSING_V3_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_LICENSING_V3_OUT_LEN);
	struct efx_ef10_nic_data *nic_data = efx->nic_data;
	size_t outlen;
	int rc;

	MCDI_SET_DWORD(inbuf, LICENSING_V3_IN_OP,
		       MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_LICENSING_V3, inbuf, sizeof(inbuf),
				outbuf, sizeof(outbuf), &outlen);
	if (rc || (outlen < MC_CMD_LICENSING_V3_OUT_LEN))
		return;

	nic_data->licensed_features = MCDI_QWORD(outbuf,
					 LICENSING_V3_OUT_LICENSED_FEATURES);
}

static int efx_ef10_get_sysclk_freq(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLOCK_OUT_LEN);
@@ -722,6 +741,8 @@ static int efx_ef10_probe(struct efx_nic *efx)
	if (rc < 0)
		goto fail5;

	efx_ef10_read_licensed_features(efx);

	/* We can have one VI for each vi_stride-byte region.
	 * However, until we use TX option descriptors we need two TX queues
	 * per channel.
@@ -760,14 +781,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
	if (rc && rc != -EPERM)
		goto fail5;

	rc = efx_ptp_probe(efx, NULL);
	/* Failure to probe PTP is not fatal.
	 * In the case of EPERM, efx_ptp_probe will print its own message (in
	 * efx_ptp_get_attributes()), so we don't need to.
	 */
	if (rc && rc != -EPERM)
		netif_warn(efx, drv, efx->net_dev,
			   "Failed to probe PTP, rc=%d\n", rc);
	efx_ptp_defer_probe_with_channel(efx);

#ifdef CONFIG_SFC_SRIOV
	if ((efx->pci_dev->physfn) && (!efx->pci_dev->is_physfn)) {
@@ -937,6 +951,11 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)

	/* Link a buffer to each TX queue */
	efx_for_each_channel(channel, efx) {
		/* Extra channels, even those with TXQs (PTP), do not require
		 * PIO resources.
		 */
		if (!channel->type->want_pio)
			continue;
		efx_for_each_channel_tx_queue(tx_queue, channel) {
			/* We assign the PIO buffers to queues in
			 * reverse order to allow for the following
@@ -1284,7 +1303,9 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
	void __iomem *membase;
	int rc;

	channel_vis = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES);
	channel_vis = max(efx->n_channels,
			  (efx->n_tx_channels + efx->n_extra_tx_channels) *
			  EFX_TXQ_TYPES);

#ifdef EFX_USE_PIO
	/* Try to allocate PIO buffers if wanted and if the full
@@ -2408,12 +2429,25 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	int i;
	BUILD_BUG_ON(MC_CMD_INIT_TXQ_OUT_LEN != 0);

	/* Only attempt to enable TX timestamping if we have the license for it,
	 * otherwise TXQ init will fail
	 */
	if (!(nic_data->licensed_features &
	      (1 << LICENSED_V3_FEATURES_TX_TIMESTAMPS_LBN))) {
		tx_queue->timestamping = false;
		/* Disable sync events on this channel. */
		if (efx->type->ptp_set_ts_sync_events)
			efx->type->ptp_set_ts_sync_events(efx, false, false);
	}

	/* TSOv2 is a limited resource that can only be configured on a limited
	 * number of queues. TSO without checksum offload is not really a thing,
	 * so we only enable it for those queues.
	 * TSOv2 cannot be used with Hardware timestamping.
	 */
	if (csum_offload && (nic_data->datapath_caps2 &
			(1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN))) {
			(1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN)) &&
	    !tx_queue->timestamping) {
		tso_v2 = true;
		netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
				channel->channel);
@@ -2439,14 +2473,16 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	inlen = MC_CMD_INIT_TXQ_IN_LEN(entries);

	do {
		MCDI_POPULATE_DWORD_3(inbuf, INIT_TXQ_IN_FLAGS,
		MCDI_POPULATE_DWORD_4(inbuf, INIT_TXQ_IN_FLAGS,
				/* This flag was removed from mcdi_pcol.h for
				 * the non-_EXT version of INIT_TXQ.  However,
				 * firmware still honours it.
				 */
				INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, tso_v2,
				INIT_TXQ_IN_FLAG_IP_CSUM_DIS, !csum_offload,
				INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload);
				INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, !csum_offload,
				INIT_TXQ_EXT_IN_FLAG_TIMESTAMP,
						tx_queue->timestamping);

		rc = efx_mcdi_rpc_quiet(efx, MC_CMD_INIT_TXQ, inbuf, inlen,
					NULL, 0, NULL);
@@ -2472,12 +2508,13 @@ static void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
	tx_queue->buffer[0].flags = EFX_TX_BUF_OPTION;
	tx_queue->insert_count = 1;
	txd = efx_tx_desc(tx_queue, 0);
	EFX_POPULATE_QWORD_4(*txd,
	EFX_POPULATE_QWORD_5(*txd,
			     ESF_DZ_TX_DESC_IS_OPT, true,
			     ESF_DZ_TX_OPTION_TYPE,
			     ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
			     ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload,
			     ESF_DZ_TX_OPTION_IP_CSUM, csum_offload);
			     ESF_DZ_TX_OPTION_IP_CSUM, csum_offload,
			     ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping);
	tx_queue->write_count = 1;

	if (tso_v2) {
@@ -3572,31 +3609,92 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel,
	return n_packets;
}

static int
static u32 efx_ef10_extract_event_ts(efx_qword_t *event)
{
	u32 tstamp;

	tstamp = EFX_QWORD_FIELD(*event, TX_TIMESTAMP_EVENT_TSTAMP_DATA_HI);
	tstamp <<= 16;
	tstamp |= EFX_QWORD_FIELD(*event, TX_TIMESTAMP_EVENT_TSTAMP_DATA_LO);

	return tstamp;
}

static void
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
{
	struct efx_nic *efx = channel->efx;
	struct efx_tx_queue *tx_queue;
	unsigned int tx_ev_desc_ptr;
	unsigned int tx_ev_q_label;
	int tx_descs = 0;
	unsigned int tx_ev_type;
	u64 ts_part;

	if (unlikely(READ_ONCE(efx->reset_pending)))
		return 0;
		return;

	if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
		return 0;
		return;

	/* Transmit completion */
	tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
	/* Get the transmit queue */
	tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
	tx_queue = efx_channel_get_tx_queue(channel,
					    tx_ev_q_label % EFX_TXQ_TYPES);
	tx_descs = ((tx_ev_desc_ptr + 1 - tx_queue->read_count) &
		    tx_queue->ptr_mask);

	if (!tx_queue->timestamping) {
		/* Transmit completion */
		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
		efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
		return;
	}

	return tx_descs;
	/* Transmit timestamps are only available for 8XXX series. They result
	 * in three events per packet. These occur in order, and are:
	 *  - the normal completion event
	 *  - the low part of the timestamp
	 *  - the high part of the timestamp
	 *
	 * Each part of the timestamp is itself split across two 16 bit
	 * fields in the event.
	 */
	tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);

	switch (tx_ev_type) {
	case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
		/* In case of Queue flush or FLR, we might have received
		 * the previous TX completion event but not the Timestamp
		 * events.
		 */
		if (tx_queue->completed_desc_ptr != tx_queue->ptr_mask)
			efx_xmit_done(tx_queue, tx_queue->completed_desc_ptr);

		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event,
						 ESF_DZ_TX_DESCR_INDX);
		tx_queue->completed_desc_ptr =
					tx_ev_desc_ptr & tx_queue->ptr_mask;
		break;

	case TX_TIMESTAMP_EVENT_TX_EV_TSTAMP_LO:
		ts_part = efx_ef10_extract_event_ts(event);
		tx_queue->completed_timestamp_minor = ts_part;
		break;

	case TX_TIMESTAMP_EVENT_TX_EV_TSTAMP_HI:
		ts_part = efx_ef10_extract_event_ts(event);
		tx_queue->completed_timestamp_major = ts_part;

		efx_xmit_done(tx_queue, tx_queue->completed_desc_ptr);
		tx_queue->completed_desc_ptr = tx_queue->ptr_mask;
		break;

	default:
		netif_err(efx, hw, efx->net_dev,
			  "channel %d unknown tx event type %d (data "
			  EFX_QWORD_FMT ")\n",
			  channel->channel, tx_ev_type,
			  EFX_QWORD_VAL(*event));
		break;
	}
}

static void
@@ -3658,7 +3756,6 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
	efx_qword_t event, *p_event;
	unsigned int read_ptr;
	int ev_code;
	int tx_descs = 0;
	int spent = 0;

	if (quota <= 0)
@@ -3698,13 +3795,7 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
			}
			break;
		case ESE_DZ_EV_CODE_TX_EV:
			tx_descs += efx_ef10_handle_tx_event(channel, &event);
			if (tx_descs > efx->txq_entries) {
				spent = quota;
				goto out;
			} else if (++spent == quota) {
				goto out;
			}
			efx_ef10_handle_tx_event(channel, &event);
			break;
		case ESE_DZ_EV_CODE_DRIVER_EV:
			efx_ef10_handle_driver_event(channel, &event);
@@ -6179,7 +6270,8 @@ static int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en,
	      efx_ef10_rx_enable_timestamping :
	      efx_ef10_rx_disable_timestamping;

	efx_for_each_channel(channel, efx) {
	channel = efx_ptp_channel(efx);
	if (channel) {
		int rc = set(channel, temp);
		if (en && rc != 0) {
			efx_ef10_ptp_set_ts_sync_events(efx, false, temp);
+11 −0
Original line number Diff line number Diff line
@@ -896,12 +896,20 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
	mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
}

bool efx_default_channel_want_txqs(struct efx_channel *channel)
{
	return channel->channel - channel->efx->tx_channel_offset <
		channel->efx->n_tx_channels;
}

static const struct efx_channel_type efx_default_channel_type = {
	.pre_probe		= efx_channel_dummy_op_int,
	.post_remove		= efx_channel_dummy_op_void,
	.get_name		= efx_get_channel_name,
	.copy			= efx_copy_channel,
	.want_txqs		= efx_default_channel_want_txqs,
	.keep_eventq		= false,
	.want_pio		= true,
};

int efx_channel_dummy_op_int(struct efx_channel *channel)
@@ -1501,6 +1509,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
	}

	/* Assign extra channels if possible */
	efx->n_extra_tx_channels = 0;
	j = efx->n_channels;
	for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++) {
		if (!efx->extra_channel_type[i])
@@ -1512,6 +1521,8 @@ static int efx_probe_interrupts(struct efx_nic *efx)
			--j;
			efx_get_channel(efx, j)->type =
				efx->extra_channel_type[i];
			if (efx_channel_has_tx_queues(efx_get_channel(efx, j)))
				efx->n_extra_tx_channels++;
		}
	}

+8 −18
Original line number Diff line number Diff line
@@ -818,17 +818,16 @@ static void efx_farch_magic_event(struct efx_channel *channel, u32 magic)
 * The NIC batches TX completion events; the message we receive is of
 * the form "complete all TX events up to this index".
 */
static int
static void
efx_farch_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
{
	unsigned int tx_ev_desc_ptr;
	unsigned int tx_ev_q_label;
	struct efx_tx_queue *tx_queue;
	struct efx_nic *efx = channel->efx;
	int tx_packets = 0;

	if (unlikely(READ_ONCE(efx->reset_pending)))
		return 0;
		return;

	if (likely(EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_COMP))) {
		/* Transmit completion */
@@ -836,8 +835,6 @@ efx_farch_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
		tx_queue = efx_channel_get_tx_queue(
			channel, tx_ev_q_label % EFX_TXQ_TYPES);
		tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
			      tx_queue->ptr_mask);
		efx_xmit_done(tx_queue, tx_ev_desc_ptr);
	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
		/* Rewrite the FIFO write pointer */
@@ -856,8 +853,6 @@ efx_farch_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
			  EFX_QWORD_FMT"\n", channel->channel,
			  EFX_QWORD_VAL(*event));
	}

	return tx_packets;
}

/* Detect errors included in the rx_evt_pkt_ok bit. */
@@ -1090,7 +1085,7 @@ efx_farch_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
	int qid;

	qid = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
	if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) {
	if (qid < EFX_TXQ_TYPES * (efx->n_tx_channels + efx->n_extra_tx_channels)) {
		tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES,
					    qid % EFX_TXQ_TYPES);
		if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
@@ -1270,7 +1265,6 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget)
	unsigned int read_ptr;
	efx_qword_t event, *p_event;
	int ev_code;
	int tx_packets = 0;
	int spent = 0;

	if (budget <= 0)
@@ -1304,12 +1298,7 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget)
				goto out;
			break;
		case FSE_AZ_EV_CODE_TX_EV:
			tx_packets += efx_farch_handle_tx_event(channel,
								&event);
			if (tx_packets > efx->txq_entries) {
				spent = budget;
				goto out;
			}
			efx_farch_handle_tx_event(channel, &event);
			break;
		case FSE_AZ_EV_CODE_DRV_GEN_EV:
			efx_farch_handle_generated_event(channel, &event);
@@ -1680,20 +1669,21 @@ void efx_farch_rx_pull_indir_table(struct efx_nic *efx)
 */
void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw)
{
	unsigned vi_count, buftbl_min;
	unsigned vi_count, buftbl_min, total_tx_channels;

#ifdef CONFIG_SFC_SRIOV
	struct siena_nic_data *nic_data = efx->nic_data;
#endif

	total_tx_channels = efx->n_tx_channels + efx->n_extra_tx_channels;
	/* Account for the buffer table entries backing the datapath channels
	 * and the descriptor caches for those channels.
	 */
	buftbl_min = ((efx->n_rx_channels * EFX_MAX_DMAQ_SIZE +
		       efx->n_tx_channels * EFX_TXQ_TYPES * EFX_MAX_DMAQ_SIZE +
		       total_tx_channels * EFX_TXQ_TYPES * EFX_MAX_DMAQ_SIZE +
		       efx->n_channels * EFX_MAX_EVQ_SIZE)
		      * sizeof(efx_qword_t) / EFX_BUF_SIZE);
	vi_count = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES);
	vi_count = max(efx->n_channels, total_tx_channels * EFX_TXQ_TYPES);

#ifdef CONFIG_SFC_SRIOV
	if (efx->type->sriov_wanted) {
+19 −2
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ struct efx_tx_buffer {
 *	Size of the region is efx_piobuf_size.
 * @piobuf_offset: Buffer offset to be specified in PIO descriptors
 * @initialised: Has hardware queue been initialised?
 * @timestamping: Is timestamping enabled for this channel?
 * @handle_tso: TSO xmit preparation handler.  Sets up the TSO metadata and
 *	may also map tx data, depending on the nature of the TSO implementation.
 * @read_count: Current read pointer.
@@ -202,6 +203,10 @@ struct efx_tx_buffer {
 *	avoid cache-line ping-pong between the xmit path and the
 *	completion path.
 * @merge_events: Number of TX merged completion events
 * @completed_desc_ptr: Most recent completed pointer - only used with
 *      timestamping.
 * @completed_timestamp_major: Top part of the most recent tx timestamp.
 * @completed_timestamp_minor: Low part of the most recent tx timestamp.
 * @insert_count: Current insert pointer
 *	This is the number of buffers that have been added to the
 *	software ring.
@@ -247,6 +252,7 @@ struct efx_tx_queue {
	void __iomem *piobuf;
	unsigned int piobuf_offset;
	bool initialised;
	bool timestamping;

	/* Function pointers used in the fast path. */
	int (*handle_tso)(struct efx_tx_queue*, struct sk_buff*, bool *);
@@ -257,6 +263,9 @@ struct efx_tx_queue {
	unsigned int merge_events;
	unsigned int bytes_compl;
	unsigned int pkts_compl;
	unsigned int completed_desc_ptr;
	u32 completed_timestamp_major;
	u32 completed_timestamp_minor;

	/* Members used only on the xmit path */
	unsigned int insert_count ____cacheline_aligned_in_smp;
@@ -522,8 +531,12 @@ struct efx_msi_context {
 * @copy: Copy the channel state prior to reallocation.  May be %NULL if
 *	reallocation is not supported.
 * @receive_skb: Handle an skb ready to be passed to netif_receive_skb()
 * @want_txqs: Determine whether this channel should have TX queues
 *	created.  If %NULL, TX queues are not created.
 * @keep_eventq: Flag for whether event queue should be kept initialised
 *	while the device is stopped
 * @want_pio: Flag for whether PIO buffers should be linked to this
 *	channel's TX queues.
 */
struct efx_channel_type {
	void (*handle_no_channel)(struct efx_nic *);
@@ -532,7 +545,9 @@ struct efx_channel_type {
	void (*get_name)(struct efx_channel *, char *buf, size_t len);
	struct efx_channel *(*copy)(const struct efx_channel *);
	bool (*receive_skb)(struct efx_channel *, struct sk_buff *);
	bool (*want_txqs)(struct efx_channel *);
	bool keep_eventq;
	bool want_pio;
};

enum efx_led_mode {
@@ -735,6 +750,7 @@ struct vfdi_status;
 * @n_channels: Number of channels in use
 * @n_rx_channels: Number of channels used for RX (= number of RX queues)
 * @n_tx_channels: Number of channels used for TX
 * @n_extra_tx_channels: Number of extra channels with TX queues
 * @rx_ip_align: RX DMA address offset to have IP header aligned in
 *	in accordance with NET_IP_ALIGN
 * @rx_dma_len: Current maximum RX DMA length
@@ -881,6 +897,7 @@ struct efx_nic {
	unsigned rss_spread;
	unsigned tx_channel_offset;
	unsigned n_tx_channels;
	unsigned n_extra_tx_channels;
	unsigned int rx_ip_align;
	unsigned int rx_dma_len;
	unsigned int rx_buffer_order;
@@ -1363,8 +1380,8 @@ efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)

static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
{
	return channel->channel - channel->efx->tx_channel_offset <
		channel->efx->n_tx_channels;
	return channel->type && channel->type->want_txqs &&
				channel->type->want_txqs(channel);
}

static inline struct efx_tx_queue *
+4 −0
Original line number Diff line number Diff line
@@ -440,6 +440,7 @@ struct efx_ef10_nic_data {
	struct efx_udp_tunnel udp_tunnels[16];
	bool udp_tunnels_dirty;
	struct mutex udp_tunnels_lock;
	u64 licensed_features;
};

int efx_init_sriov(void);
@@ -448,6 +449,7 @@ void efx_fini_sriov(void);
struct ethtool_ts_info;
int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel);
void efx_ptp_defer_probe_with_channel(struct efx_nic *efx);
struct efx_channel *efx_ptp_channel(struct efx_nic *efx);
void efx_ptp_remove(struct efx_nic *efx);
int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr);
int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr);
@@ -471,6 +473,8 @@ static inline void efx_rx_skb_attach_timestamp(struct efx_channel *channel,
}
void efx_ptp_start_datapath(struct efx_nic *efx);
void efx_ptp_stop_datapath(struct efx_nic *efx);
bool efx_ptp_use_mac_tx_timestamps(struct efx_nic *efx);
ktime_t efx_ptp_nic_to_kernel_time(struct efx_tx_queue *tx_queue);

extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
Loading