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

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