net: atlantic: PTP statistics
authorPavel Belous <pbelous@marvell.com>
Mon, 20 Jul 2020 18:32:38 +0000 (21:32 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2020 01:07:38 +0000 (18:07 -0700)
This patch adds PTP rings statistics. Before that
these were missing from overall stats, hardening debugging
and analysis.

Signed-off-by: Pavel Belous <pbelous@marvell.com>
Signed-off-by: Mark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
drivers/net/ethernet/aquantia/atlantic/aq_ptp.h

index 9e18d30..1ab5314 100644 (file)
@@ -177,6 +177,11 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev)
        u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
                      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
 
+#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+       n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
+                  tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
+#endif
+
 #if IS_ENABLED(CONFIG_MACSEC)
        if (nic->macsec_cfg) {
                n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
@@ -199,6 +204,9 @@ static void aq_ethtool_stats(struct net_device *ndev,
 
        memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
        data = aq_nic_get_stats(aq_nic, data);
+#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+       data = aq_ptp_get_stats(aq_nic, data);
+#endif
 #if IS_ENABLED(CONFIG_MACSEC)
        data = aq_macsec_get_stats(aq_nic, data);
 #endif
@@ -275,6 +283,35 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
                                }
                        }
                }
+#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+               if (nic->aq_ptp) {
+                       const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
+                       const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
+                       unsigned int ptp_ring_idx =
+                               aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
+
+                       snprintf(tc_string, 8, "PTP ");
+
+                       for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
+                               for (si = 0; si < rx_stat_cnt; si++) {
+                                       snprintf(p, ETH_GSTRING_LEN,
+                                                aq_ethtool_queue_rx_stat_names[si],
+                                                tc_string,
+                                                i ? PTP_HWST_RING_IDX : ptp_ring_idx);
+                                       p += ETH_GSTRING_LEN;
+                               }
+                               if (i >= tx_ring_cnt)
+                                       continue;
+                               for (si = 0; si < tx_stat_cnt; si++) {
+                                       snprintf(p, ETH_GSTRING_LEN,
+                                                aq_ethtool_queue_tx_stat_names[si],
+                                                tc_string,
+                                                i ? PTP_HWST_RING_IDX : ptp_ring_idx);
+                                       p += ETH_GSTRING_LEN;
+                               }
+                       }
+               }
+#endif
 #if IS_ENABLED(CONFIG_MACSEC)
                if (!nic->macsec_cfg)
                        break;
index ec6aa9b..06de19f 100644 (file)
@@ -81,6 +81,8 @@ struct aq_ptp_s {
 
        bool extts_pin_enabled;
        u64 last_sync1588_ts;
+
+       bool a1_ptp;
 };
 
 struct ptp_tm_offset {
@@ -947,21 +949,6 @@ void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic)
        aq_ring_rx_deinit(&aq_ptp->ptp_rx);
 }
 
-#define PTP_8TC_RING_IDX             8
-#define PTP_4TC_RING_IDX            16
-#define PTP_HWST_RING_IDX           31
-
-/* Index must be 8 (8 TCs) or 16 (4 TCs).
- * It depends on Traffic Class mode.
- */
-static unsigned int ptp_ring_idx(const enum aq_tc_mode tc_mode)
-{
-       if (tc_mode == AQ_TC_MODE_8TCS)
-               return PTP_8TC_RING_IDX;
-
-       return PTP_4TC_RING_IDX;
-}
-
 int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
 {
        struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
@@ -973,7 +960,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
        if (!aq_ptp)
                return 0;
 
-       tx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
+       tx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
 
        ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic,
                                tx_ring_idx, &aq_nic->aq_nic_cfg);
@@ -982,7 +969,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
                goto err_exit;
        }
 
-       rx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
+       rx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode);
 
        ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic,
                                rx_ring_idx, &aq_nic->aq_nic_cfg);
@@ -1174,11 +1161,17 @@ static void aq_ptp_poll_sync_work_cb(struct work_struct *w);
 
 int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
 {
+       bool a1_ptp = ATL_HW_IS_CHIP_FEATURE(aq_nic->aq_hw, ATLANTIC);
        struct hw_atl_utils_mbox mbox;
        struct ptp_clock *clock;
        struct aq_ptp_s *aq_ptp;
        int err = 0;
 
+       if (!a1_ptp) {
+               aq_nic->aq_ptp = NULL;
+               return 0;
+       }
+
        if (!aq_nic->aq_hw_ops->hw_get_ptp_ts) {
                aq_nic->aq_ptp = NULL;
                return 0;
@@ -1205,6 +1198,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
        }
 
        aq_ptp->aq_nic = aq_nic;
+       aq_ptp->a1_ptp = a1_ptp;
 
        spin_lock_init(&aq_ptp->ptp_lock);
        spin_lock_init(&aq_ptp->ptp_ring_lock);
@@ -1395,4 +1389,36 @@ static void aq_ptp_poll_sync_work_cb(struct work_struct *w)
                schedule_delayed_work(&aq_ptp->poll_sync, timeout);
        }
 }
+
+int aq_ptp_get_ring_cnt(struct aq_nic_s *aq_nic, const enum atl_ring_type ring_type)
+{
+       if (!aq_nic->aq_ptp)
+               return 0;
+
+       /* Additional RX ring is allocated for PTP HWTS on A1 */
+       return (aq_nic->aq_ptp->a1_ptp && ring_type == ATL_RING_RX) ? 2 : 1;
+}
+
+u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data)
+{
+       struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
+       unsigned int count = 0U;
+
+       if (!aq_ptp)
+               return data;
+
+       count = aq_ring_fill_stats_data(&aq_ptp->ptp_rx, data);
+       data += count;
+       count = aq_ring_fill_stats_data(&aq_ptp->ptp_tx, data);
+       data += count;
+
+       if (aq_ptp->a1_ptp) {
+               /* Only Receive ring for HWTS */
+               count = aq_ring_fill_stats_data(&aq_ptp->hwts_rx, data);
+               data += count;
+       }
+
+       return data;
+}
+
 #endif
index 2319064..28ccb7c 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Aquantia Corporation Network Driver
- * Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved
+/* Atlantic Network Driver
+ *
+ * Copyright (C) 2014-2019 aQuantia Corporation
+ * Copyright (C) 2019-2020 Marvell International Ltd.
  */
 
 /* File aq_ptp.h: Declaration of PTP functions.
 
 #include <linux/net_tstamp.h>
 
+#include "aq_ring.h"
+
+#define PTP_8TC_RING_IDX             8
+#define PTP_4TC_RING_IDX            16
+#define PTP_HWST_RING_IDX           31
+
+/* Index must to be 8 (8 TCs) or 16 (4 TCs).
+ * It depends from Traffic Class mode.
+ */
+static inline unsigned int aq_ptp_ring_idx(const enum aq_tc_mode tc_mode)
+{
+       if (tc_mode == AQ_TC_MODE_8TCS)
+               return PTP_8TC_RING_IDX;
+
+       return PTP_4TC_RING_IDX;
+}
+
 #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
 
 /* Common functions */
@@ -55,6 +74,10 @@ struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp);
 
 int aq_ptp_link_change(struct aq_nic_s *aq_nic);
 
+/* PTP ring statistics */
+int aq_ptp_get_ring_cnt(struct aq_nic_s *aq_nic, const enum atl_ring_type ring_type);
+u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data);
+
 #else
 
 static inline int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)