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

net: dsa: microchip: Fix reserved multicast address table programming

KSZ9477/KSZ9897 and LAN937X families of switches use a reserved multicast
address table for some specific forwarding with some multicast addresses,
like the one used in STP. The hardware assumes the host port is the last
port in KSZ9897 family and port 5 in LAN937X family. Most of the time
this assumption is correct but not in other cases like KSZ9477.
Originally the function just setups the first entry, but the others still
need update, especially for one common multicast address that is used by
PTP operation.

LAN937x also uses different register bits when accessing the reserved
table.

Fixes: 457c182af597 ("net: dsa: microchip: generic access to ksz9477 static and reserved table")
Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Tested-by: Łukasz Majewski <lukma@nabladev.com>
Link: https://patch.msgid.link/20251105033741.6455-1-Tristram.Ha@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Tristram Ha and committed by
Jakub Kicinski
96baf482 7d1988a9

+91 -16
+84 -14
drivers/net/dsa/microchip/ksz9477.c
··· 1355 1355 } 1356 1356 } 1357 1357 1358 + #define RESV_MCAST_CNT 8 1359 + 1360 + static u8 reserved_mcast_map[RESV_MCAST_CNT] = { 0, 1, 3, 16, 32, 33, 2, 17 }; 1361 + 1358 1362 int ksz9477_enable_stp_addr(struct ksz_device *dev) 1359 1363 { 1364 + u8 i, ports, update; 1360 1365 const u32 *masks; 1366 + bool override; 1361 1367 u32 data; 1362 1368 int ret; 1363 1369 ··· 1372 1366 /* Enable Reserved multicast table */ 1373 1367 ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_RESV_MCAST_ENABLE, true); 1374 1368 1375 - /* Set the Override bit for forwarding BPDU packet to CPU */ 1376 - ret = ksz_write32(dev, REG_SW_ALU_VAL_B, 1377 - ALU_V_OVERRIDE | BIT(dev->cpu_port)); 1378 - if (ret < 0) 1379 - return ret; 1369 + /* The reserved multicast address table has 8 entries. Each entry has 1370 + * a default value of which port to forward. It is assumed the host 1371 + * port is the last port in most of the switches, but that is not the 1372 + * case for KSZ9477 or maybe KSZ9897. For LAN937X family the default 1373 + * port is port 5, the first RGMII port. It is okay for LAN9370, a 1374 + * 5-port switch, but may not be correct for the other 8-port 1375 + * versions. It is necessary to update the whole table to forward to 1376 + * the right ports. 1377 + * Furthermore PTP messages can use a reserved multicast address and 1378 + * the host will not receive them if this table is not correct. 1379 + */ 1380 + for (i = 0; i < RESV_MCAST_CNT; i++) { 1381 + data = reserved_mcast_map[i] << 1382 + dev->info->shifts[ALU_STAT_INDEX]; 1383 + data |= ALU_STAT_START | 1384 + masks[ALU_STAT_DIRECT] | 1385 + masks[ALU_RESV_MCAST_ADDR] | 1386 + masks[ALU_STAT_READ]; 1387 + ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); 1388 + if (ret < 0) 1389 + return ret; 1380 1390 1381 - data = ALU_STAT_START | ALU_RESV_MCAST_ADDR | masks[ALU_STAT_WRITE]; 1391 + /* wait to be finished */ 1392 + ret = ksz9477_wait_alu_sta_ready(dev); 1393 + if (ret < 0) 1394 + return ret; 1382 1395 1383 - ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); 1384 - if (ret < 0) 1385 - return ret; 1396 + ret = ksz_read32(dev, REG_SW_ALU_VAL_B, &data); 1397 + if (ret < 0) 1398 + return ret; 1386 1399 1387 - /* wait to be finished */ 1388 - ret = ksz9477_wait_alu_sta_ready(dev); 1389 - if (ret < 0) { 1390 - dev_err(dev->dev, "Failed to update Reserved Multicast table\n"); 1391 - return ret; 1400 + override = false; 1401 + ports = data & dev->port_mask; 1402 + switch (i) { 1403 + case 0: 1404 + case 6: 1405 + /* Change the host port. */ 1406 + update = BIT(dev->cpu_port); 1407 + override = true; 1408 + break; 1409 + case 2: 1410 + /* Change the host port. */ 1411 + update = BIT(dev->cpu_port); 1412 + break; 1413 + case 4: 1414 + case 5: 1415 + case 7: 1416 + /* Skip the host port. */ 1417 + update = dev->port_mask & ~BIT(dev->cpu_port); 1418 + break; 1419 + default: 1420 + update = ports; 1421 + break; 1422 + } 1423 + if (update != ports || override) { 1424 + data &= ~dev->port_mask; 1425 + data |= update; 1426 + /* Set Override bit to receive frame even when port is 1427 + * closed. 1428 + */ 1429 + if (override) 1430 + data |= ALU_V_OVERRIDE; 1431 + ret = ksz_write32(dev, REG_SW_ALU_VAL_B, data); 1432 + if (ret < 0) 1433 + return ret; 1434 + 1435 + data = reserved_mcast_map[i] << 1436 + dev->info->shifts[ALU_STAT_INDEX]; 1437 + data |= ALU_STAT_START | 1438 + masks[ALU_STAT_DIRECT] | 1439 + masks[ALU_RESV_MCAST_ADDR] | 1440 + masks[ALU_STAT_WRITE]; 1441 + ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); 1442 + if (ret < 0) 1443 + return ret; 1444 + 1445 + /* wait to be finished */ 1446 + ret = ksz9477_wait_alu_sta_ready(dev); 1447 + if (ret < 0) 1448 + return ret; 1449 + } 1392 1450 } 1393 1451 1394 1452 return 0;
+1 -2
drivers/net/dsa/microchip/ksz9477_reg.h
··· 2 2 /* 3 3 * Microchip KSZ9477 register definitions 4 4 * 5 - * Copyright (C) 2017-2024 Microchip Technology Inc. 5 + * Copyright (C) 2017-2025 Microchip Technology Inc. 6 6 */ 7 7 8 8 #ifndef __KSZ9477_REGS_H ··· 397 397 398 398 #define ALU_RESV_MCAST_INDEX_M (BIT(6) - 1) 399 399 #define ALU_STAT_START BIT(7) 400 - #define ALU_RESV_MCAST_ADDR BIT(1) 401 400 402 401 #define REG_SW_ALU_VAL_A 0x0420 403 402
+4
drivers/net/dsa/microchip/ksz_common.c
··· 808 808 static const u32 ksz9477_masks[] = { 809 809 [ALU_STAT_WRITE] = 0, 810 810 [ALU_STAT_READ] = 1, 811 + [ALU_STAT_DIRECT] = 0, 812 + [ALU_RESV_MCAST_ADDR] = BIT(1), 811 813 [P_MII_TX_FLOW_CTRL] = BIT(5), 812 814 [P_MII_RX_FLOW_CTRL] = BIT(3), 813 815 }; ··· 837 835 static const u32 lan937x_masks[] = { 838 836 [ALU_STAT_WRITE] = 1, 839 837 [ALU_STAT_READ] = 2, 838 + [ALU_STAT_DIRECT] = BIT(3), 839 + [ALU_RESV_MCAST_ADDR] = BIT(2), 840 840 [P_MII_TX_FLOW_CTRL] = BIT(5), 841 841 [P_MII_RX_FLOW_CTRL] = BIT(3), 842 842 };
+2
drivers/net/dsa/microchip/ksz_common.h
··· 294 294 DYNAMIC_MAC_TABLE_TIMESTAMP, 295 295 ALU_STAT_WRITE, 296 296 ALU_STAT_READ, 297 + ALU_STAT_DIRECT, 298 + ALU_RESV_MCAST_ADDR, 297 299 P_MII_TX_FLOW_CTRL, 298 300 P_MII_RX_FLOW_CTRL, 299 301 };