Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-airoha-add-ppe-support-for-rx-wlan-offload'

Lorenzo Bianconi says:

====================
net: airoha: Add PPE support for RX wlan offload

Introduce the missing bits to airoha ppe driver to offload traffic received
by the MT76 driver (wireless NIC) and forwarded by the Packet Processor
Engine (PPE) to the ethernet interface.

v2: https://lore.kernel.org/20250822-airoha-en7581-wlan-rx-offload-v2-0-8a76e1d3fec2@kernel.org
v1: https://lore.kernel.org/20250819-airoha-en7581-wlan-rx-offload-v1-0-71a097e0e2a1@kernel.org
====================

Link: https://patch.msgid.link/20250823-airoha-en7581-wlan-rx-offload-v3-0-f78600ec3ed8@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+150 -37
+5 -2
drivers/net/ethernet/airoha/airoha_eth.c
··· 698 698 699 699 reason = FIELD_GET(AIROHA_RXD4_PPE_CPU_REASON, msg1); 700 700 if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) 701 - airoha_ppe_check_skb(eth->ppe, q->skb, hash); 701 + airoha_ppe_check_skb(&eth->ppe->dev, q->skb, hash, 702 + false); 702 703 703 704 done++; 704 705 napi_gro_receive(&q->napi, q->skb); ··· 2600 2599 void *type_data, void *cb_priv) 2601 2600 { 2602 2601 struct net_device *dev = cb_priv; 2602 + struct airoha_gdm_port *port = netdev_priv(dev); 2603 + struct airoha_eth *eth = port->qdma->eth; 2603 2604 2604 2605 if (!tc_can_offload(dev)) 2605 2606 return -EOPNOTSUPP; 2606 2607 2607 2608 switch (type) { 2608 2609 case TC_SETUP_CLSFLOWER: 2609 - return airoha_ppe_setup_tc_block_cb(dev, type_data); 2610 + return airoha_ppe_setup_tc_block_cb(&eth->ppe->dev, type_data); 2610 2611 case TC_SETUP_CLSMATCHALL: 2611 2612 return airoha_dev_tc_matchall(dev, type_data); 2612 2613 default:
+5 -7
drivers/net/ethernet/airoha/airoha_eth.h
··· 13 13 #include <linux/kernel.h> 14 14 #include <linux/netdevice.h> 15 15 #include <linux/reset.h> 16 + #include <linux/soc/airoha/airoha_offload.h> 16 17 #include <net/dsa.h> 17 18 18 19 #define AIROHA_MAX_NUM_GDM_PORTS 4 ··· 227 226 u64 rx_fragment; 228 227 u64 rx_jabber; 229 228 u64 rx_len[7]; 230 - }; 231 - 232 - enum { 233 - PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, 234 229 }; 235 230 236 231 enum { ··· 543 546 #define AIROHA_RXD4_FOE_ENTRY GENMASK(15, 0) 544 547 545 548 struct airoha_ppe { 549 + struct airoha_ppe_dev dev; 546 550 struct airoha_eth *eth; 547 551 548 552 void *foe; ··· 618 620 bool airoha_is_valid_gdm_port(struct airoha_eth *eth, 619 621 struct airoha_gdm_port *port); 620 622 621 - void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, 622 - u16 hash); 623 - int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data); 623 + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, 624 + u16 hash, bool rx_wlan); 625 + int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); 624 626 int airoha_ppe_init(struct airoha_eth *eth); 625 627 void airoha_ppe_deinit(struct airoha_eth *eth); 626 628 void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port);
-1
drivers/net/ethernet/airoha/airoha_npu.c
··· 11 11 #include <linux/of_platform.h> 12 12 #include <linux/of_reserved_mem.h> 13 13 #include <linux/regmap.h> 14 - #include <linux/soc/airoha/airoha_offload.h> 15 14 16 15 #include "airoha_eth.h" 17 16
+85 -27
drivers/net/ethernet/airoha/airoha_ppe.c
··· 6 6 7 7 #include <linux/ip.h> 8 8 #include <linux/ipv6.h> 9 + #include <linux/of_platform.h> 10 + #include <linux/platform_device.h> 9 11 #include <linux/rhashtable.h> 10 - #include <linux/soc/airoha/airoha_offload.h> 11 12 #include <net/ipv6.h> 12 13 #include <net/pkt_cls.h> 13 14 ··· 616 615 617 616 static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, 618 617 struct airoha_foe_entry *e, 619 - u32 hash) 618 + u32 hash, bool rx_wlan) 620 619 { 621 620 struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); 622 621 u32 ts = airoha_ppe_get_timestamp(ppe); ··· 639 638 goto unlock; 640 639 } 641 640 642 - airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); 641 + if (!rx_wlan) 642 + airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); 643 643 644 644 if (hash < PPE_SRAM_NUM_ENTRIES) { 645 645 dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); ··· 666 664 e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE; 667 665 e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, 668 666 AIROHA_FOE_STATE_INVALID); 669 - airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); 667 + airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash, false); 670 668 e->hash = 0xffff; 671 669 } 672 670 if (e->type == FLOW_TYPE_L2_SUBFLOW) { ··· 705 703 static int 706 704 airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe, 707 705 struct airoha_flow_table_entry *e, 708 - u32 hash) 706 + u32 hash, bool rx_wlan) 709 707 { 710 708 u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP; 711 709 struct airoha_foe_entry *hwe_p, hwe; ··· 746 744 } 747 745 748 746 hwe.bridge.data = e->data.bridge.data; 749 - airoha_ppe_foe_commit_entry(ppe, &hwe, hash); 747 + airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan); 750 748 751 749 return 0; 752 750 } 753 751 754 752 static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, 755 753 struct sk_buff *skb, 756 - u32 hash) 754 + u32 hash, bool rx_wlan) 757 755 { 758 756 struct airoha_flow_table_entry *e; 759 757 struct airoha_foe_bridge br = {}; ··· 786 784 if (!airoha_ppe_foe_compare_entry(e, hwe)) 787 785 continue; 788 786 789 - airoha_ppe_foe_commit_entry(ppe, &e->data, hash); 787 + airoha_ppe_foe_commit_entry(ppe, &e->data, hash, rx_wlan); 790 788 commit_done = true; 791 789 e->hash = hash; 792 790 } ··· 798 796 e = rhashtable_lookup_fast(&ppe->l2_flows, &br, 799 797 airoha_l2_flow_table_params); 800 798 if (e) 801 - airoha_ppe_foe_commit_subflow_entry(ppe, e, hash); 799 + airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan); 802 800 unlock: 803 801 spin_unlock_bh(&ppe_lock); 804 802 } ··· 937 935 return airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); 938 936 } 939 937 940 - static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, 938 + static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth, 941 939 struct flow_cls_offload *f) 942 940 { 943 941 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 944 - struct airoha_eth *eth = port->qdma->eth; 945 942 struct airoha_flow_table_entry *e; 946 943 struct airoha_flow_data data = {}; 947 944 struct net_device *odev = NULL; ··· 1137 1136 return err; 1138 1137 } 1139 1138 1140 - static int airoha_ppe_flow_offload_destroy(struct airoha_gdm_port *port, 1139 + static int airoha_ppe_flow_offload_destroy(struct airoha_eth *eth, 1141 1140 struct flow_cls_offload *f) 1142 1141 { 1143 - struct airoha_eth *eth = port->qdma->eth; 1144 1142 struct airoha_flow_table_entry *e; 1145 1143 1146 1144 e = rhashtable_lookup(&eth->flow_table, &f->cookie, ··· 1182 1182 rcu_read_unlock(); 1183 1183 } 1184 1184 1185 - static int airoha_ppe_flow_offload_stats(struct airoha_gdm_port *port, 1185 + static int airoha_ppe_flow_offload_stats(struct airoha_eth *eth, 1186 1186 struct flow_cls_offload *f) 1187 1187 { 1188 - struct airoha_eth *eth = port->qdma->eth; 1189 1188 struct airoha_flow_table_entry *e; 1190 1189 u32 idle; 1191 1190 ··· 1208 1209 return 0; 1209 1210 } 1210 1211 1211 - static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, 1212 + static int airoha_ppe_flow_offload_cmd(struct airoha_eth *eth, 1212 1213 struct flow_cls_offload *f) 1213 1214 { 1214 1215 switch (f->command) { 1215 1216 case FLOW_CLS_REPLACE: 1216 - return airoha_ppe_flow_offload_replace(port, f); 1217 + return airoha_ppe_flow_offload_replace(eth, f); 1217 1218 case FLOW_CLS_DESTROY: 1218 - return airoha_ppe_flow_offload_destroy(port, f); 1219 + return airoha_ppe_flow_offload_destroy(eth, f); 1219 1220 case FLOW_CLS_STATS: 1220 - return airoha_ppe_flow_offload_stats(port, f); 1221 + return airoha_ppe_flow_offload_stats(eth, f); 1221 1222 default: 1222 1223 break; 1223 1224 } ··· 1284 1285 return err; 1285 1286 } 1286 1287 1287 - int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data) 1288 + int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data) 1288 1289 { 1289 - struct airoha_gdm_port *port = netdev_priv(dev); 1290 - struct flow_cls_offload *cls = type_data; 1291 - struct airoha_eth *eth = port->qdma->eth; 1290 + struct airoha_ppe *ppe = dev->priv; 1291 + struct airoha_eth *eth = ppe->eth; 1292 1292 int err = 0; 1293 1293 1294 1294 mutex_lock(&flow_offload_mutex); ··· 1295 1297 if (!eth->npu) 1296 1298 err = airoha_ppe_offload_setup(eth); 1297 1299 if (!err) 1298 - err = airoha_ppe_flow_offload_cmd(port, cls); 1300 + err = airoha_ppe_flow_offload_cmd(eth, type_data); 1299 1301 1300 1302 mutex_unlock(&flow_offload_mutex); 1301 1303 1302 1304 return err; 1303 1305 } 1304 1306 1305 - void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, 1306 - u16 hash) 1307 + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, 1308 + u16 hash, bool rx_wlan) 1307 1309 { 1310 + struct airoha_ppe *ppe = dev->priv; 1308 1311 u16 now, diff; 1309 1312 1310 1313 if (hash > PPE_HASH_MASK) ··· 1317 1318 return; 1318 1319 1319 1320 ppe->foe_check_time[hash] = now; 1320 - airoha_ppe_foe_insert_entry(ppe, skb, hash); 1321 + airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); 1321 1322 } 1322 1323 1323 1324 void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) ··· 1341 1342 PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); 1342 1343 } 1343 1344 1345 + struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev) 1346 + { 1347 + struct platform_device *pdev; 1348 + struct device_node *np; 1349 + struct airoha_eth *eth; 1350 + 1351 + np = of_parse_phandle(dev->of_node, "airoha,eth", 0); 1352 + if (!np) 1353 + return ERR_PTR(-ENODEV); 1354 + 1355 + pdev = of_find_device_by_node(np); 1356 + if (!pdev) { 1357 + dev_err(dev, "cannot find device node %s\n", np->name); 1358 + of_node_put(np); 1359 + return ERR_PTR(-ENODEV); 1360 + } 1361 + of_node_put(np); 1362 + 1363 + if (!try_module_get(THIS_MODULE)) { 1364 + dev_err(dev, "failed to get the device driver module\n"); 1365 + goto error_pdev_put; 1366 + } 1367 + 1368 + eth = platform_get_drvdata(pdev); 1369 + if (!eth) 1370 + goto error_module_put; 1371 + 1372 + if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) { 1373 + dev_err(&pdev->dev, 1374 + "failed to create device link to consumer %s\n", 1375 + dev_name(dev)); 1376 + goto error_module_put; 1377 + } 1378 + 1379 + return &eth->ppe->dev; 1380 + 1381 + error_module_put: 1382 + module_put(THIS_MODULE); 1383 + error_pdev_put: 1384 + platform_device_put(pdev); 1385 + 1386 + return ERR_PTR(-ENODEV); 1387 + } 1388 + EXPORT_SYMBOL_GPL(airoha_ppe_get_dev); 1389 + 1390 + void airoha_ppe_put_dev(struct airoha_ppe_dev *dev) 1391 + { 1392 + struct airoha_ppe *ppe = dev->priv; 1393 + struct airoha_eth *eth = ppe->eth; 1394 + 1395 + module_put(THIS_MODULE); 1396 + put_device(eth->dev); 1397 + } 1398 + EXPORT_SYMBOL_GPL(airoha_ppe_put_dev); 1399 + 1344 1400 int airoha_ppe_init(struct airoha_eth *eth) 1345 1401 { 1346 1402 struct airoha_ppe *ppe; ··· 1404 1350 ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL); 1405 1351 if (!ppe) 1406 1352 return -ENOMEM; 1353 + 1354 + ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb; 1355 + ppe->dev.ops.check_skb = airoha_ppe_check_skb; 1356 + ppe->dev.priv = ppe; 1407 1357 1408 1358 foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry); 1409 1359 ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma,
+55
include/linux/soc/airoha/airoha_offload.h
··· 9 9 #include <linux/spinlock.h> 10 10 #include <linux/workqueue.h> 11 11 12 + enum { 13 + PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, 14 + }; 15 + 16 + struct airoha_ppe_dev { 17 + struct { 18 + int (*setup_tc_block_cb)(struct airoha_ppe_dev *dev, 19 + void *type_data); 20 + void (*check_skb)(struct airoha_ppe_dev *dev, 21 + struct sk_buff *skb, u16 hash, 22 + bool rx_wlan); 23 + } ops; 24 + 25 + void *priv; 26 + }; 27 + 28 + #if (IS_BUILTIN(CONFIG_NET_AIROHA) || IS_MODULE(CONFIG_NET_AIROHA)) 29 + struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev); 30 + void airoha_ppe_put_dev(struct airoha_ppe_dev *dev); 31 + 32 + static inline int airoha_ppe_dev_setup_tc_block_cb(struct airoha_ppe_dev *dev, 33 + void *type_data) 34 + { 35 + return dev->ops.setup_tc_block_cb(dev, type_data); 36 + } 37 + 38 + static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev, 39 + struct sk_buff *skb, 40 + u16 hash, bool rx_wlan) 41 + { 42 + dev->ops.check_skb(dev, skb, hash, rx_wlan); 43 + } 44 + #else 45 + static inline struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev) 46 + { 47 + return NULL; 48 + } 49 + 50 + static inline void airoha_ppe_put_dev(struct airoha_ppe_dev *dev) 51 + { 52 + } 53 + 54 + static inline int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, 55 + void *type_data) 56 + { 57 + return -EOPNOTSUPP; 58 + } 59 + 60 + static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev, 61 + struct sk_buff *skb, u16 hash, 62 + bool rx_wlan) 63 + { 64 + } 65 + #endif 66 + 12 67 #define NPU_NUM_CORES 8 13 68 #define NPU_NUM_IRQ 6 14 69 #define NPU_RX0_DESC_NUM 512