]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
sfc_ef100: statistics gathering
authorEdward Cree <ecree@solarflare.com>
Mon, 3 Aug 2020 20:37:20 +0000 (21:37 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Aug 2020 01:22:55 +0000 (18:22 -0700)
MAC stats work much the same as on EF10, with a periodic DMA to a region
 specified via an MCDI.

Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/ef100_netdev.c
drivers/net/ethernet/sfc/ef100_nic.c
drivers/net/ethernet/sfc/ef100_nic.h

index 362a915c836afc4b3d2afdbad7141cc80576e7ad..63c311ba28b93e79bb6a98306cc95f77b3b24343 100644 (file)
@@ -86,6 +86,7 @@ static int ef100_net_stop(struct net_device *net_dev)
 
        netif_stop_queue(net_dev);
        efx_stop_all(efx);
+       efx_mcdi_mac_fini_stats(efx);
        efx_disable_interrupts(efx);
        efx_clear_interrupt_affinity(efx);
        efx_nic_fini_interrupt(efx);
@@ -157,6 +158,10 @@ static int ef100_net_open(struct net_device *net_dev)
         */
        (void) efx_mcdi_poll_reboot(efx);
 
+       rc = efx_mcdi_mac_init_stats(efx);
+       if (rc)
+               goto fail;
+
        efx_start_all(efx);
 
        /* Link state detection is normally event-driven; we have
@@ -212,6 +217,7 @@ static const struct net_device_ops ef100_netdev_ops = {
        .ndo_open               = ef100_net_open,
        .ndo_stop               = ef100_net_stop,
        .ndo_start_xmit         = ef100_hard_start_xmit,
+       .ndo_get_stats64        = efx_net_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = efx_set_rx_mode, /* Lookout */
        .ndo_get_phys_port_id   = efx_get_phys_port_id,
index 1953e16b2b96c16bbcd05bb34984888e23a1609c..c81da0b2f0c1be0bb6def29880f99660700904f8 100644 (file)
@@ -453,6 +453,171 @@ static int ef100_reset(struct efx_nic *efx, enum reset_type reset_type)
        return rc;
 }
 
+static void ef100_common_stat_mask(unsigned long *mask)
+{
+       __set_bit(EF100_STAT_port_rx_packets, mask);
+       __set_bit(EF100_STAT_port_tx_packets, mask);
+       __set_bit(EF100_STAT_port_rx_bytes, mask);
+       __set_bit(EF100_STAT_port_tx_bytes, mask);
+       __set_bit(EF100_STAT_port_rx_multicast, mask);
+       __set_bit(EF100_STAT_port_rx_bad, mask);
+       __set_bit(EF100_STAT_port_rx_align_error, mask);
+       __set_bit(EF100_STAT_port_rx_overflow, mask);
+}
+
+static void ef100_ethtool_stat_mask(unsigned long *mask)
+{
+       __set_bit(EF100_STAT_port_tx_pause, mask);
+       __set_bit(EF100_STAT_port_tx_unicast, mask);
+       __set_bit(EF100_STAT_port_tx_multicast, mask);
+       __set_bit(EF100_STAT_port_tx_broadcast, mask);
+       __set_bit(EF100_STAT_port_tx_lt64, mask);
+       __set_bit(EF100_STAT_port_tx_64, mask);
+       __set_bit(EF100_STAT_port_tx_65_to_127, mask);
+       __set_bit(EF100_STAT_port_tx_128_to_255, mask);
+       __set_bit(EF100_STAT_port_tx_256_to_511, mask);
+       __set_bit(EF100_STAT_port_tx_512_to_1023, mask);
+       __set_bit(EF100_STAT_port_tx_1024_to_15xx, mask);
+       __set_bit(EF100_STAT_port_tx_15xx_to_jumbo, mask);
+       __set_bit(EF100_STAT_port_rx_good, mask);
+       __set_bit(EF100_STAT_port_rx_pause, mask);
+       __set_bit(EF100_STAT_port_rx_unicast, mask);
+       __set_bit(EF100_STAT_port_rx_broadcast, mask);
+       __set_bit(EF100_STAT_port_rx_lt64, mask);
+       __set_bit(EF100_STAT_port_rx_64, mask);
+       __set_bit(EF100_STAT_port_rx_65_to_127, mask);
+       __set_bit(EF100_STAT_port_rx_128_to_255, mask);
+       __set_bit(EF100_STAT_port_rx_256_to_511, mask);
+       __set_bit(EF100_STAT_port_rx_512_to_1023, mask);
+       __set_bit(EF100_STAT_port_rx_1024_to_15xx, mask);
+       __set_bit(EF100_STAT_port_rx_15xx_to_jumbo, mask);
+       __set_bit(EF100_STAT_port_rx_gtjumbo, mask);
+       __set_bit(EF100_STAT_port_rx_bad_gtjumbo, mask);
+       __set_bit(EF100_STAT_port_rx_length_error, mask);
+       __set_bit(EF100_STAT_port_rx_nodesc_drops, mask);
+       __set_bit(GENERIC_STAT_rx_nodesc_trunc, mask);
+       __set_bit(GENERIC_STAT_rx_noskb_drops, mask);
+}
+
+#define EF100_DMA_STAT(ext_name, mcdi_name)                    \
+       [EF100_STAT_ ## ext_name] =                             \
+       { #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
+
+static const struct efx_hw_stat_desc ef100_stat_desc[EF100_STAT_COUNT] = {
+       EF100_DMA_STAT(port_tx_bytes, TX_BYTES),
+       EF100_DMA_STAT(port_tx_packets, TX_PKTS),
+       EF100_DMA_STAT(port_tx_pause, TX_PAUSE_PKTS),
+       EF100_DMA_STAT(port_tx_unicast, TX_UNICAST_PKTS),
+       EF100_DMA_STAT(port_tx_multicast, TX_MULTICAST_PKTS),
+       EF100_DMA_STAT(port_tx_broadcast, TX_BROADCAST_PKTS),
+       EF100_DMA_STAT(port_tx_lt64, TX_LT64_PKTS),
+       EF100_DMA_STAT(port_tx_64, TX_64_PKTS),
+       EF100_DMA_STAT(port_tx_65_to_127, TX_65_TO_127_PKTS),
+       EF100_DMA_STAT(port_tx_128_to_255, TX_128_TO_255_PKTS),
+       EF100_DMA_STAT(port_tx_256_to_511, TX_256_TO_511_PKTS),
+       EF100_DMA_STAT(port_tx_512_to_1023, TX_512_TO_1023_PKTS),
+       EF100_DMA_STAT(port_tx_1024_to_15xx, TX_1024_TO_15XX_PKTS),
+       EF100_DMA_STAT(port_tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS),
+       EF100_DMA_STAT(port_rx_bytes, RX_BYTES),
+       EF100_DMA_STAT(port_rx_packets, RX_PKTS),
+       EF100_DMA_STAT(port_rx_good, RX_GOOD_PKTS),
+       EF100_DMA_STAT(port_rx_bad, RX_BAD_FCS_PKTS),
+       EF100_DMA_STAT(port_rx_pause, RX_PAUSE_PKTS),
+       EF100_DMA_STAT(port_rx_unicast, RX_UNICAST_PKTS),
+       EF100_DMA_STAT(port_rx_multicast, RX_MULTICAST_PKTS),
+       EF100_DMA_STAT(port_rx_broadcast, RX_BROADCAST_PKTS),
+       EF100_DMA_STAT(port_rx_lt64, RX_UNDERSIZE_PKTS),
+       EF100_DMA_STAT(port_rx_64, RX_64_PKTS),
+       EF100_DMA_STAT(port_rx_65_to_127, RX_65_TO_127_PKTS),
+       EF100_DMA_STAT(port_rx_128_to_255, RX_128_TO_255_PKTS),
+       EF100_DMA_STAT(port_rx_256_to_511, RX_256_TO_511_PKTS),
+       EF100_DMA_STAT(port_rx_512_to_1023, RX_512_TO_1023_PKTS),
+       EF100_DMA_STAT(port_rx_1024_to_15xx, RX_1024_TO_15XX_PKTS),
+       EF100_DMA_STAT(port_rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS),
+       EF100_DMA_STAT(port_rx_gtjumbo, RX_GTJUMBO_PKTS),
+       EF100_DMA_STAT(port_rx_bad_gtjumbo, RX_JABBER_PKTS),
+       EF100_DMA_STAT(port_rx_align_error, RX_ALIGN_ERROR_PKTS),
+       EF100_DMA_STAT(port_rx_length_error, RX_LENGTH_ERROR_PKTS),
+       EF100_DMA_STAT(port_rx_overflow, RX_OVERFLOW_PKTS),
+       EF100_DMA_STAT(port_rx_nodesc_drops, RX_NODESC_DROPS),
+       EFX_GENERIC_SW_STAT(rx_nodesc_trunc),
+       EFX_GENERIC_SW_STAT(rx_noskb_drops),
+};
+
+static size_t ef100_describe_stats(struct efx_nic *efx, u8 *names)
+{
+       DECLARE_BITMAP(mask, EF100_STAT_COUNT) = {};
+
+       ef100_ethtool_stat_mask(mask);
+       return efx_nic_describe_stats(ef100_stat_desc, EF100_STAT_COUNT,
+                                     mask, names);
+}
+
+static size_t ef100_update_stats_common(struct efx_nic *efx, u64 *full_stats,
+                                       struct rtnl_link_stats64 *core_stats)
+{
+       struct ef100_nic_data *nic_data = efx->nic_data;
+       DECLARE_BITMAP(mask, EF100_STAT_COUNT) = {};
+       size_t stats_count = 0, index;
+       u64 *stats = nic_data->stats;
+
+       ef100_ethtool_stat_mask(mask);
+
+       if (full_stats) {
+               for_each_set_bit(index, mask, EF100_STAT_COUNT) {
+                       if (ef100_stat_desc[index].name) {
+                               *full_stats++ = stats[index];
+                               ++stats_count;
+                       }
+               }
+       }
+
+       if (!core_stats)
+               return stats_count;
+
+       core_stats->rx_packets = stats[EF100_STAT_port_rx_packets];
+       core_stats->tx_packets = stats[EF100_STAT_port_tx_packets];
+       core_stats->rx_bytes = stats[EF100_STAT_port_rx_bytes];
+       core_stats->tx_bytes = stats[EF100_STAT_port_tx_bytes];
+       core_stats->rx_dropped = stats[EF100_STAT_port_rx_nodesc_drops] +
+                                stats[GENERIC_STAT_rx_nodesc_trunc] +
+                                stats[GENERIC_STAT_rx_noskb_drops];
+       core_stats->multicast = stats[EF100_STAT_port_rx_multicast];
+       core_stats->rx_length_errors =
+                       stats[EF100_STAT_port_rx_gtjumbo] +
+                       stats[EF100_STAT_port_rx_length_error];
+       core_stats->rx_crc_errors = stats[EF100_STAT_port_rx_bad];
+       core_stats->rx_frame_errors =
+                       stats[EF100_STAT_port_rx_align_error];
+       core_stats->rx_fifo_errors = stats[EF100_STAT_port_rx_overflow];
+       core_stats->rx_errors = (core_stats->rx_length_errors +
+                                core_stats->rx_crc_errors +
+                                core_stats->rx_frame_errors);
+
+       return stats_count;
+}
+
+static size_t ef100_update_stats(struct efx_nic *efx,
+                                u64 *full_stats,
+                                struct rtnl_link_stats64 *core_stats)
+{
+       __le64 *mc_stats = kmalloc(array_size(efx->num_mac_stats, sizeof(__le64)), GFP_ATOMIC);
+       struct ef100_nic_data *nic_data = efx->nic_data;
+       DECLARE_BITMAP(mask, EF100_STAT_COUNT) = {};
+       u64 *stats = nic_data->stats;
+
+       ef100_common_stat_mask(mask);
+       ef100_ethtool_stat_mask(mask);
+
+       efx_nic_copy_stats(efx, mc_stats);
+       efx_nic_update_stats(ef100_stat_desc, EF100_STAT_COUNT, mask,
+                            stats, mc_stats, false);
+
+       kfree(mc_stats);
+
+       return ef100_update_stats_common(efx, full_stats, core_stats);
+}
+
 static int efx_ef100_get_phys_port_id(struct efx_nic *efx,
                                      struct netdev_phys_item_id *ppid)
 {
@@ -557,6 +722,11 @@ const struct efx_nic_type ef100_pf_nic_type = {
        .rx_restore_rss_contexts = efx_mcdi_rx_restore_rss_contexts,
 
        .reconfigure_mac = ef100_reconfigure_mac,
+       .describe_stats = ef100_describe_stats,
+       .start_stats = efx_mcdi_mac_start_stats,
+       .update_stats = ef100_update_stats,
+       .pull_stats = efx_mcdi_mac_pull_stats,
+       .stop_stats = efx_mcdi_mac_stop_stats,
 
        /* Per-type bar/size configuration not used on ef100. Location of
         * registers is defined by extended capabilities.
index c8816bc6ae78fd88a4eb8ec0486b190377e696aa..7c2d374900743d2418eeabcb4b9bac8f59772fd2 100644 (file)
@@ -17,6 +17,46 @@ extern const struct efx_nic_type ef100_pf_nic_type;
 int ef100_probe_pf(struct efx_nic *efx);
 void ef100_remove(struct efx_nic *efx);
 
+enum {
+       EF100_STAT_port_tx_bytes = GENERIC_STAT_COUNT,
+       EF100_STAT_port_tx_packets,
+       EF100_STAT_port_tx_pause,
+       EF100_STAT_port_tx_unicast,
+       EF100_STAT_port_tx_multicast,
+       EF100_STAT_port_tx_broadcast,
+       EF100_STAT_port_tx_lt64,
+       EF100_STAT_port_tx_64,
+       EF100_STAT_port_tx_65_to_127,
+       EF100_STAT_port_tx_128_to_255,
+       EF100_STAT_port_tx_256_to_511,
+       EF100_STAT_port_tx_512_to_1023,
+       EF100_STAT_port_tx_1024_to_15xx,
+       EF100_STAT_port_tx_15xx_to_jumbo,
+       EF100_STAT_port_rx_bytes,
+       EF100_STAT_port_rx_packets,
+       EF100_STAT_port_rx_good,
+       EF100_STAT_port_rx_bad,
+       EF100_STAT_port_rx_pause,
+       EF100_STAT_port_rx_unicast,
+       EF100_STAT_port_rx_multicast,
+       EF100_STAT_port_rx_broadcast,
+       EF100_STAT_port_rx_lt64,
+       EF100_STAT_port_rx_64,
+       EF100_STAT_port_rx_65_to_127,
+       EF100_STAT_port_rx_128_to_255,
+       EF100_STAT_port_rx_256_to_511,
+       EF100_STAT_port_rx_512_to_1023,
+       EF100_STAT_port_rx_1024_to_15xx,
+       EF100_STAT_port_rx_15xx_to_jumbo,
+       EF100_STAT_port_rx_gtjumbo,
+       EF100_STAT_port_rx_bad_gtjumbo,
+       EF100_STAT_port_rx_align_error,
+       EF100_STAT_port_rx_length_error,
+       EF100_STAT_port_rx_overflow,
+       EF100_STAT_port_rx_nodesc_drops,
+       EF100_STAT_COUNT
+};
+
 struct ef100_nic_data {
        struct efx_nic *efx;
        struct efx_buffer mcdi_buf;
@@ -26,6 +66,7 @@ struct ef100_nic_data {
        u16 warm_boot_count;
        u8 port_id[ETH_ALEN];
        DECLARE_BITMAP(evq_phases, EFX_MAX_CHANNELS);
+       u64 stats[EF100_STAT_COUNT];
        u16 tso_max_hdr_len;
        u16 tso_max_payload_num_segs;
        u16 tso_max_frames;