733-v6.4-24-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. @@ -4637,8 +4637,8 @@ static int mtk_probe(struct platform_dev
  52. for (i = 0; i < num_ppe; i++) {
  53. u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400;
  54. - eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr,
  55. - eth->soc->offload_version, i);
  56. + eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, i);
  57. +
  58. if (!eth->ppe[i]) {
  59. err = -ENOMEM;
  60. goto err_deinit_ppe;
  61. @@ -4764,6 +4764,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. @@ -4801,6 +4802,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. @@ -4821,6 +4823,7 @@ static const struct mtk_soc_data mt7981_
  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. @@ -4841,6 +4844,7 @@ static const struct mtk_soc_data mt7986_
  86. .offload_version = 2,
  87. .hash_offset = 4,
  88. .foe_entry_size = sizeof(struct mtk_foe_entry),
  89. + .has_accounting = true,
  90. .txrx = {
  91. .txd_size = sizeof(struct mtk_tx_dma_v2),
  92. .rxd_size = sizeof(struct mtk_rx_dma_v2),
  93. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  94. +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
  95. @@ -1008,6 +1008,8 @@ struct mtk_reg_map {
  96. * the extra setup for those pins used by GMAC.
  97. * @hash_offset Flow table hash offset.
  98. * @foe_entry_size Foe table entry size.
  99. + * @has_accounting Bool indicating support for accounting of
  100. + * offloaded flows.
  101. * @txd_size Tx DMA descriptor size.
  102. * @rxd_size Rx DMA descriptor size.
  103. * @rx_irq_done_mask Rx irq done register mask.
  104. @@ -1025,6 +1027,7 @@ struct mtk_soc_data {
  105. u8 hash_offset;
  106. u16 foe_entry_size;
  107. netdev_features_t hw_features;
  108. + bool has_accounting;
  109. struct {
  110. u32 txd_size;
  111. u32 rxd_size;
  112. --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
  113. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
  114. @@ -74,6 +74,48 @@ static int mtk_ppe_wait_busy(struct mtk_
  115. return ret;
  116. }
  117. +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
  118. +{
  119. + int ret;
  120. + u32 val;
  121. +
  122. + ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val,
  123. + !(val & MTK_PPE_MIB_SER_CR_ST),
  124. + 20, MTK_PPE_WAIT_TIMEOUT_US);
  125. +
  126. + if (ret)
  127. + dev_err(ppe->dev, "MIB table busy");
  128. +
  129. + return ret;
  130. +}
  131. +
  132. +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
  133. +{
  134. + u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
  135. + u32 val, cnt_r0, cnt_r1, cnt_r2;
  136. + int ret;
  137. +
  138. + val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST;
  139. + ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val);
  140. +
  141. + ret = mtk_ppe_mib_wait_busy(ppe);
  142. + if (ret)
  143. + return ret;
  144. +
  145. + cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0);
  146. + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
  147. + cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
  148. +
  149. + byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
  150. + byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
  151. + pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
  152. + pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
  153. + *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
  154. + *packets = (pkt_cnt_high << 16) | pkt_cnt_low;
  155. +
  156. + return 0;
  157. +}
  158. +
  159. static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
  160. {
  161. ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
  162. @@ -465,6 +507,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp
  163. hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID);
  164. dma_wmb();
  165. mtk_ppe_cache_clear(ppe);
  166. + if (ppe->accounting) {
  167. + struct mtk_foe_accounting *acct;
  168. +
  169. + acct = ppe->acct_table + entry->hash * sizeof(*acct);
  170. + acct->packets = 0;
  171. + acct->bytes = 0;
  172. + }
  173. }
  174. entry->hash = 0xffff;
  175. @@ -572,6 +621,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p
  176. wmb();
  177. hwe->ib1 = entry->ib1;
  178. + if (ppe->accounting)
  179. + *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT;
  180. +
  181. dma_wmb();
  182. mtk_ppe_cache_clear(ppe);
  183. @@ -763,11 +815,39 @@ int mtk_ppe_prepare_reset(struct mtk_ppe
  184. return mtk_ppe_wait_busy(ppe);
  185. }
  186. -struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
  187. - int version, int index)
  188. +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
  189. + struct mtk_foe_accounting *diff)
  190. +{
  191. + struct mtk_foe_accounting *acct;
  192. + int size = sizeof(struct mtk_foe_accounting);
  193. + u64 bytes, packets;
  194. +
  195. + if (!ppe->accounting)
  196. + return NULL;
  197. +
  198. + if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
  199. + return NULL;
  200. +
  201. + acct = ppe->acct_table + index * size;
  202. +
  203. + acct->bytes += bytes;
  204. + acct->packets += packets;
  205. +
  206. + if (diff) {
  207. + diff->bytes = bytes;
  208. + diff->packets = packets;
  209. + }
  210. +
  211. + return acct;
  212. +}
  213. +
  214. +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index)
  215. {
  216. + bool accounting = eth->soc->has_accounting;
  217. const struct mtk_soc_data *soc = eth->soc;
  218. + struct mtk_foe_accounting *acct;
  219. struct device *dev = eth->dev;
  220. + struct mtk_mib_entry *mib;
  221. struct mtk_ppe *ppe;
  222. u32 foe_flow_size;
  223. void *foe;
  224. @@ -784,7 +864,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
  225. ppe->base = base;
  226. ppe->eth = eth;
  227. ppe->dev = dev;
  228. - ppe->version = version;
  229. + ppe->version = eth->soc->offload_version;
  230. + ppe->accounting = accounting;
  231. foe = dmam_alloc_coherent(ppe->dev,
  232. MTK_PPE_ENTRIES * soc->foe_entry_size,
  233. @@ -800,6 +881,23 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
  234. if (!ppe->foe_flow)
  235. goto err_free_l2_flows;
  236. + if (accounting) {
  237. + mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
  238. + &ppe->mib_phys, GFP_KERNEL);
  239. + if (!mib)
  240. + return NULL;
  241. +
  242. + ppe->mib_table = mib;
  243. +
  244. + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
  245. + GFP_KERNEL);
  246. +
  247. + if (!acct)
  248. + return NULL;
  249. +
  250. + ppe->acct_table = acct;
  251. + }
  252. +
  253. mtk_ppe_debugfs_init(ppe, index);
  254. return ppe;
  255. @@ -929,6 +1027,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe)
  256. ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777);
  257. ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f);
  258. }
  259. +
  260. + if (ppe->accounting && ppe->mib_phys) {
  261. + ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys);
  262. + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN,
  263. + MTK_PPE_MIB_CFG_EN);
  264. + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR,
  265. + MTK_PPE_MIB_CFG_RD_CLR);
  266. + ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN,
  267. + MTK_PPE_MIB_CFG_RD_CLR);
  268. + }
  269. }
  270. int mtk_ppe_stop(struct mtk_ppe *ppe)
  271. --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
  272. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
  273. @@ -57,6 +57,7 @@ enum {
  274. #define MTK_FOE_IB2_MULTICAST BIT(8)
  275. #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
  276. +#define MTK_FOE_IB2_MIB_CNT BIT(15)
  277. #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
  278. #define MTK_FOE_IB2_WDMA_WINFO BIT(17)
  279. @@ -285,16 +286,34 @@ struct mtk_flow_entry {
  280. unsigned long cookie;
  281. };
  282. +struct mtk_mib_entry {
  283. + u32 byt_cnt_l;
  284. + u16 byt_cnt_h;
  285. + u32 pkt_cnt_l;
  286. + u8 pkt_cnt_h;
  287. + u8 _rsv0;
  288. + u32 _rsv1;
  289. +} __packed;
  290. +
  291. +struct mtk_foe_accounting {
  292. + u64 bytes;
  293. + u64 packets;
  294. +};
  295. +
  296. struct mtk_ppe {
  297. struct mtk_eth *eth;
  298. struct device *dev;
  299. void __iomem *base;
  300. int version;
  301. char dirname[5];
  302. + bool accounting;
  303. void *foe_table;
  304. dma_addr_t foe_phys;
  305. + struct mtk_mib_entry *mib_table;
  306. + dma_addr_t mib_phys;
  307. +
  308. u16 foe_check_time[MTK_PPE_ENTRIES];
  309. struct hlist_head *foe_flow;
  310. @@ -303,8 +322,7 @@ struct mtk_ppe {
  311. void *acct_table;
  312. };
  313. -struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
  314. - int version, int index);
  315. +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index);
  316. void mtk_ppe_deinit(struct mtk_eth *eth);
  317. void mtk_ppe_start(struct mtk_ppe *ppe);
  318. int mtk_ppe_stop(struct mtk_ppe *ppe);
  319. @@ -359,5 +377,7 @@ int mtk_foe_entry_commit(struct mtk_ppe
  320. void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
  321. int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
  322. int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index);
  323. +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
  324. + struct mtk_foe_accounting *diff);
  325. #endif
  326. --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
  327. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
  328. @@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  329. struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i);
  330. struct mtk_foe_mac_info *l2;
  331. struct mtk_flow_addr_info ai = {};
  332. + struct mtk_foe_accounting *acct;
  333. unsigned char h_source[ETH_ALEN];
  334. unsigned char h_dest[ETH_ALEN];
  335. int type, state;
  336. @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  337. if (bind && state != MTK_FOE_STATE_BIND)
  338. continue;
  339. + acct = mtk_foe_entry_get_mib(ppe, i, NULL);
  340. +
  341. type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
  342. seq_printf(m, "%05x %s %7s", i,
  343. mtk_foe_entry_state_str(state),
  344. @@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file
  345. *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
  346. seq_printf(m, " eth=%pM->%pM etype=%04x"
  347. - " vlan=%d,%d ib1=%08x ib2=%08x\n",
  348. + " vlan=%d,%d ib1=%08x ib2=%08x"
  349. + " packets=%llu bytes=%llu\n",
  350. h_source, h_dest, ntohs(l2->etype),
  351. - l2->vlan1, l2->vlan2, entry->ib1, ib2);
  352. + l2->vlan1, l2->vlan2, entry->ib1, ib2,
  353. + acct ? acct->packets : 0, acct ? acct->bytes : 0);
  354. }
  355. return 0;
  356. --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  357. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  358. @@ -497,6 +497,7 @@ static int
  359. mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
  360. {
  361. struct mtk_flow_entry *entry;
  362. + struct mtk_foe_accounting diff;
  363. u32 idle;
  364. entry = rhashtable_lookup(&eth->flow_table, &f->cookie,
  365. @@ -507,6 +508,13 @@ mtk_flow_offload_stats(struct mtk_eth *e
  366. idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry);
  367. f->stats.lastused = jiffies - idle * HZ;
  368. + if (entry->hash != 0xFFFF &&
  369. + mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash,
  370. + &diff)) {
  371. + f->stats.pkts += diff.packets;
  372. + f->stats.bytes += diff.bytes;
  373. + }
  374. +
  375. return 0;
  376. }
  377. --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
  378. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
  379. @@ -149,6 +149,20 @@ enum {
  380. #define MTK_PPE_MIB_TB_BASE 0x338
  381. +#define MTK_PPE_MIB_SER_CR 0x33C
  382. +#define MTK_PPE_MIB_SER_CR_ST BIT(16)
  383. +#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0)
  384. +
  385. +#define MTK_PPE_MIB_SER_R0 0x340
  386. +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
  387. +
  388. +#define MTK_PPE_MIB_SER_R1 0x344
  389. +#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16)
  390. +#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0)
  391. +
  392. +#define MTK_PPE_MIB_SER_R2 0x348
  393. +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
  394. +
  395. #define MTK_PPE_MIB_CACHE_CTL 0x350
  396. #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
  397. #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)