sfc: on 8000 series use TX queues for TX timestamps
[linux-2.6-microblaze.git] / drivers / net / ethernet / sfc / ef10.c
index e566dbb..b460e06 100644 (file)
@@ -160,11 +160,31 @@ static int efx_ef10_get_warm_boot_count(struct efx_nic *efx)
                EFX_DWORD_FIELD(reg, EFX_WORD_0) : -EIO;
 }
 
+/* On all EF10s up to and including SFC9220 (Medford1), all PFs use BAR 0 for
+ * I/O space and BAR 2(&3) for memory.  On SFC9250 (Medford2), there is no I/O
+ * bar; PFs use BAR 0/1 for memory.
+ */
+static unsigned int efx_ef10_pf_mem_bar(struct efx_nic *efx)
+{
+       switch (efx->pci_dev->device) {
+       case 0x0b03: /* SFC9250 PF */
+               return 0;
+       default:
+               return 2;
+       }
+}
+
+/* All VFs use BAR 0/1 for memory */
+static unsigned int efx_ef10_vf_mem_bar(struct efx_nic *efx)
+{
+       return 0;
+}
+
 static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
 {
        int bar;
 
-       bar = efx->type->mem_bar;
+       bar = efx->type->mem_bar(efx);
        return resource_size(&efx->pci_dev->resource[bar]);
 }
 
@@ -213,7 +233,7 @@ static int efx_ef10_get_vf_index(struct efx_nic *efx)
 
 static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
 {
-       MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V2_OUT_LEN);
+       MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V4_OUT_LEN);
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
        size_t outlen;
        int rc;
@@ -257,9 +277,70 @@ static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
                return -ENODEV;
        }
 
+       if (outlen >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
+               u8 vi_window_mode = MCDI_BYTE(outbuf,
+                               GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
+
+               switch (vi_window_mode) {
+               case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_8K:
+                       efx->vi_stride = 8192;
+                       break;
+               case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_16K:
+                       efx->vi_stride = 16384;
+                       break;
+               case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_64K:
+                       efx->vi_stride = 65536;
+                       break;
+               default:
+                       netif_err(efx, probe, efx->net_dev,
+                                 "Unrecognised VI window mode %d\n",
+                                 vi_window_mode);
+                       return -EIO;
+               }
+               netif_dbg(efx, probe, efx->net_dev, "vi_stride = %u\n",
+                         efx->vi_stride);
+       } else {
+               /* keep default VI stride */
+               netif_dbg(efx, probe, efx->net_dev,
+                         "firmware did not report VI window mode, assuming vi_stride = %u\n",
+                         efx->vi_stride);
+       }
+
+       if (outlen >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
+               efx->num_mac_stats = MCDI_WORD(outbuf,
+                               GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
+               netif_dbg(efx, probe, efx->net_dev,
+                         "firmware reports num_mac_stats = %u\n",
+                         efx->num_mac_stats);
+       } else {
+               /* leave num_mac_stats as the default value, MC_CMD_MAC_NSTATS */
+               netif_dbg(efx, probe, efx->net_dev,
+                         "firmware did not report num_mac_stats, assuming %u\n",
+                         efx->num_mac_stats);
+       }
+
        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);
@@ -589,17 +670,6 @@ static int efx_ef10_probe(struct efx_nic *efx)
        struct efx_ef10_nic_data *nic_data;
        int i, rc;
 
-       /* We can have one VI for each 8K region.  However, until we
-        * use TX option descriptors we need two TX queues per channel.
-        */
-       efx->max_channels = min_t(unsigned int,
-                                 EFX_MAX_CHANNELS,
-                                 efx_ef10_mem_map_size(efx) /
-                                 (EFX_VI_PAGE_SIZE * EFX_TXQ_TYPES));
-       efx->max_tx_channels = efx->max_channels;
-       if (WARN_ON(efx->max_channels == 0))
-               return -EIO;
-
        nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
        if (!nic_data)
                return -ENOMEM;
@@ -671,6 +741,22 @@ 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.
+        */
+       efx->max_channels = min_t(unsigned int,
+                                 EFX_MAX_CHANNELS,
+                                 efx_ef10_mem_map_size(efx) /
+                                 (efx->vi_stride * EFX_TXQ_TYPES));
+       efx->max_tx_channels = efx->max_channels;
+       if (WARN_ON(efx->max_channels == 0)) {
+               rc = -EIO;
+               goto fail5;
+       }
+
        efx->rx_packet_len_offset =
                ES_DZ_RX_PREFIX_PKTLEN_OFST - ES_DZ_RX_PREFIX_SIZE;
 
@@ -695,7 +781,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
        if (rc && rc != -EPERM)
                goto fail5;
 
-       efx_ptp_probe(efx, NULL);
+       efx_ptp_defer_probe_with_channel(efx);
 
 #ifdef CONFIG_SFC_SRIOV
        if ((efx->pci_dev->physfn) && (!efx->pci_dev->is_physfn)) {
@@ -865,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
@@ -907,7 +998,7 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)
                        } else {
                                tx_queue->piobuf =
                                        nic_data->pio_write_base +
-                                       index * EFX_VI_PAGE_SIZE + offset;
+                                       index * efx->vi_stride + offset;
                                tx_queue->piobuf_offset = offset;
                                netif_dbg(efx, probe, efx->net_dev,
                                          "linked VI %u to PIO buffer %u offset %x addr %p\n",
@@ -1212,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
@@ -1253,19 +1346,19 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
         * for writing PIO buffers through.
         *
         * The UC mapping contains (channel_vis - 1) complete VIs and the
-        * first half of the next VI.  Then the WC mapping begins with
-        * the second half of this last VI.
+        * first 4K of the next VI.  Then the WC mapping begins with
+        * the remainder of this last VI.
         */
-       uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * EFX_VI_PAGE_SIZE +
+       uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * efx->vi_stride +
                                     ER_DZ_TX_PIOBUF);
        if (nic_data->n_piobufs) {
                /* pio_write_vi_base rounds down to give the number of complete
                 * VIs inside the UC mapping.
                 */
-               pio_write_vi_base = uc_mem_map_size / EFX_VI_PAGE_SIZE;
+               pio_write_vi_base = uc_mem_map_size / efx->vi_stride;
                wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
                                               nic_data->n_piobufs) *
-                                             EFX_VI_PAGE_SIZE) -
+                                             efx->vi_stride) -
                                   uc_mem_map_size);
                max_vis = pio_write_vi_base + nic_data->n_piobufs;
        } else {
@@ -1337,7 +1430,7 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx)
                nic_data->pio_write_vi_base = pio_write_vi_base;
                nic_data->pio_write_base =
                        nic_data->wc_membase +
-                       (pio_write_vi_base * EFX_VI_PAGE_SIZE + ER_DZ_TX_PIOBUF -
+                       (pio_write_vi_base * efx->vi_stride + ER_DZ_TX_PIOBUF -
                         uc_mem_map_size);
 
                rc = efx_ef10_link_piobufs(efx);
@@ -1571,6 +1664,29 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
        EF10_DMA_STAT(tx_bad, VADAPTER_TX_BAD_PACKETS),
        EF10_DMA_STAT(tx_bad_bytes, VADAPTER_TX_BAD_BYTES),
        EF10_DMA_STAT(tx_overflow, VADAPTER_TX_OVERFLOW),
+       EF10_DMA_STAT(fec_uncorrected_errors, FEC_UNCORRECTED_ERRORS),
+       EF10_DMA_STAT(fec_corrected_errors, FEC_CORRECTED_ERRORS),
+       EF10_DMA_STAT(fec_corrected_symbols_lane0, FEC_CORRECTED_SYMBOLS_LANE0),
+       EF10_DMA_STAT(fec_corrected_symbols_lane1, FEC_CORRECTED_SYMBOLS_LANE1),
+       EF10_DMA_STAT(fec_corrected_symbols_lane2, FEC_CORRECTED_SYMBOLS_LANE2),
+       EF10_DMA_STAT(fec_corrected_symbols_lane3, FEC_CORRECTED_SYMBOLS_LANE3),
+       EF10_DMA_STAT(ctpio_dmabuf_start, CTPIO_DMABUF_START),
+       EF10_DMA_STAT(ctpio_vi_busy_fallback, CTPIO_VI_BUSY_FALLBACK),
+       EF10_DMA_STAT(ctpio_long_write_success, CTPIO_LONG_WRITE_SUCCESS),
+       EF10_DMA_STAT(ctpio_missing_dbell_fail, CTPIO_MISSING_DBELL_FAIL),
+       EF10_DMA_STAT(ctpio_overflow_fail, CTPIO_OVERFLOW_FAIL),
+       EF10_DMA_STAT(ctpio_underflow_fail, CTPIO_UNDERFLOW_FAIL),
+       EF10_DMA_STAT(ctpio_timeout_fail, CTPIO_TIMEOUT_FAIL),
+       EF10_DMA_STAT(ctpio_noncontig_wr_fail, CTPIO_NONCONTIG_WR_FAIL),
+       EF10_DMA_STAT(ctpio_frm_clobber_fail, CTPIO_FRM_CLOBBER_FAIL),
+       EF10_DMA_STAT(ctpio_invalid_wr_fail, CTPIO_INVALID_WR_FAIL),
+       EF10_DMA_STAT(ctpio_vi_clobber_fallback, CTPIO_VI_CLOBBER_FALLBACK),
+       EF10_DMA_STAT(ctpio_unqualified_fallback, CTPIO_UNQUALIFIED_FALLBACK),
+       EF10_DMA_STAT(ctpio_runt_fallback, CTPIO_RUNT_FALLBACK),
+       EF10_DMA_STAT(ctpio_success, CTPIO_SUCCESS),
+       EF10_DMA_STAT(ctpio_fallback, CTPIO_FALLBACK),
+       EF10_DMA_STAT(ctpio_poison, CTPIO_POISON),
+       EF10_DMA_STAT(ctpio_erase, CTPIO_ERASE),
 };
 
 #define HUNT_COMMON_STAT_MASK ((1ULL << EF10_STAT_port_tx_bytes) |     \
@@ -1646,6 +1762,43 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
        (1ULL << EF10_STAT_port_rx_dp_hlb_fetch) |                      \
        (1ULL << EF10_STAT_port_rx_dp_hlb_wait))
 
+/* These statistics are only provided if the NIC supports MC_CMD_MAC_STATS_V2,
+ * indicated by returning a value >= MC_CMD_MAC_NSTATS_V2 in
+ * MC_CMD_GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS.
+ * These bits are in the second u64 of the raw mask.
+ */
+#define EF10_FEC_STAT_MASK (                                           \
+       (1ULL << (EF10_STAT_fec_uncorrected_errors - 64)) |             \
+       (1ULL << (EF10_STAT_fec_corrected_errors - 64)) |               \
+       (1ULL << (EF10_STAT_fec_corrected_symbols_lane0 - 64)) |        \
+       (1ULL << (EF10_STAT_fec_corrected_symbols_lane1 - 64)) |        \
+       (1ULL << (EF10_STAT_fec_corrected_symbols_lane2 - 64)) |        \
+       (1ULL << (EF10_STAT_fec_corrected_symbols_lane3 - 64)))
+
+/* These statistics are only provided if the NIC supports MC_CMD_MAC_STATS_V3,
+ * indicated by returning a value >= MC_CMD_MAC_NSTATS_V3 in
+ * MC_CMD_GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS.
+ * These bits are in the second u64 of the raw mask.
+ */
+#define EF10_CTPIO_STAT_MASK (                                         \
+       (1ULL << (EF10_STAT_ctpio_dmabuf_start - 64)) |                 \
+       (1ULL << (EF10_STAT_ctpio_vi_busy_fallback - 64)) |             \
+       (1ULL << (EF10_STAT_ctpio_long_write_success - 64)) |           \
+       (1ULL << (EF10_STAT_ctpio_missing_dbell_fail - 64)) |           \
+       (1ULL << (EF10_STAT_ctpio_overflow_fail - 64)) |                \
+       (1ULL << (EF10_STAT_ctpio_underflow_fail - 64)) |               \
+       (1ULL << (EF10_STAT_ctpio_timeout_fail - 64)) |                 \
+       (1ULL << (EF10_STAT_ctpio_noncontig_wr_fail - 64)) |            \
+       (1ULL << (EF10_STAT_ctpio_frm_clobber_fail - 64)) |             \
+       (1ULL << (EF10_STAT_ctpio_invalid_wr_fail - 64)) |              \
+       (1ULL << (EF10_STAT_ctpio_vi_clobber_fallback - 64)) |          \
+       (1ULL << (EF10_STAT_ctpio_unqualified_fallback - 64)) |         \
+       (1ULL << (EF10_STAT_ctpio_runt_fallback - 64)) |                \
+       (1ULL << (EF10_STAT_ctpio_success - 64)) |                      \
+       (1ULL << (EF10_STAT_ctpio_fallback - 64)) |                     \
+       (1ULL << (EF10_STAT_ctpio_poison - 64)) |                       \
+       (1ULL << (EF10_STAT_ctpio_erase - 64)))
+
 static u64 efx_ef10_raw_stat_mask(struct efx_nic *efx)
 {
        u64 raw_mask = HUNT_COMMON_STAT_MASK;
@@ -1684,10 +1837,22 @@ static void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask)
        if (nic_data->datapath_caps &
            (1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN)) {
                raw_mask[0] |= ~((1ULL << EF10_STAT_rx_unicast) - 1);
-               raw_mask[1] = (1ULL << (EF10_STAT_COUNT - 63)) - 1;
+               raw_mask[1] = (1ULL << (EF10_STAT_V1_COUNT - 64)) - 1;
        } else {
                raw_mask[1] = 0;
        }
+       /* Only show FEC stats when NIC supports MC_CMD_MAC_STATS_V2 */
+       if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V2)
+               raw_mask[1] |= EF10_FEC_STAT_MASK;
+
+       /* CTPIO stats appear in V3. Only show them on devices that actually
+        * support CTPIO. Although this driver doesn't use CTPIO others might,
+        * and we may be reporting the stats for the underlying port.
+        */
+       if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V3 &&
+           (nic_data->datapath_caps2 &
+            (1 << MC_CMD_GET_CAPABILITIES_V4_OUT_CTPIO_LBN)))
+               raw_mask[1] |= EF10_CTPIO_STAT_MASK;
 
 #if BITS_PER_LONG == 64
        BUILD_BUG_ON(BITS_TO_LONGS(EF10_STAT_COUNT) != 2);
@@ -1791,7 +1956,7 @@ static int efx_ef10_try_update_nic_stats_pf(struct efx_nic *efx)
 
        dma_stats = efx->stats_buffer.addr;
 
-       generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
+       generation_end = dma_stats[efx->num_mac_stats - 1];
        if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
                return 0;
        rmb();
@@ -1839,7 +2004,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
        DECLARE_BITMAP(mask, EF10_STAT_COUNT);
        __le64 generation_start, generation_end;
        u64 *stats = nic_data->stats;
-       u32 dma_len = MC_CMD_MAC_NSTATS * sizeof(u64);
+       u32 dma_len = efx->num_mac_stats * sizeof(u64);
        struct efx_buffer stats_buf;
        __le64 *dma_stats;
        int rc;
@@ -1864,7 +2029,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
        }
 
        dma_stats = stats_buf.addr;
-       dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
+       dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID;
 
        MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, stats_buf.dma_addr);
        MCDI_POPULATE_DWORD_1(inbuf, MAC_STATS_IN_CMD,
@@ -1883,7 +2048,7 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
                goto out;
        }
 
-       generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
+       generation_end = dma_stats[efx->num_mac_stats - 1];
        if (generation_end == EFX_MC_STATS_GENERATION_INVALID) {
                WARN_ON_ONCE(1);
                goto out;
@@ -1951,8 +2116,9 @@ static void efx_ef10_push_irq_moderation(struct efx_channel *channel)
        } else {
                unsigned int ticks = efx_usecs_to_ticks(efx, usecs);
 
-               EFX_POPULATE_DWORD_2(timer_cmd, ERF_DZ_TC_TIMER_MODE, mode,
-                                    ERF_DZ_TC_TIMER_VAL, ticks);
+               EFX_POPULATE_DWORD_3(timer_cmd, ERF_DZ_TC_TIMER_MODE, mode,
+                                    ERF_DZ_TC_TIMER_VAL, ticks,
+                                    ERF_FZ_TC_TMR_REL_VAL, ticks);
                efx_writed_page(efx, &timer_cmd, ER_DZ_EVQ_TMR,
                                channel->channel);
        }
@@ -2263,12 +2429,21 @@ 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;
+
        /* 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);
@@ -2294,14 +2469,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);
@@ -2327,12 +2504,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) {
@@ -3233,8 +3411,8 @@ static u16 efx_ef10_handle_rx_event_errors(struct efx_channel *channel,
                if (unlikely(rx_encap_hdr != ESE_EZ_ENCAP_HDR_VXLAN &&
                             ((rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
                               rx_l3_class != ESE_DZ_L3_CLASS_IP6) ||
-                             (rx_l4_class != ESE_DZ_L4_CLASS_TCP &&
-                              rx_l4_class != ESE_DZ_L4_CLASS_UDP))))
+                             (rx_l4_class != ESE_FZ_L4_CLASS_TCP &&
+                              rx_l4_class != ESE_FZ_L4_CLASS_UDP))))
                        netdev_WARN(efx->net_dev,
                                    "invalid class for RX_TCPUDP_CKSUM_ERR: event="
                                    EFX_QWORD_FMT "\n",
@@ -3271,8 +3449,8 @@ static u16 efx_ef10_handle_rx_event_errors(struct efx_channel *channel,
                                    EFX_QWORD_VAL(*event));
                else if (unlikely((rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
                                   rx_l3_class != ESE_DZ_L3_CLASS_IP6) ||
-                                 (rx_l4_class != ESE_DZ_L4_CLASS_TCP &&
-                                  rx_l4_class != ESE_DZ_L4_CLASS_UDP)))
+                                 (rx_l4_class != ESE_FZ_L4_CLASS_TCP &&
+                                  rx_l4_class != ESE_FZ_L4_CLASS_UDP)))
                        netdev_WARN(efx->net_dev,
                                    "invalid class for RX_TCP_UDP_INNER_CHKSUM_ERR: event="
                                    EFX_QWORD_FMT "\n",
@@ -3307,7 +3485,7 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel,
        next_ptr_lbits = EFX_QWORD_FIELD(*event, ESF_DZ_RX_DSC_PTR_LBITS);
        rx_queue_label = EFX_QWORD_FIELD(*event, ESF_DZ_RX_QLABEL);
        rx_l3_class = EFX_QWORD_FIELD(*event, ESF_DZ_RX_L3_CLASS);
-       rx_l4_class = EFX_QWORD_FIELD(*event, ESF_DZ_RX_L4_CLASS);
+       rx_l4_class = EFX_QWORD_FIELD(*event, ESF_FZ_RX_L4_CLASS);
        rx_cont = EFX_QWORD_FIELD(*event, ESF_DZ_RX_CONT);
        rx_encap_hdr =
                nic_data->datapath_caps &
@@ -3385,8 +3563,8 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel,
                                                         rx_l3_class, rx_l4_class,
                                                         event);
        } else {
-               bool tcpudp = rx_l4_class == ESE_DZ_L4_CLASS_TCP ||
-                             rx_l4_class == ESE_DZ_L4_CLASS_UDP;
+               bool tcpudp = rx_l4_class == ESE_FZ_L4_CLASS_TCP ||
+                             rx_l4_class == ESE_FZ_L4_CLASS_UDP;
 
                switch (rx_encap_hdr) {
                case ESE_EZ_ENCAP_HDR_VXLAN: /* VxLAN or GENEVE */
@@ -3407,7 +3585,7 @@ static int efx_ef10_handle_rx_event(struct efx_channel *channel,
                }
        }
 
-       if (rx_l4_class == ESE_DZ_L4_CLASS_TCP)
+       if (rx_l4_class == ESE_FZ_L4_CLASS_TCP)
                flags |= EFX_RX_PKT_TCP;
 
        channel->irq_mod_score += 2 * n_packets;
@@ -3427,31 +3605,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);
-       efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
 
-       return tx_descs;
+       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;
+       }
+
+       /* 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
@@ -3513,7 +3752,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)
@@ -3553,13 +3791,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);
@@ -6034,7 +6266,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);
@@ -6392,7 +6625,7 @@ out_unlock:
 
 const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
        .is_vf = true,
-       .mem_bar = EFX_MEM_VF_BAR,
+       .mem_bar = efx_ef10_vf_mem_bar,
        .mem_map_size = efx_ef10_mem_map_size,
        .probe = efx_ef10_probe_vf,
        .remove = efx_ef10_remove,
@@ -6500,7 +6733,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
 
 const struct efx_nic_type efx_hunt_a0_nic_type = {
        .is_vf = false,
-       .mem_bar = EFX_MEM_BAR,
+       .mem_bar = efx_ef10_pf_mem_bar,
        .mem_map_size = efx_ef10_mem_map_size,
        .probe = efx_ef10_probe_pf,
        .remove = efx_ef10_remove,