diff mbox series

[v4,1/8] mt76 - mt7915: Add ethtool stats support.

Message ID 20210723154627.10078-1-greearb@candelatech.com
State Superseded
Headers show
Series [v4,1/8] mt76 - mt7915: Add ethtool stats support. | expand

Commit Message

Ben Greear July 23, 2021, 3:46 p.m. UTC
From: Ben Greear <greearb@candelatech.com>

This exposes some tx-path stats to the ethtool API, so that
ethtool -S wlanX provides some more useful info.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 
v4: move ethtool code to main.c
  Re-work the 2/8 patch per review.
  Did not try to refactor the station walk per comments on 3/8, I saw
  no clean way to do that.

.../net/wireless/mediatek/mt76/mt7915/main.c  | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)

Comments

Lorenzo Bianconi July 24, 2021, 12:36 p.m. UTC | #1
> From: Ben Greear <greearb@candelatech.com>

> 

> This exposes some tx-path stats to the ethtool API, so that

> ethtool -S wlanX provides some more useful info.

> 

> Signed-off-by: Ben Greear <greearb@candelatech.com>

> ---

>  

> v4: move ethtool code to main.c

>   Re-work the 2/8 patch per review.

>   Did not try to refactor the station walk per comments on 3/8, I saw

>   no clean way to do that.

> 

> .../net/wireless/mediatek/mt76/mt7915/main.c  | 136 ++++++++++++++++++

>  1 file changed, 136 insertions(+)

> 

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> index 48b5e2051bad..d0288fe2abdf 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> @@ -1028,6 +1028,139 @@ static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,

>  	mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);

>  }

>  

> +static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {

> +	"tx_ampdu_len:0-1",

> +	"tx_ampdu_len:2-10",

> +	"tx_ampdu_len:11-19",

> +	"tx_ampdu_len:20-28",

> +	"tx_ampdu_len:29-37",

> +	"tx_ampdu_len:38-46",

> +	"tx_ampdu_len:47-55",

> +	"tx_ampdu_len:56-79",

> +	"tx_ampdu_len:80-103",

> +	"tx_ampdu_len:104-127",

> +	"tx_ampdu_len:128-151",

> +	"tx_ampdu_len:152-175",

> +	"tx_ampdu_len:176-199",

> +	"tx_ampdu_len:200-223",

> +	"tx_ampdu_len:224-247",

> +	"ba_miss_count",

> +	"tx_beamformer_ppdu_iBF",

> +	"tx_beamformer_ppdu_eBF",

> +	"tx_beamformer_rx_feedback_all",

> +	"tx_beamformer_rx_feedback_he",

> +	"tx_beamformer_rx_feedback_vht",

> +	"tx_beamformer_rx_feedback_ht",

> +	"tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */

> +	"tx_beamformer_rx_feedback_nc",

> +	"tx_beamformer_rx_feedback_nr",

> +	"tx_beamformee_ok_feedback_pkts",

> +	"tx_beamformee_feedback_trig",

> +	"tx_mu_beamforming",

> +	"tx_mu_mpdu",

> +	"tx_mu_successful_mpdu",

> +	"tx_su_successful_mpdu",

> +	"tx_msdu_pack_1",

> +	"tx_msdu_pack_2",

> +	"tx_msdu_pack_3",

> +	"tx_msdu_pack_4",

> +	"tx_msdu_pack_5",

> +	"tx_msdu_pack_6",

> +	"tx_msdu_pack_7",

> +	"tx_msdu_pack_8",

> +};

> +

> +#define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)

> +

> +/* Ethtool related API */

> +void mt7915_get_et_strings(struct ieee80211_hw *hw,

> +			   struct ieee80211_vif *vif,

> +			   u32 sset, u8 *data)


please make them static

Regards,
Lorenzo

> +{

> +	if (sset == ETH_SS_STATS)

> +		memcpy(data, *mt7915_gstrings_stats,

> +		       sizeof(mt7915_gstrings_stats));

> +}

> +

> +int mt7915_get_et_sset_count(struct ieee80211_hw *hw,

> +			     struct ieee80211_vif *vif, int sset)

> +{

> +	if (sset == ETH_SS_STATS)

> +		return MT7915_SSTATS_LEN;

> +

> +	return 0;

> +}

> +

> +void mt7915_get_et_stats(struct ieee80211_hw *hw,

> +			 struct ieee80211_vif *vif,

> +			 struct ethtool_stats *stats, u64 *data)

> +{

> +	struct mt7915_dev *dev = mt7915_hw_dev(hw);

> +	struct mt7915_phy *phy = mt7915_hw_phy(hw);

> +

> +	/* TODO:  These are mostly dev-wide stats at this point.

> +	 *  Get some per-vif stats?

> +	 */

> +

> +	/* See mt7915_ampdu_stat_read_phy, etc */

> +	bool ext_phy = phy != &dev->phy;

> +	int i, n, cnt;

> +	int ei = 0;

> +

> +	if (!phy)

> +		return;

> +

> +	/* Tx ampdu stat */

> +	n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;

> +	for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)

> +		data[ei++] = dev->mt76.aggr_stats[i + n];

> +

> +	data[ei++] = phy->mib.ba_miss_cnt;

> +

> +	/* Tx Beamformer monitor */

> +	cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));

> +	data[ei++] = FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);

> +

> +	/* Tx Beamformer Rx feedback monitor */

> +	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HE, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HT, cnt);

> +

> +	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NC, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NR, cnt);

> +

> +	/* Tx Beamformee Rx NDPA & Tx feedback report */

> +	cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));

> +	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);

> +	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);

> +

> +	/* Tx SU & MU counters */

> +	cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));

> +	data[ei++] = FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));

> +	data[ei++] = cnt;

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));

> +	data[ei++] = cnt; /* MU MPDU SUccessful */

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));

> +	data[ei++] = cnt; /* SU MPDU successful */

> +

> +	/* TODO:  External phy too?? */

> +

> +	/* Tx amsdu info (pack-count histogram) */

> +	for (i = 0; i < 8; i++)

> +		data[ei++] = mt76_rr(dev,  MT_PLE_AMSDU_PACK_MSDU_CNT(i));

> +

> +	WARN_ON(ei != MT7915_SSTATS_LEN);

> +}

> +

>  const struct ieee80211_ops mt7915_ops = {

>  	.tx = mt7915_tx,

>  	.start = mt7915_start,

> @@ -1052,6 +1185,9 @@ const struct ieee80211_ops mt7915_ops = {

>  	.get_txpower = mt76_get_txpower,

>  	.channel_switch_beacon = mt7915_channel_switch_beacon,

>  	.get_stats = mt7915_get_stats,

> +	.get_et_sset_count = mt7915_get_et_sset_count,

> +	.get_et_stats = mt7915_get_et_stats,

> +	.get_et_strings = mt7915_get_et_strings,

>  	.get_tsf = mt7915_get_tsf,

>  	.set_tsf = mt7915_set_tsf,

>  	.offset_tsf = mt7915_offset_tsf,

> -- 

> 2.20.1

>
Lorenzo Bianconi July 24, 2021, 12:39 p.m. UTC | #2
> From: Ben Greear <greearb@candelatech.com>

> 

> These counters are clear-on-read, so we need to accumulate

> them in the update_stats poll logic, and read the accumulated

> values instead of directly doing register reads when reporting

> to debugfs and ethtool stats.

> 

> Signed-off-by: Ben Greear <greearb@candelatech.com>

> ---

>  .../net/wireless/mediatek/mt76/mt7915/debugfs.c | 17 ++++++++---------

>  drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 13 ++++++++++++-

>  .../net/wireless/mediatek/mt76/mt7915/main.c    | 16 +++++-----------

>  .../net/wireless/mediatek/mt76/mt7915/mt7915.h  |  4 ++++

>  4 files changed, 29 insertions(+), 21 deletions(-)

> 

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> index 1a48b09d0cb7..35248d182728 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> @@ -152,6 +152,7 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)

>  		"BW20", "BW40", "BW80", "BW160"

>  	};

>  	int cnt;

> +	struct mib_stats *mib = &phy->mib;


according to the check below this can be a NULL pointer dereference

>  

>  	if (!phy)

>  		return;

> @@ -187,15 +188,13 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)

>  		   FIELD_GET(MT_ETBF_TX_FB_TRI, cnt));

>  

>  	/* Tx SU & MU counters */

> -	cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));

> -	seq_printf(s, "Tx multi-user Beamforming counts: %ld\n",

> -		   FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt));

> -	cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));

> -	seq_printf(s, "Tx multi-user MPDU counts: %d\n", cnt);

> -	cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));

> -	seq_printf(s, "Tx multi-user successful MPDU counts: %d\n", cnt);

> -	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));

> -	seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt);

> +	seq_printf(s, "Tx multi-user Beamforming counts: %d\n",

> +		   mib->tx_bf_cnt);

> +	seq_printf(s, "Tx multi-user MPDU counts: %d\n", mib->tx_mu_mpdu_cnt);

> +	seq_printf(s, "Tx multi-user successful MPDU counts: %d\n",

> +		   mib->tx_mu_acked_mpdu_cnt);

> +	seq_printf(s, "Tx single-user successful MPDU counts: %d\n",

> +		   mib->tx_su_acked_mpdu_cnt);

>  

>  	seq_puts(s, "\n");

>  }

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> index 6f445999e516..064d754e0565 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> @@ -1890,10 +1890,21 @@ mt7915_mac_update_stats(struct mt7915_phy *phy)

>  	struct mt7915_dev *dev = phy->dev;

>  	struct mib_stats *mib = &phy->mib;

>  	bool ext_phy = phy != &dev->phy;

> -	int i, aggr0, aggr1;

> +	int i, aggr0, aggr1, cnt;

>  

>  	mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),

>  					   MT_MIB_SDR3_FCS_ERR_MASK);

> +	cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));

> +	mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));

> +	mib->tx_mu_mpdu_cnt += cnt;

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));

> +	mib->tx_mu_acked_mpdu_cnt += cnt;

> +

> +	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));

> +	mib->tx_su_acked_mpdu_cnt += cnt;

>  

>  	aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;

>  	for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> index de083008663e..be6444650afe 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> @@ -1131,6 +1131,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,

>  	struct mt7915_sta *msta;

>  	struct mt7915_sta_stats *mstats;

>  	bool found_sta = false;

> +	struct mib_stats *mib = &phy->mib;

>  

>  	/* See mt7915_ampdu_stat_read_phy, etc */

>  	bool ext_phy = phy != &dev->phy;

> @@ -1170,17 +1171,10 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,

>  	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);

>  

>  	/* Tx SU & MU counters */

> -	cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));

> -	data[ei++] = FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);

> -

> -	cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));

> -	data[ei++] = cnt;

> -

> -	cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));

> -	data[ei++] = cnt; /* MU MPDU SUccessful */

> -

> -	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));

> -	data[ei++] = cnt; /* SU MPDU successful */

> +	data[ei++] = mib->tx_bf_cnt;

> +	data[ei++] = mib->tx_mu_mpdu_cnt;

> +	data[ei++] = mib->tx_mu_acked_mpdu_cnt;

> +	data[ei++] = mib->tx_su_acked_mpdu_cnt;

>  

>  	/* TODO:  External phy too?? */

>  

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> index a8617ba69a21..26f2befc46dd 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> @@ -116,6 +116,10 @@ struct mib_stats {

>  	u32 rts_cnt;

>  	u32 rts_retries_cnt;

>  	u32 ba_miss_cnt;

> +	u32 tx_bf_cnt;

> +	u32 tx_mu_mpdu_cnt;

> +	u32 tx_mu_acked_mpdu_cnt;

> +	u32 tx_su_acked_mpdu_cnt;

>  	/* Add more stats here, updated from mac_update_stats */

>  };

>  

> -- 

> 2.20.1

>
Lorenzo Bianconi July 24, 2021, 12:40 p.m. UTC | #3
On Jul 23, greearb@candelatech.com wrote:
> From: Ben Greear <greearb@candelatech.com>

> 

> These are clear-on-read, so accumulate them in the update_stats

> polling method, then access them via the mib structure

> when reading them from debugfs/ethtool.

> 

> Signed-off-by: Ben Greear <greearb@candelatech.com>

> ---

>  .../wireless/mediatek/mt76/mt7915/debugfs.c   | 44 +++++++++----------

>  .../net/wireless/mediatek/mt76/mt7915/mac.c   | 19 ++++++++

>  .../net/wireless/mediatek/mt76/mt7915/main.c  | 28 +++++-------

>  .../wireless/mediatek/mt76/mt7915/mt7915.h    | 15 +++++++

>  4 files changed, 66 insertions(+), 40 deletions(-)

> 

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> index 35248d182728..91664ac63a8d 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c

> @@ -146,46 +146,42 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,

>  static void

>  mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)

>  {

> -	struct mt7915_dev *dev = s->private;

> -	bool ext_phy = phy != &dev->phy;

>  	static const char * const bw[] = {

>  		"BW20", "BW40", "BW80", "BW160"

>  	};

> -	int cnt;

> -	struct mib_stats *mib = &phy->mib;

> +	struct mib_stats *mib;

>  

>  	if (!phy)

>  		return;

>  

> +	mib = &phy->mib;


please merge it in the previous patch

> +

>  	/* Tx Beamformer monitor */

>  	seq_puts(s, "\nTx Beamformer applied PPDU counts: ");

>  

> -	cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));

> -	seq_printf(s, "iBF: %ld, eBF: %ld\n",

> -		   FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt),

> -		   FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt));

> +	seq_printf(s, "iBF: %d, eBF: %d\n",

> +		   mib->tx_bf_ibf_ppdu_cnt,

> +		   mib->tx_bf_ebf_ppdu_cnt);

>  

>  	/* Tx Beamformer Rx feedback monitor */

>  	seq_puts(s, "Tx Beamformer Rx feedback statistics: ");

>  

> -	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));

> -	seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld, ",

> -		   FIELD_GET(MT_ETBF_RX_FB_ALL, cnt),

> -		   FIELD_GET(MT_ETBF_RX_FB_HE, cnt),

> -		   FIELD_GET(MT_ETBF_RX_FB_VHT, cnt),

> -		   FIELD_GET(MT_ETBF_RX_FB_HT, cnt));

> -	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));

> -	seq_printf(s, "%s, NC: %ld, NR: %ld\n",

> -		   bw[FIELD_GET(MT_ETBF_RX_FB_BW, cnt)],

> -		   FIELD_GET(MT_ETBF_RX_FB_NC, cnt),

> -		   FIELD_GET(MT_ETBF_RX_FB_NR, cnt));

> +	seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",

> +		   mib->tx_bf_rx_fb_all_cnt,

> +		   mib->tx_bf_rx_fb_he_cnt,

> +		   mib->tx_bf_rx_fb_vht_cnt,

> +		   mib->tx_bf_rx_fb_ht_cnt);

> +

> +	seq_printf(s, "%s, NC: %d, NR: %d\n",

> +		   bw[mib->tx_bf_rx_fb_bw],

> +		   mib->tx_bf_rx_fb_nc_cnt,

> +		   mib->tx_bf_rx_fb_nr_cnt);

>  

>  	/* Tx Beamformee Rx NDPA & Tx feedback report */

> -	cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));

> -	seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n",

> -		   FIELD_GET(MT_ETBF_TX_FB_CPL, cnt));

> -	seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n",

> -		   FIELD_GET(MT_ETBF_TX_FB_TRI, cnt));

> +	seq_printf(s, "Tx Beamformee successful feedback frames: %d\n",

> +		   mib->tx_bf_fb_cpl_cnt);

> +	seq_printf(s, "Tx Beamformee feedback triggered counts: %d\n",

> +		   mib->tx_bf_fb_trig_cnt);

>  

>  	/* Tx SU & MU counters */

>  	seq_printf(s, "Tx multi-user Beamforming counts: %d\n",

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> index 064d754e0565..c395600b378a 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c

> @@ -1906,6 +1906,25 @@ mt7915_mac_update_stats(struct mt7915_phy *phy)

>  	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));

>  	mib->tx_su_acked_mpdu_cnt += cnt;

>  

> +	cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));

> +	mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);

> +	mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);

> +

> +	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));

> +	mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);

> +	mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);

> +	mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);

> +	mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);

> +

> +	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));

> +	mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);

> +	mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);

> +	mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);

> +

> +	cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));

> +	mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);

> +	mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);

> +

>  	aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;

>  	for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {

>  		u32 val;

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> index be6444650afe..885e35bf0fe8 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c

> @@ -1135,7 +1135,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,

>  

>  	/* See mt7915_ampdu_stat_read_phy, etc */

>  	bool ext_phy = phy != &dev->phy;

> -	int i, j, n, cnt, next_ei;

> +	int i, j, n, next_ei;

>  	int ei = 0;

>  

>  	if (!phy)

> @@ -1149,26 +1149,22 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,

>  	data[ei++] = phy->mib.ba_miss_cnt;

>  

>  	/* Tx Beamformer monitor */

> -	cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));

> -	data[ei++] = FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);

> +	data[ei++] = mib->tx_bf_ibf_ppdu_cnt;

> +	data[ei++] = mib->tx_bf_ebf_ppdu_cnt;

>  

>  	/* Tx Beamformer Rx feedback monitor */

> -	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HE, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HT, cnt);

> +	data[ei++] = mib->tx_bf_rx_fb_all_cnt;

> +	data[ei++] = mib->tx_bf_rx_fb_he_cnt;

> +	data[ei++] = mib->tx_bf_rx_fb_vht_cnt;

> +	data[ei++] = mib->tx_bf_rx_fb_ht_cnt;

>  

> -	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NC, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NR, cnt);

> +	data[ei++] = mib->tx_bf_rx_fb_bw;

> +	data[ei++] = mib->tx_bf_rx_fb_nc_cnt;

> +	data[ei++] = mib->tx_bf_rx_fb_nr_cnt;

>  

>  	/* Tx Beamformee Rx NDPA & Tx feedback report */

> -	cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));

> -	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);

> -	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);

> +	data[ei++] = mib->tx_bf_fb_cpl_cnt;

> +	data[ei++] = mib->tx_bf_fb_trig_cnt;

>  

>  	/* Tx SU & MU counters */

>  	data[ei++] = mib->tx_bf_cnt;

> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> index 26f2befc46dd..565766debb5e 100644

> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

> @@ -110,6 +110,7 @@ struct mt7915_vif {

>  	struct cfg80211_bitrate_mask bitrate_mask;

>  };

>  

> +/* per-phy stats.  */

>  struct mib_stats {

>  	u32 ack_fail_cnt;

>  	u32 fcs_err_cnt;

> @@ -120,6 +121,20 @@ struct mib_stats {

>  	u32 tx_mu_mpdu_cnt;

>  	u32 tx_mu_acked_mpdu_cnt;

>  	u32 tx_su_acked_mpdu_cnt;

> +	u32 tx_bf_ibf_ppdu_cnt;

> +	u32 tx_bf_ebf_ppdu_cnt;

> +

> +	u32 tx_bf_rx_fb_all_cnt;

> +	u32 tx_bf_rx_fb_he_cnt;

> +	u32 tx_bf_rx_fb_vht_cnt;

> +	u32 tx_bf_rx_fb_ht_cnt;

> +

> +	u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */

> +	u32 tx_bf_rx_fb_nc_cnt;

> +	u32 tx_bf_rx_fb_nr_cnt;

> +	u32 tx_bf_fb_cpl_cnt;

> +	u32 tx_bf_fb_trig_cnt;

> +

>  	/* Add more stats here, updated from mac_update_stats */

>  };

>  

> -- 

> 2.20.1

>
Kalle Valo July 31, 2021, 7:48 a.m. UTC | #4
greearb@candelatech.com writes:

> From: Ben Greear <greearb@candelatech.com>

>

> This exposes some tx-path stats to the ethtool API, so that

> ethtool -S wlanX provides some more useful info.

>

> Signed-off-by: Ben Greear <greearb@candelatech.com>


The subject style mt76 uses is:

mt76: mt7915: Add ethtool stats support

And no period in the end.

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Ben Greear Aug. 2, 2021, 2:49 p.m. UTC | #5
On 7/31/21 12:48 AM, Kalle Valo wrote:
> greearb@candelatech.com writes:

> 

>> From: Ben Greear <greearb@candelatech.com>

>>

>> This exposes some tx-path stats to the ethtool API, so that

>> ethtool -S wlanX provides some more useful info.

>>

>> Signed-off-by: Ben Greear <greearb@candelatech.com>

> 

> The subject style mt76 uses is:

> 

> mt76: mt7915: Add ethtool stats support

> 

> And no period in the end.


Don't apply the 1/8 series.  I merged two patches based on previous
comment so now it is a x/7 series.  I'll go through and make sure
I have punctuation correct and re-submit that x/7 as needed.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com
diff mbox series

Patch

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 48b5e2051bad..d0288fe2abdf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1028,6 +1028,139 @@  static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
 	mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);
 }
 
+static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"tx_ampdu_len:0-1",
+	"tx_ampdu_len:2-10",
+	"tx_ampdu_len:11-19",
+	"tx_ampdu_len:20-28",
+	"tx_ampdu_len:29-37",
+	"tx_ampdu_len:38-46",
+	"tx_ampdu_len:47-55",
+	"tx_ampdu_len:56-79",
+	"tx_ampdu_len:80-103",
+	"tx_ampdu_len:104-127",
+	"tx_ampdu_len:128-151",
+	"tx_ampdu_len:152-175",
+	"tx_ampdu_len:176-199",
+	"tx_ampdu_len:200-223",
+	"tx_ampdu_len:224-247",
+	"ba_miss_count",
+	"tx_beamformer_ppdu_iBF",
+	"tx_beamformer_ppdu_eBF",
+	"tx_beamformer_rx_feedback_all",
+	"tx_beamformer_rx_feedback_he",
+	"tx_beamformer_rx_feedback_vht",
+	"tx_beamformer_rx_feedback_ht",
+	"tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */
+	"tx_beamformer_rx_feedback_nc",
+	"tx_beamformer_rx_feedback_nr",
+	"tx_beamformee_ok_feedback_pkts",
+	"tx_beamformee_feedback_trig",
+	"tx_mu_beamforming",
+	"tx_mu_mpdu",
+	"tx_mu_successful_mpdu",
+	"tx_su_successful_mpdu",
+	"tx_msdu_pack_1",
+	"tx_msdu_pack_2",
+	"tx_msdu_pack_3",
+	"tx_msdu_pack_4",
+	"tx_msdu_pack_5",
+	"tx_msdu_pack_6",
+	"tx_msdu_pack_7",
+	"tx_msdu_pack_8",
+};
+
+#define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)
+
+/* Ethtool related API */
+void mt7915_get_et_strings(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   u32 sset, u8 *data)
+{
+	if (sset == ETH_SS_STATS)
+		memcpy(data, *mt7915_gstrings_stats,
+		       sizeof(mt7915_gstrings_stats));
+}
+
+int mt7915_get_et_sset_count(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif, int sset)
+{
+	if (sset == ETH_SS_STATS)
+		return MT7915_SSTATS_LEN;
+
+	return 0;
+}
+
+void mt7915_get_et_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 struct ethtool_stats *stats, u64 *data)
+{
+	struct mt7915_dev *dev = mt7915_hw_dev(hw);
+	struct mt7915_phy *phy = mt7915_hw_phy(hw);
+
+	/* TODO:  These are mostly dev-wide stats at this point.
+	 *  Get some per-vif stats?
+	 */
+
+	/* See mt7915_ampdu_stat_read_phy, etc */
+	bool ext_phy = phy != &dev->phy;
+	int i, n, cnt;
+	int ei = 0;
+
+	if (!phy)
+		return;
+
+	/* Tx ampdu stat */
+	n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
+	for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)
+		data[ei++] = dev->mt76.aggr_stats[i + n];
+
+	data[ei++] = phy->mib.ba_miss_cnt;
+
+	/* Tx Beamformer monitor */
+	cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));
+	data[ei++] = FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
+
+	/* Tx Beamformer Rx feedback monitor */
+	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
+
+	cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
+
+	/* Tx Beamformee Rx NDPA & Tx feedback report */
+	cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
+	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
+	data[ei++] = FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
+
+	/* Tx SU & MU counters */
+	cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy));
+	data[ei++] = FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);
+
+	cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));
+	data[ei++] = cnt;
+
+	cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));
+	data[ei++] = cnt; /* MU MPDU SUccessful */
+
+	cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
+	data[ei++] = cnt; /* SU MPDU successful */
+
+	/* TODO:  External phy too?? */
+
+	/* Tx amsdu info (pack-count histogram) */
+	for (i = 0; i < 8; i++)
+		data[ei++] = mt76_rr(dev,  MT_PLE_AMSDU_PACK_MSDU_CNT(i));
+
+	WARN_ON(ei != MT7915_SSTATS_LEN);
+}
+
 const struct ieee80211_ops mt7915_ops = {
 	.tx = mt7915_tx,
 	.start = mt7915_start,
@@ -1052,6 +1185,9 @@  const struct ieee80211_ops mt7915_ops = {
 	.get_txpower = mt76_get_txpower,
 	.channel_switch_beacon = mt7915_channel_switch_beacon,
 	.get_stats = mt7915_get_stats,
+	.get_et_sset_count = mt7915_get_et_sset_count,
+	.get_et_stats = mt7915_get_et_stats,
+	.get_et_strings = mt7915_get_et_strings,
 	.get_tsf = mt7915_get_tsf,
 	.set_tsf = mt7915_set_tsf,
 	.offset_tsf = mt7915_offset_tsf,