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

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