kernel: support hw flow-offloading counters on newer MediaTek SoCs
The packet processing engine (PPE) found in newer ARM-based MediaTek SoCs provides packet and byte counters for offloaded streams. Import pending patch reading and using those counters. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
		| @@ -0,0 +1,409 @@ | |||||||
|  | From patchwork Wed Nov  2 00:58:01 2022 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org> | ||||||
|  | X-Patchwork-Id: 13027653 | ||||||
|  | X-Patchwork-Delegate: kuba@kernel.org | ||||||
|  | Return-Path: <netdev-owner@kernel.org> | ||||||
|  | Date: Wed, 2 Nov 2022 00:58:01 +0000 | ||||||
|  | From: Daniel Golle <daniel@makrotopia.org> | ||||||
|  | To: Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>, | ||||||
|  |         Sean Wang <sean.wang@mediatek.com>, | ||||||
|  |         Mark Lee <Mark-MC.Lee@mediatek.com>, | ||||||
|  |         "David S. Miller" <davem@davemloft.net>, | ||||||
|  |         Eric Dumazet <edumazet@google.com>, | ||||||
|  |         Jakub Kicinski <kuba@kernel.org>, | ||||||
|  |         Paolo Abeni <pabeni@redhat.com>, | ||||||
|  |         Matthias Brugger <matthias.bgg@gmail.com>, | ||||||
|  |         netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, | ||||||
|  |         linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org | ||||||
|  | Subject: [PATCH v4] net: ethernet: mediatek: ppe: add support for flow | ||||||
|  |  accounting | ||||||
|  | Message-ID: <Y2HAmYYPd77dz+K5@makrotopia.org> | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Disposition: inline | ||||||
|  | Precedence: bulk | ||||||
|  | List-ID: <netdev.vger.kernel.org> | ||||||
|  | X-Mailing-List: netdev@vger.kernel.org | ||||||
|  | X-Patchwork-Delegate: kuba@kernel.org | ||||||
|  |  | ||||||
|  | The PPE units found in MT7622 and newer support packet and byte | ||||||
|  | accounting of hw-offloaded flows. Add support for reading those | ||||||
|  | counters as found in MediaTek's SDK[1]. | ||||||
|  |  | ||||||
|  | [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92 | ||||||
|  | Signed-off-by: Daniel Golle <daniel@makrotopia.org> | ||||||
|  | --- | ||||||
|  | v4: declare function mtk_mib_entry_read as static | ||||||
|  | v3: don't bother to set 'false' values in any zero-initialized struct | ||||||
|  |     use mtk_foe_entry_ib2 | ||||||
|  |     both changes were requested by Felix Fietkau | ||||||
|  |  | ||||||
|  | v2: fix wrong variable name in return value check spotted by Denis Kirjanov | ||||||
|  |  | ||||||
|  |  drivers/net/ethernet/mediatek/mtk_eth_soc.c   |   7 +- | ||||||
|  |  drivers/net/ethernet/mediatek/mtk_eth_soc.h   |   1 + | ||||||
|  |  drivers/net/ethernet/mediatek/mtk_ppe.c       | 110 +++++++++++++++++- | ||||||
|  |  drivers/net/ethernet/mediatek/mtk_ppe.h       |  23 +++- | ||||||
|  |  .../net/ethernet/mediatek/mtk_ppe_debugfs.c   |   9 +- | ||||||
|  |  .../net/ethernet/mediatek/mtk_ppe_offload.c   |   7 ++ | ||||||
|  |  drivers/net/ethernet/mediatek/mtk_ppe_regs.h  |  14 +++ | ||||||
|  |  7 files changed, 166 insertions(+), 5 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c | ||||||
|  | @@ -4084,7 +4084,9 @@ static int mtk_probe(struct platform_dev | ||||||
|  |  			u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; | ||||||
|  |   | ||||||
|  |  			eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, | ||||||
|  | -						   eth->soc->offload_version, i); | ||||||
|  | +						   eth->soc->offload_version, i, | ||||||
|  | +						   eth->soc->has_accounting); | ||||||
|  | + | ||||||
|  |  			if (!eth->ppe[i]) { | ||||||
|  |  				err = -ENOMEM; | ||||||
|  |  				goto err_free_dev; | ||||||
|  | @@ -4204,6 +4206,7 @@ static const struct mtk_soc_data mt7622_ | ||||||
|  |  	.required_pctl = false, | ||||||
|  |  	.offload_version = 2, | ||||||
|  |  	.hash_offset = 2, | ||||||
|  | +	.has_accounting = true, | ||||||
|  |  	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16, | ||||||
|  |  	.txrx = { | ||||||
|  |  		.txd_size = sizeof(struct mtk_tx_dma), | ||||||
|  | @@ -4241,6 +4244,7 @@ static const struct mtk_soc_data mt7629_ | ||||||
|  |  	.hw_features = MTK_HW_FEATURES, | ||||||
|  |  	.required_clks = MT7629_CLKS_BITMAP, | ||||||
|  |  	.required_pctl = false, | ||||||
|  | +	.has_accounting = true, | ||||||
|  |  	.txrx = { | ||||||
|  |  		.txd_size = sizeof(struct mtk_tx_dma), | ||||||
|  |  		.rxd_size = sizeof(struct mtk_rx_dma), | ||||||
|  | @@ -4261,6 +4265,7 @@ static const struct mtk_soc_data mt7986_ | ||||||
|  |  	.offload_version = 2, | ||||||
|  |  	.hash_offset = 4, | ||||||
|  |  	.foe_entry_size = sizeof(struct mtk_foe_entry), | ||||||
|  | +	.has_accounting = true, | ||||||
|  |  	.txrx = { | ||||||
|  |  		.txd_size = sizeof(struct mtk_tx_dma_v2), | ||||||
|  |  		.rxd_size = sizeof(struct mtk_rx_dma_v2), | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h | ||||||
|  | @@ -983,6 +983,7 @@ struct mtk_soc_data { | ||||||
|  |  	u8		hash_offset; | ||||||
|  |  	u16		foe_entry_size; | ||||||
|  |  	netdev_features_t hw_features; | ||||||
|  | +	bool		has_accounting; | ||||||
|  |  	struct { | ||||||
|  |  		u32	txd_size; | ||||||
|  |  		u32	rxd_size; | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_ppe.c | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c | ||||||
|  | @@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_ | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	u32 val; | ||||||
|  | + | ||||||
|  | +	ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val, | ||||||
|  | +				 !(val & MTK_PPE_MIB_SER_CR_ST), | ||||||
|  | +				 20, MTK_PPE_WAIT_TIMEOUT_US); | ||||||
|  | + | ||||||
|  | +	if (ret) | ||||||
|  | +		dev_err(ppe->dev, "MIB table busy"); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets) | ||||||
|  | +{ | ||||||
|  | +	u32 val, cnt_r0, cnt_r1, cnt_r2; | ||||||
|  | +	u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high; | ||||||
|  | + | ||||||
|  | +	val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST; | ||||||
|  | +	ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val); | ||||||
|  | + | ||||||
|  | +	if (mtk_ppe_mib_wait_busy(ppe)) | ||||||
|  | +		return -ETIMEDOUT; | ||||||
|  | + | ||||||
|  | +	cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); | ||||||
|  | +	cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); | ||||||
|  | +	cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2); | ||||||
|  | + | ||||||
|  | +	byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0); | ||||||
|  | +	byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1); | ||||||
|  | +	pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1); | ||||||
|  | +	pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2); | ||||||
|  | +	*bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low; | ||||||
|  | +	*packets = (pkt_cnt_high << 16) | pkt_cnt_low; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) | ||||||
|  |  { | ||||||
|  |  	ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR); | ||||||
|  | @@ -444,6 +484,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp | ||||||
|  |  		hwe->ib1 &= ~MTK_FOE_IB1_STATE; | ||||||
|  |  		hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); | ||||||
|  |  		dma_wmb(); | ||||||
|  | +		if (ppe->accounting) { | ||||||
|  | +			struct mtk_foe_accounting *acct; | ||||||
|  | + | ||||||
|  | +			acct = ppe->acct_table + entry->hash * sizeof(*acct); | ||||||
|  | +			acct->packets = 0; | ||||||
|  | +			acct->bytes = 0; | ||||||
|  | +		} | ||||||
|  |  	} | ||||||
|  |  	entry->hash = 0xffff; | ||||||
|  |   | ||||||
|  | @@ -551,6 +598,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p | ||||||
|  |  	wmb(); | ||||||
|  |  	hwe->ib1 = entry->ib1; | ||||||
|  |   | ||||||
|  | +	if (ppe->accounting) | ||||||
|  | +		*mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT; | ||||||
|  | + | ||||||
|  |  	dma_wmb(); | ||||||
|  |   | ||||||
|  |  	mtk_ppe_cache_clear(ppe); | ||||||
|  | @@ -716,14 +766,42 @@ int mtk_foe_entry_idle_time(struct mtk_p | ||||||
|  |  	return __mtk_foe_entry_idle_time(ppe, entry->data.ib1); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, | ||||||
|  | +						 struct mtk_foe_accounting *diff) | ||||||
|  | +{ | ||||||
|  | +	struct mtk_foe_accounting *acct; | ||||||
|  | +	int size = sizeof(struct mtk_foe_accounting); | ||||||
|  | +	u64 bytes, packets; | ||||||
|  | + | ||||||
|  | +	if (!ppe->accounting) | ||||||
|  | +		return NULL; | ||||||
|  | + | ||||||
|  | +	if (mtk_mib_entry_read(ppe, index, &bytes, &packets)) | ||||||
|  | +		return NULL; | ||||||
|  | + | ||||||
|  | +	acct = ppe->acct_table + index * size; | ||||||
|  | + | ||||||
|  | +	acct->bytes += bytes; | ||||||
|  | +	acct->packets += packets; | ||||||
|  | + | ||||||
|  | +	if (diff) { | ||||||
|  | +		diff->bytes = bytes; | ||||||
|  | +		diff->packets = packets; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return acct; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, | ||||||
|  | -			     int version, int index) | ||||||
|  | +			     int version, int index, bool accounting) | ||||||
|  |  { | ||||||
|  |  	const struct mtk_soc_data *soc = eth->soc; | ||||||
|  |  	struct device *dev = eth->dev; | ||||||
|  |  	struct mtk_ppe *ppe; | ||||||
|  |  	u32 foe_flow_size; | ||||||
|  |  	void *foe; | ||||||
|  | +	struct mtk_mib_entry *mib; | ||||||
|  | +	struct mtk_foe_accounting *acct; | ||||||
|  |   | ||||||
|  |  	ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL); | ||||||
|  |  	if (!ppe) | ||||||
|  | @@ -738,6 +816,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ | ||||||
|  |  	ppe->eth = eth; | ||||||
|  |  	ppe->dev = dev; | ||||||
|  |  	ppe->version = version; | ||||||
|  | +	ppe->accounting = accounting; | ||||||
|  |   | ||||||
|  |  	foe = dmam_alloc_coherent(ppe->dev, | ||||||
|  |  				  MTK_PPE_ENTRIES * soc->foe_entry_size, | ||||||
|  | @@ -753,6 +832,25 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ | ||||||
|  |  	if (!ppe->foe_flow) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | +	if (accounting) { | ||||||
|  | +		mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), | ||||||
|  | +					  &ppe->mib_phys, GFP_KERNEL); | ||||||
|  | +		if (!mib) | ||||||
|  | +			return NULL; | ||||||
|  | + | ||||||
|  | +		memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib)); | ||||||
|  | + | ||||||
|  | +		ppe->mib_table = mib; | ||||||
|  | + | ||||||
|  | +		acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), | ||||||
|  | +				    GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +		if (!acct) | ||||||
|  | +			return NULL; | ||||||
|  | + | ||||||
|  | +		ppe->acct_table = acct; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	mtk_ppe_debugfs_init(ppe, index); | ||||||
|  |   | ||||||
|  |  	return ppe; | ||||||
|  | @@ -867,6 +965,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe) | ||||||
|  |  		ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777); | ||||||
|  |  		ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f); | ||||||
|  |  	} | ||||||
|  | + | ||||||
|  | +	if (ppe->accounting && ppe->mib_phys) { | ||||||
|  | +		ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys); | ||||||
|  | +		ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, | ||||||
|  | +			MTK_PPE_MIB_CFG_EN); | ||||||
|  | +		ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, | ||||||
|  | +			MTK_PPE_MIB_CFG_RD_CLR); | ||||||
|  | +		ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, | ||||||
|  | +			MTK_PPE_MIB_CFG_RD_CLR); | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int mtk_ppe_stop(struct mtk_ppe *ppe) | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_ppe.h | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h | ||||||
|  | @@ -57,6 +57,7 @@ enum { | ||||||
|  |  #define MTK_FOE_IB2_MULTICAST		BIT(8) | ||||||
|  |   | ||||||
|  |  #define MTK_FOE_IB2_WDMA_QID2		GENMASK(13, 12) | ||||||
|  | +#define MTK_FOE_IB2_MIB_CNT		BIT(15) | ||||||
|  |  #define MTK_FOE_IB2_WDMA_DEVIDX		BIT(16) | ||||||
|  |  #define MTK_FOE_IB2_WDMA_WINFO		BIT(17) | ||||||
|  |   | ||||||
|  | @@ -284,16 +285,34 @@ struct mtk_flow_entry { | ||||||
|  |  	unsigned long cookie; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +struct mtk_mib_entry { | ||||||
|  | +	u32	byt_cnt_l; | ||||||
|  | +	u16	byt_cnt_h; | ||||||
|  | +	u32	pkt_cnt_l; | ||||||
|  | +	u8	pkt_cnt_h; | ||||||
|  | +	u8	_rsv0; | ||||||
|  | +	u32	_rsv1; | ||||||
|  | +} __packed; | ||||||
|  | + | ||||||
|  | +struct mtk_foe_accounting { | ||||||
|  | +	u64	bytes; | ||||||
|  | +	u64	packets; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  struct mtk_ppe { | ||||||
|  |  	struct mtk_eth *eth; | ||||||
|  |  	struct device *dev; | ||||||
|  |  	void __iomem *base; | ||||||
|  |  	int version; | ||||||
|  |  	char dirname[5]; | ||||||
|  | +	bool accounting; | ||||||
|  |   | ||||||
|  |  	void *foe_table; | ||||||
|  |  	dma_addr_t foe_phys; | ||||||
|  |   | ||||||
|  | +	struct mtk_mib_entry *mib_table; | ||||||
|  | +	dma_addr_t mib_phys; | ||||||
|  | + | ||||||
|  |  	u16 foe_check_time[MTK_PPE_ENTRIES]; | ||||||
|  |  	struct hlist_head *foe_flow; | ||||||
|  |   | ||||||
|  | @@ -303,7 +322,7 @@ struct mtk_ppe { | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, | ||||||
|  | -			     int version, int index); | ||||||
|  | +			     int version, int index, bool accounting); | ||||||
|  |  void mtk_ppe_start(struct mtk_ppe *ppe); | ||||||
|  |  int mtk_ppe_stop(struct mtk_ppe *ppe); | ||||||
|  |   | ||||||
|  | @@ -354,5 +373,7 @@ int mtk_foe_entry_commit(struct mtk_ppe | ||||||
|  |  void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); | ||||||
|  |  int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); | ||||||
|  |  int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); | ||||||
|  | +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, | ||||||
|  | +						 struct mtk_foe_accounting *diff); | ||||||
|  |   | ||||||
|  |  #endif | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c | ||||||
|  | @@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file | ||||||
|  |  		struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i); | ||||||
|  |  		struct mtk_foe_mac_info *l2; | ||||||
|  |  		struct mtk_flow_addr_info ai = {}; | ||||||
|  | +		struct mtk_foe_accounting *acct; | ||||||
|  |  		unsigned char h_source[ETH_ALEN]; | ||||||
|  |  		unsigned char h_dest[ETH_ALEN]; | ||||||
|  |  		int type, state; | ||||||
|  | @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file | ||||||
|  |  		if (bind && state != MTK_FOE_STATE_BIND) | ||||||
|  |  			continue; | ||||||
|  |   | ||||||
|  | +		acct = mtk_foe_entry_get_mib(ppe, i, NULL); | ||||||
|  | + | ||||||
|  |  		type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1); | ||||||
|  |  		seq_printf(m, "%05x %s %7s", i, | ||||||
|  |  			   mtk_foe_entry_state_str(state), | ||||||
|  | @@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file | ||||||
|  |  		*((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo); | ||||||
|  |   | ||||||
|  |  		seq_printf(m, " eth=%pM->%pM etype=%04x" | ||||||
|  | -			      " vlan=%d,%d ib1=%08x ib2=%08x\n", | ||||||
|  | +			      " vlan=%d,%d ib1=%08x ib2=%08x" | ||||||
|  | +			      " packets=%lld bytes=%lld\n", | ||||||
|  |  			   h_source, h_dest, ntohs(l2->etype), | ||||||
|  | -			   l2->vlan1, l2->vlan2, entry->ib1, ib2); | ||||||
|  | +			   l2->vlan1, l2->vlan2, entry->ib1, ib2, | ||||||
|  | +			   acct->packets, acct->bytes); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c | ||||||
|  | @@ -491,6 +491,7 @@ static int | ||||||
|  |  mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) | ||||||
|  |  { | ||||||
|  |  	struct mtk_flow_entry *entry; | ||||||
|  | +	struct mtk_foe_accounting diff; | ||||||
|  |  	u32 idle; | ||||||
|  |   | ||||||
|  |  	entry = rhashtable_lookup(ð->flow_table, &f->cookie, | ||||||
|  | @@ -501,6 +502,12 @@ mtk_flow_offload_stats(struct mtk_eth *e | ||||||
|  |  	idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); | ||||||
|  |  	f->stats.lastused = jiffies - idle * HZ; | ||||||
|  |   | ||||||
|  | +	if (entry->hash != 0xFFFF) { | ||||||
|  | +		mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, &diff); | ||||||
|  | +		f->stats.pkts += diff.packets; | ||||||
|  | +		f->stats.bytes += diff.bytes; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h | ||||||
|  | +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h | ||||||
|  | @@ -143,6 +143,20 @@ enum { | ||||||
|  |   | ||||||
|  |  #define MTK_PPE_MIB_TB_BASE			0x338 | ||||||
|  |   | ||||||
|  | +#define MTK_PPE_MIB_SER_CR			0x33C | ||||||
|  | +#define MTK_PPE_MIB_SER_CR_ST			BIT(16) | ||||||
|  | +#define MTK_PPE_MIB_SER_CR_ADDR			GENMASK(13, 0) | ||||||
|  | + | ||||||
|  | +#define MTK_PPE_MIB_SER_R0			0x340 | ||||||
|  | +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW		GENMASK(31, 0) | ||||||
|  | + | ||||||
|  | +#define MTK_PPE_MIB_SER_R1			0x344 | ||||||
|  | +#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW		GENMASK(31, 16) | ||||||
|  | +#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH	GENMASK(15, 0) | ||||||
|  | + | ||||||
|  | +#define MTK_PPE_MIB_SER_R2			0x348 | ||||||
|  | +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH		GENMASK(23, 0) | ||||||
|  | + | ||||||
|  |  #define MTK_PPE_MIB_CACHE_CTL			0x350 | ||||||
|  |  #define MTK_PPE_MIB_CACHE_CTL_EN		BIT(0) | ||||||
|  |  #define MTK_PPE_MIB_CACHE_CTL_FLUSH		BIT(2) | ||||||
		Reference in New Issue
	
	Block a user
	 Daniel Golle
					Daniel Golle