731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. From patchwork Wed Nov 2 00:58:01 2022
  2. Content-Type: text/plain; charset="utf-8"
  3. MIME-Version: 1.0
  4. Content-Transfer-Encoding: 7bit
  5. X-Patchwork-Submitter: Daniel Golle <[email protected]>
  6. X-Patchwork-Id: 13027653
  7. X-Patchwork-Delegate: [email protected]
  8. Return-Path: <[email protected]>
  9. Date: Wed, 2 Nov 2022 00:58:01 +0000
  10. From: Daniel Golle <[email protected]>
  11. To: Felix Fietkau <[email protected]>, John Crispin <[email protected]>,
  12. Sean Wang <[email protected]>,
  13. Mark Lee <[email protected]>,
  14. "David S. Miller" <[email protected]>,
  15. Eric Dumazet <[email protected]>,
  16. Jakub Kicinski <[email protected]>,
  17. Paolo Abeni <[email protected]>,
  18. Matthias Brugger <[email protected]>,
  19. [email protected], [email protected],
  20. [email protected], [email protected]
  21. Subject: [PATCH v4] net: ethernet: mediatek: ppe: add support for flow
  22. accounting
  23. Message-ID: <[email protected]>
  24. MIME-Version: 1.0
  25. Content-Disposition: inline
  26. Precedence: bulk
  27. List-ID: <netdev.vger.kernel.org>
  28. X-Mailing-List: [email protected]
  29. X-Patchwork-Delegate: [email protected]
  30. The PPE units found in MT7622 and newer support packet and byte
  31. accounting of hw-offloaded flows. Add support for reading those
  32. counters as found in MediaTek's SDK[1].
  33. [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92
  34. Signed-off-by: Daniel Golle <[email protected]>
  35. ---
  36. v4: declare function mtk_mib_entry_read as static
  37. v3: don't bother to set 'false' values in any zero-initialized struct
  38. use mtk_foe_entry_ib2
  39. both changes were requested by Felix Fietkau
  40. v2: fix wrong variable name in return value check spotted by Denis Kirjanov
  41. drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +-
  42. drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 +
  43. drivers/net/ethernet/mediatek/mtk_ppe.c | 110 +++++++++++++++++-
  44. drivers/net/ethernet/mediatek/mtk_ppe.h | 23 +++-
  45. .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +-
  46. .../net/ethernet/mediatek/mtk_ppe_offload.c | 7 ++
  47. drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++
  48. 7 files changed, 166 insertions(+), 5 deletions(-)
  49. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
  50. +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
  51. @@ -4090,7 +4090,9 @@ static int mtk_probe(struct platform_dev
  52. u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400;
  53. eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr,
  54. - eth->soc->offload_version, i);
  55. + eth->soc->offload_version, i,
  56. + eth->soc->has_accounting);
  57. +
  58. if (!eth->ppe[i]) {
  59. err = -ENOMEM;
  60. goto err_free_dev;
  61. @@ -4213,6 +4215,7 @@ static const struct mtk_soc_data mt7622_
  62. .required_pctl = false,
  63. .offload_version = 2,
  64. .hash_offset = 2,
  65. + .has_accounting = true,
  66. .foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
  67. .txrx = {
  68. .txd_size = sizeof(struct mtk_tx_dma),
  69. @@ -4250,6 +4253,7 @@ static const struct mtk_soc_data mt7629_
  70. .hw_features = MTK_HW_FEATURES,
  71. .required_clks = MT7629_CLKS_BITMAP,
  72. .required_pctl = false,
  73. + .has_accounting = true,
  74. .txrx = {
  75. .txd_size = sizeof(struct mtk_tx_dma),
  76. .rxd_size = sizeof(struct mtk_rx_dma),
  77. @@ -4270,6 +4274,7 @@ static const struct mtk_soc_data mt7986_
  78. .offload_version = 2,
  79. .hash_offset = 4,
  80. .foe_entry_size = sizeof(struct mtk_foe_entry),
  81. + .has_accounting = true,
  82. .txrx = {
  83. .txd_size = sizeof(struct mtk_tx_dma_v2),
  84. .rxd_size = sizeof(struct mtk_rx_dma_v2),
  85. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  86. +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  87. @@ -983,6 +983,7 @@ struct mtk_soc_data {
  88. u8 hash_offset;
  89. u16 foe_entry_size;
  90. netdev_features_t hw_features;
  91. + bool has_accounting;
  92. struct {
  93. u32 txd_size;
  94. u32 rxd_size;
  95. --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
  96. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
  97. @@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_
  98. return ret;
  99. }
  100. +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
  101. +{
  102. + int ret;
  103. + u32 val;
  104. +
  105. + ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val,
  106. + !(val & MTK_PPE_MIB_SER_CR_ST),
  107. + 20, MTK_PPE_WAIT_TIMEOUT_US);
  108. +
  109. + if (ret)
  110. + dev_err(ppe->dev, "MIB table busy");
  111. +
  112. + return ret;
  113. +}
  114. +
  115. +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
  116. +{
  117. + u32 val, cnt_r0, cnt_r1, cnt_r2;
  118. + u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
  119. +
  120. + val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST;
  121. + ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val);
  122. +
  123. + if (mtk_ppe_mib_wait_busy(ppe))
  124. + return -ETIMEDOUT;
  125. +
  126. + cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0);
  127. + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
  128. + cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
  129. +
  130. + byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
  131. + byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
  132. + pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
  133. + pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
  134. + *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
  135. + *packets = (pkt_cnt_high << 16) | pkt_cnt_low;
  136. +
  137. + return 0;
  138. +}
  139. +
  140. static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
  141. {
  142. ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
  143. @@ -444,6 +484,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp
  144. hwe->ib1 &= ~MTK_FOE_IB1_STATE;
  145. hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID);
  146. dma_wmb();
  147. + if (ppe->accounting) {
  148. + struct mtk_foe_accounting *acct;
  149. +
  150. + acct = ppe->acct_table + entry->hash * sizeof(*acct);
  151. + acct->packets = 0;
  152. + acct->bytes = 0;
  153. + }
  154. }
  155. entry->hash = 0xffff;
  156. @@ -551,6 +598,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p
  157. wmb();
  158. hwe->ib1 = entry->ib1;
  159. + if (ppe->accounting)
  160. + *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT;
  161. +
  162. dma_wmb();
  163. mtk_ppe_cache_clear(ppe);
  164. @@ -716,14 +766,42 @@ int mtk_foe_entry_idle_time(struct mtk_p
  165. return __mtk_foe_entry_idle_time(ppe, entry->data.ib1);
  166. }
  167. +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
  168. + struct mtk_foe_accounting *diff)
  169. +{
  170. + struct mtk_foe_accounting *acct;
  171. + int size = sizeof(struct mtk_foe_accounting);
  172. + u64 bytes, packets;
  173. +
  174. + if (!ppe->accounting)
  175. + return NULL;
  176. +
  177. + if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
  178. + return NULL;
  179. +
  180. + acct = ppe->acct_table + index * size;
  181. +
  182. + acct->bytes += bytes;
  183. + acct->packets += packets;
  184. +
  185. + if (diff) {
  186. + diff->bytes = bytes;
  187. + diff->packets = packets;
  188. + }
  189. +
  190. + return acct;
  191. +}
  192. +
  193. struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
  194. - int version, int index)
  195. + int version, int index, bool accounting)
  196. {
  197. const struct mtk_soc_data *soc = eth->soc;
  198. struct device *dev = eth->dev;
  199. struct mtk_ppe *ppe;
  200. u32 foe_flow_size;
  201. void *foe;
  202. + struct mtk_mib_entry *mib;
  203. + struct mtk_foe_accounting *acct;
  204. ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL);
  205. if (!ppe)
  206. @@ -738,6 +816,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
  207. ppe->eth = eth;
  208. ppe->dev = dev;
  209. ppe->version = version;
  210. + ppe->accounting = accounting;
  211. foe = dmam_alloc_coherent(ppe->dev,
  212. MTK_PPE_ENTRIES * soc->foe_entry_size,
  213. @@ -753,6 +832,25 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
  214. if (!ppe->foe_flow)
  215. return NULL;
  216. + if (accounting) {
  217. + mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
  218. + &ppe->mib_phys, GFP_KERNEL);
  219. + if (!mib)
  220. + return NULL;
  221. +
  222. + memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib));
  223. +
  224. + ppe->mib_table = mib;
  225. +
  226. + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
  227. + GFP_KERNEL);
  228. +
  229. + if (!acct)
  230. + return NULL;
  231. +
  232. + ppe->acct_table = acct;
  233. + }
  234. +
  235. mtk_ppe_debugfs_init(ppe, index);
  236. return ppe;
  237. @@ -867,6 +965,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe)
  238. ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777);
  239. ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f);
  240. }
  241. +
  242. + if (ppe->accounting && ppe->mib_phys) {
  243. + ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys);
  244. + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN,
  245. + MTK_PPE_MIB_CFG_EN);
  246. + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR,
  247. + MTK_PPE_MIB_CFG_RD_CLR);
  248. + ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN,
  249. + MTK_PPE_MIB_CFG_RD_CLR);
  250. + }
  251. }
  252. int mtk_ppe_stop(struct mtk_ppe *ppe)
  253. --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
  254. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
  255. @@ -57,6 +57,7 @@ enum {
  256. #define MTK_FOE_IB2_MULTICAST BIT(8)
  257. #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
  258. +#define MTK_FOE_IB2_MIB_CNT BIT(15)
  259. #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
  260. #define MTK_FOE_IB2_WDMA_WINFO BIT(17)
  261. @@ -284,16 +285,34 @@ struct mtk_flow_entry {
  262. unsigned long cookie;
  263. };
  264. +struct mtk_mib_entry {
  265. + u32 byt_cnt_l;
  266. + u16 byt_cnt_h;
  267. + u32 pkt_cnt_l;
  268. + u8 pkt_cnt_h;
  269. + u8 _rsv0;
  270. + u32 _rsv1;
  271. +} __packed;
  272. +
  273. +struct mtk_foe_accounting {
  274. + u64 bytes;
  275. + u64 packets;
  276. +};
  277. +
  278. struct mtk_ppe {
  279. struct mtk_eth *eth;
  280. struct device *dev;
  281. void __iomem *base;
  282. int version;
  283. char dirname[5];
  284. + bool accounting;
  285. void *foe_table;
  286. dma_addr_t foe_phys;
  287. + struct mtk_mib_entry *mib_table;
  288. + dma_addr_t mib_phys;
  289. +
  290. u16 foe_check_time[MTK_PPE_ENTRIES];
  291. struct hlist_head *foe_flow;
  292. @@ -303,7 +322,7 @@ struct mtk_ppe {
  293. };
  294. struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
  295. - int version, int index);
  296. + int version, int index, bool accounting);
  297. void mtk_ppe_start(struct mtk_ppe *ppe);
  298. int mtk_ppe_stop(struct mtk_ppe *ppe);
  299. @@ -354,5 +373,7 @@ int mtk_foe_entry_commit(struct mtk_ppe
  300. void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
  301. int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
  302. int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index);
  303. +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
  304. + struct mtk_foe_accounting *diff);
  305. #endif
  306. --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
  307. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
  308. @@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  309. struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i);
  310. struct mtk_foe_mac_info *l2;
  311. struct mtk_flow_addr_info ai = {};
  312. + struct mtk_foe_accounting *acct;
  313. unsigned char h_source[ETH_ALEN];
  314. unsigned char h_dest[ETH_ALEN];
  315. int type, state;
  316. @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  317. if (bind && state != MTK_FOE_STATE_BIND)
  318. continue;
  319. + acct = mtk_foe_entry_get_mib(ppe, i, NULL);
  320. +
  321. type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
  322. seq_printf(m, "%05x %s %7s", i,
  323. mtk_foe_entry_state_str(state),
  324. @@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  325. *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
  326. seq_printf(m, " eth=%pM->%pM etype=%04x"
  327. - " vlan=%d,%d ib1=%08x ib2=%08x\n",
  328. + " vlan=%d,%d ib1=%08x ib2=%08x"
  329. + " packets=%lld bytes=%lld\n",
  330. h_source, h_dest, ntohs(l2->etype),
  331. - l2->vlan1, l2->vlan2, entry->ib1, ib2);
  332. + l2->vlan1, l2->vlan2, entry->ib1, ib2,
  333. + acct->packets, acct->bytes);
  334. }
  335. return 0;
  336. --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  337. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  338. @@ -491,6 +491,7 @@ static int
  339. mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
  340. {
  341. struct mtk_flow_entry *entry;
  342. + struct mtk_foe_accounting diff;
  343. u32 idle;
  344. entry = rhashtable_lookup(&eth->flow_table, &f->cookie,
  345. @@ -501,6 +502,12 @@ mtk_flow_offload_stats(struct mtk_eth *e
  346. idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry);
  347. f->stats.lastused = jiffies - idle * HZ;
  348. + if (entry->hash != 0xFFFF) {
  349. + mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, &diff);
  350. + f->stats.pkts += diff.packets;
  351. + f->stats.bytes += diff.bytes;
  352. + }
  353. +
  354. return 0;
  355. }
  356. --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
  357. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
  358. @@ -143,6 +143,20 @@ enum {
  359. #define MTK_PPE_MIB_TB_BASE 0x338
  360. +#define MTK_PPE_MIB_SER_CR 0x33C
  361. +#define MTK_PPE_MIB_SER_CR_ST BIT(16)
  362. +#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0)
  363. +
  364. +#define MTK_PPE_MIB_SER_R0 0x340
  365. +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
  366. +
  367. +#define MTK_PPE_MIB_SER_R1 0x344
  368. +#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16)
  369. +#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0)
  370. +
  371. +#define MTK_PPE_MIB_SER_R2 0x348
  372. +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
  373. +
  374. #define MTK_PPE_MIB_CACHE_CTL 0x350
  375. #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
  376. #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)