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-fix-ipv6-hw-acceleration'

Lorenzo Bianconi says:

====================
net: airoha: Fix IPv6 hw acceleration

Fix IPv6 hw acceleration in bridge mode resolving ib2 and
airoha_foe_mac_info_common overwrite in
airoha_ppe_foe_commit_subflow_entry routine.
Introduce UPDMEM source-mac table used to set source mac address for
L3 IPv6 hw accelerated traffic.
====================

Link: https://patch.msgid.link/20250602-airoha-flowtable-ipv6-fix-v2-0-3287f8b55214@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+54 -11
+2
drivers/net/ethernet/airoha/airoha_eth.c
··· 84 84 val = (addr[3] << 16) | (addr[4] << 8) | addr[5]; 85 85 airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); 86 86 airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); 87 + 88 + airoha_ppe_init_upd_mem(port); 87 89 } 88 90 89 91 static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
+1
drivers/net/ethernet/airoha/airoha_eth.h
··· 614 614 int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data); 615 615 int airoha_ppe_init(struct airoha_eth *eth); 616 616 void airoha_ppe_deinit(struct airoha_eth *eth); 617 + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port); 617 618 struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, 618 619 u32 hash); 619 620 void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
+41 -11
drivers/net/ethernet/airoha/airoha_ppe.c
··· 223 223 int dsa_port = airoha_get_dsa_port(&dev); 224 224 struct airoha_foe_mac_info_common *l2; 225 225 u32 qdata, ports_pad, val; 226 + u8 smac_id = 0xf; 226 227 227 228 memset(hwe, 0, sizeof(*hwe)); 228 229 ··· 258 257 */ 259 258 if (airhoa_is_lan_gdm_port(port)) 260 259 val |= AIROHA_FOE_IB2_FAST_PATH; 260 + 261 + smac_id = port->id; 261 262 } 262 263 263 264 if (is_multicast_ether_addr(data->eth.h_dest)) ··· 294 291 hwe->ipv4.l2.src_mac_lo = 295 292 get_unaligned_be16(data->eth.h_source + 4); 296 293 } else { 297 - l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, 0xf); 294 + l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id); 298 295 } 299 296 300 297 if (data->vlan.num) { ··· 639 636 u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP; 640 637 struct airoha_foe_entry *hwe_p, hwe; 641 638 struct airoha_flow_table_entry *f; 642 - struct airoha_foe_mac_info *l2; 643 639 int type; 644 640 645 641 hwe_p = airoha_ppe_foe_get_entry(ppe, hash); ··· 655 653 656 654 memcpy(&hwe, hwe_p, sizeof(*hwe_p)); 657 655 hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask); 658 - l2 = &hwe.bridge.l2; 659 - memcpy(l2, &e->data.bridge.l2, sizeof(*l2)); 660 656 661 657 type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1); 662 - if (type == PPE_PKT_TYPE_IPV4_HNAPT) 663 - memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple, 664 - sizeof(hwe.ipv4.new_tuple)); 665 - else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T && 666 - l2->common.etype == ETH_P_IP) 667 - l2->common.etype = ETH_P_IPV6; 658 + if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { 659 + memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2)); 660 + hwe.ipv6.ib2 = e->data.bridge.ib2; 661 + /* setting smac_id to 0xf instruct the hw to keep original 662 + * source mac address 663 + */ 664 + hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, 665 + 0xf); 666 + } else { 667 + memcpy(&hwe.bridge.l2, &e->data.bridge.l2, 668 + sizeof(hwe.bridge.l2)); 669 + hwe.bridge.ib2 = e->data.bridge.ib2; 670 + if (type == PPE_PKT_TYPE_IPV4_HNAPT) 671 + memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple, 672 + sizeof(hwe.ipv4.new_tuple)); 673 + } 668 674 669 - hwe.bridge.ib2 = e->data.bridge.ib2; 670 675 hwe.bridge.data = e->data.bridge.data; 671 676 airoha_ppe_foe_commit_entry(ppe, &hwe, hash); 672 677 ··· 1245 1236 1246 1237 ppe->foe_check_time[hash] = now; 1247 1238 airoha_ppe_foe_insert_entry(ppe, skb, hash); 1239 + } 1240 + 1241 + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) 1242 + { 1243 + struct airoha_eth *eth = port->qdma->eth; 1244 + struct net_device *dev = port->dev; 1245 + const u8 *addr = dev->dev_addr; 1246 + u32 val; 1247 + 1248 + val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; 1249 + airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val); 1250 + airoha_fe_wr(eth, REG_UPDMEM_CTRL(0), 1251 + FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) | 1252 + PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); 1253 + 1254 + val = (addr[0] << 8) | addr[1]; 1255 + airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val); 1256 + airoha_fe_wr(eth, REG_UPDMEM_CTRL(0), 1257 + FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) | 1258 + FIELD_PREP(PPE_UPDMEM_OFFSET_MASK, 1) | 1259 + PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); 1248 1260 } 1249 1261 1250 1262 int airoha_ppe_init(struct airoha_eth *eth)
+10
drivers/net/ethernet/airoha/airoha_regs.h
··· 313 313 #define REG_PPE_RAM_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x320) 314 314 #define REG_PPE_RAM_ENTRY(_m, _n) (REG_PPE_RAM_BASE(_m) + ((_n) << 2)) 315 315 316 + #define REG_UPDMEM_CTRL(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x370) 317 + #define PPE_UPDMEM_ACK_MASK BIT(31) 318 + #define PPE_UPDMEM_ADDR_MASK GENMASK(11, 8) 319 + #define PPE_UPDMEM_OFFSET_MASK GENMASK(7, 4) 320 + #define PPE_UPDMEM_SEL_MASK GENMASK(3, 2) 321 + #define PPE_UPDMEM_WR_MASK BIT(1) 322 + #define PPE_UPDMEM_REQ_MASK BIT(0) 323 + 324 + #define REG_UPDMEM_DATA(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x374) 325 + 316 326 #define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) 317 327 #define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) 318 328 #define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288)