702-v5.19-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. From: Felix Fietkau <[email protected]>
  2. Date: Sat, 5 Feb 2022 18:29:22 +0100
  3. Subject: [PATCH] net: ethernet: mtk_eth_soc: implement flow offloading
  4. to WED devices
  5. This allows hardware flow offloading from Ethernet to WLAN on MT7622 SoC
  6. Co-developed-by: Lorenzo Bianconi <[email protected]>
  7. Signed-off-by: Lorenzo Bianconi <[email protected]>
  8. Signed-off-by: Felix Fietkau <[email protected]>
  9. ---
  10. --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
  11. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
  12. @@ -329,6 +329,24 @@ int mtk_foe_entry_set_pppoe(struct mtk_f
  13. return 0;
  14. }
  15. +int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
  16. + int bss, int wcid)
  17. +{
  18. + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
  19. + u32 *ib2 = mtk_foe_entry_ib2(entry);
  20. +
  21. + *ib2 &= ~MTK_FOE_IB2_PORT_MG;
  22. + *ib2 |= MTK_FOE_IB2_WDMA_WINFO;
  23. + if (wdma_idx)
  24. + *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
  25. +
  26. + l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) |
  27. + FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) |
  28. + FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq);
  29. +
  30. + return 0;
  31. +}
  32. +
  33. static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry)
  34. {
  35. return !(entry->ib1 & MTK_FOE_IB1_STATIC) &&
  36. --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
  37. +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
  38. @@ -48,9 +48,9 @@ enum {
  39. #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5)
  40. #define MTK_FOE_IB2_MULTICAST BIT(8)
  41. -#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12)
  42. -#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16)
  43. -#define MTK_FOE_IB2_WHNAT_NAT BIT(17)
  44. +#define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
  45. +#define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
  46. +#define MTK_FOE_IB2_WDMA_WINFO BIT(17)
  47. #define MTK_FOE_IB2_PORT_MG GENMASK(17, 12)
  48. @@ -58,9 +58,9 @@ enum {
  49. #define MTK_FOE_IB2_DSCP GENMASK(31, 24)
  50. -#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0)
  51. -#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6)
  52. -#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14)
  53. +#define MTK_FOE_VLAN2_WINFO_BSS GENMASK(5, 0)
  54. +#define MTK_FOE_VLAN2_WINFO_WCID GENMASK(13, 6)
  55. +#define MTK_FOE_VLAN2_WINFO_RING GENMASK(15, 14)
  56. enum {
  57. MTK_FOE_STATE_INVALID,
  58. @@ -281,6 +281,8 @@ int mtk_foe_entry_set_ipv6_tuple(struct
  59. int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
  60. int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
  61. int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
  62. +int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
  63. + int bss, int wcid);
  64. int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry,
  65. u16 timestamp);
  66. int mtk_ppe_debugfs_init(struct mtk_ppe *ppe);
  67. --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  68. +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
  69. @@ -10,6 +10,7 @@
  70. #include <net/pkt_cls.h>
  71. #include <net/dsa.h>
  72. #include "mtk_eth_soc.h"
  73. +#include "mtk_wed.h"
  74. struct mtk_flow_data {
  75. struct ethhdr eth;
  76. @@ -39,6 +40,7 @@ struct mtk_flow_entry {
  77. struct rhash_head node;
  78. unsigned long cookie;
  79. u16 hash;
  80. + s8 wed_index;
  81. };
  82. static const struct rhashtable_params mtk_flow_ht_params = {
  83. @@ -80,6 +82,35 @@ mtk_flow_offload_mangle_eth(const struct
  84. memcpy(dest, src, act->mangle.mask ? 2 : 4);
  85. }
  86. +static int
  87. +mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info)
  88. +{
  89. + struct net_device_path_ctx ctx = {
  90. + .dev = dev,
  91. + .daddr = addr,
  92. + };
  93. + struct net_device_path path = {};
  94. +
  95. + if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
  96. + return -1;
  97. +
  98. + if (!dev->netdev_ops->ndo_fill_forward_path)
  99. + return -1;
  100. +
  101. + if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path))
  102. + return -1;
  103. +
  104. + if (path.type != DEV_PATH_MTK_WDMA)
  105. + return -1;
  106. +
  107. + info->wdma_idx = path.mtk_wdma.wdma_idx;
  108. + info->queue = path.mtk_wdma.queue;
  109. + info->bss = path.mtk_wdma.bss;
  110. + info->wcid = path.mtk_wdma.wcid;
  111. +
  112. + return 0;
  113. +}
  114. +
  115. static int
  116. mtk_flow_mangle_ports(const struct flow_action_entry *act,
  117. @@ -149,10 +180,20 @@ mtk_flow_get_dsa_port(struct net_device
  118. static int
  119. mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
  120. - struct net_device *dev)
  121. + struct net_device *dev, const u8 *dest_mac,
  122. + int *wed_index)
  123. {
  124. + struct mtk_wdma_info info = {};
  125. int pse_port, dsa_port;
  126. + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
  127. + mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
  128. + info.wcid);
  129. + pse_port = 3;
  130. + *wed_index = info.wdma_idx;
  131. + goto out;
  132. + }
  133. +
  134. dsa_port = mtk_flow_get_dsa_port(&dev);
  135. if (dsa_port >= 0)
  136. mtk_foe_entry_set_dsa(foe, dsa_port);
  137. @@ -164,6 +205,7 @@ mtk_flow_set_output_device(struct mtk_et
  138. else
  139. return -EOPNOTSUPP;
  140. +out:
  141. mtk_foe_entry_set_pse_port(foe, pse_port);
  142. return 0;
  143. @@ -179,6 +221,7 @@ mtk_flow_offload_replace(struct mtk_eth
  144. struct net_device *odev = NULL;
  145. struct mtk_flow_entry *entry;
  146. int offload_type = 0;
  147. + int wed_index = -1;
  148. u16 addr_type = 0;
  149. u32 timestamp;
  150. u8 l4proto = 0;
  151. @@ -326,10 +369,14 @@ mtk_flow_offload_replace(struct mtk_eth
  152. if (data.pppoe.num == 1)
  153. mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
  154. - err = mtk_flow_set_output_device(eth, &foe, odev);
  155. + err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest,
  156. + &wed_index);
  157. if (err)
  158. return err;
  159. + if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
  160. + return err;
  161. +
  162. entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  163. if (!entry)
  164. return -ENOMEM;
  165. @@ -343,6 +390,7 @@ mtk_flow_offload_replace(struct mtk_eth
  166. }
  167. entry->hash = hash;
  168. + entry->wed_index = wed_index;
  169. err = rhashtable_insert_fast(&eth->flow_table, &entry->node,
  170. mtk_flow_ht_params);
  171. if (err < 0)
  172. @@ -353,6 +401,8 @@ clear_flow:
  173. mtk_foe_entry_clear(&eth->ppe, hash);
  174. free:
  175. kfree(entry);
  176. + if (wed_index >= 0)
  177. + mtk_wed_flow_remove(wed_index);
  178. return err;
  179. }
  180. @@ -369,6 +419,8 @@ mtk_flow_offload_destroy(struct mtk_eth
  181. mtk_foe_entry_clear(&eth->ppe, entry->hash);
  182. rhashtable_remove_fast(&eth->flow_table, &entry->node,
  183. mtk_flow_ht_params);
  184. + if (entry->wed_index >= 0)
  185. + mtk_wed_flow_remove(entry->wed_index);
  186. kfree(entry);
  187. return 0;
  188. --- a/drivers/net/ethernet/mediatek/mtk_wed.h
  189. +++ b/drivers/net/ethernet/mediatek/mtk_wed.h
  190. @@ -7,6 +7,7 @@
  191. #include <linux/soc/mediatek/mtk_wed.h>
  192. #include <linux/debugfs.h>
  193. #include <linux/regmap.h>
  194. +#include <linux/netdevice.h>
  195. struct mtk_eth;
  196. @@ -27,6 +28,12 @@ struct mtk_wed_hw {
  197. int index;
  198. };
  199. +struct mtk_wdma_info {
  200. + u8 wdma_idx;
  201. + u8 queue;
  202. + u16 wcid;
  203. + u8 bss;
  204. +};
  205. #ifdef CONFIG_NET_MEDIATEK_SOC_WED
  206. static inline void
  207. --- a/include/linux/netdevice.h
  208. +++ b/include/linux/netdevice.h
  209. @@ -875,6 +875,7 @@ enum net_device_path_type {
  210. DEV_PATH_BRIDGE,
  211. DEV_PATH_PPPOE,
  212. DEV_PATH_DSA,
  213. + DEV_PATH_MTK_WDMA,
  214. };
  215. struct net_device_path {
  216. @@ -900,6 +901,12 @@ struct net_device_path {
  217. int port;
  218. u16 proto;
  219. } dsa;
  220. + struct {
  221. + u8 wdma_idx;
  222. + u8 queue;
  223. + u16 wcid;
  224. + u8 bss;
  225. + } mtk_wdma;
  226. };
  227. };
  228. --- a/net/core/dev.c
  229. +++ b/net/core/dev.c
  230. @@ -769,6 +769,10 @@ int dev_fill_forward_path(const struct n
  231. if (WARN_ON_ONCE(last_dev == ctx.dev))
  232. return -1;
  233. }
  234. +
  235. + if (!ctx.dev)
  236. + return ret;
  237. +
  238. path = dev_fwd_path(stack);
  239. if (!path)
  240. return -1;