Skip to content

Commit

Permalink
net: atlantic: PTP statistics
Browse files Browse the repository at this point in the history
This patch adds PTP rings statistics. Before that
these were missing from overall stats, hardening debugging
and analysis.

Signed-off-by: Pavel Belous <[email protected]>
Signed-off-by: Mark Starovoytov <[email protected]>
Signed-off-by: Igor Russkikh <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Pavel Belous authored and davem330 committed Jul 21, 2020
1 parent aa7e17a commit 14b539a
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 19 deletions.
37 changes: 37 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) +
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
60 changes: 43 additions & 17 deletions drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ struct aq_ptp_s {

bool extts_pin_enabled;
u64 last_sync1588_ts;

bool a1_ptp;
};

struct ptp_tm_offset {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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
27 changes: 25 additions & 2 deletions drivers/net/ethernet/aquantia/atlantic/aq_ptp.h
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -10,6 +12,23 @@

#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 */
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 14b539a

Please sign in to comment.