Skip to content

Commit 96baf48

Browse files
triha2workkuba-moo
authored andcommitted
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: 457c182 ("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>
1 parent 7d1988a commit 96baf48

File tree

4 files changed

+91
-16
lines changed

4 files changed

+91
-16
lines changed

drivers/net/dsa/microchip/ksz9477.c

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,9 +1355,15 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
13551355
}
13561356
}
13571357

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+
13581362
int ksz9477_enable_stp_addr(struct ksz_device *dev)
13591363
{
1364+
u8 i, ports, update;
13601365
const u32 *masks;
1366+
bool override;
13611367
u32 data;
13621368
int ret;
13631369

@@ -1366,23 +1372,87 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev)
13661372
/* Enable Reserved multicast table */
13671373
ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_RESV_MCAST_ENABLE, true);
13681374

1369-
/* Set the Override bit for forwarding BPDU packet to CPU */
1370-
ret = ksz_write32(dev, REG_SW_ALU_VAL_B,
1371-
ALU_V_OVERRIDE | BIT(dev->cpu_port));
1372-
if (ret < 0)
1373-
return ret;
1375+
/* The reserved multicast address table has 8 entries. Each entry has
1376+
* a default value of which port to forward. It is assumed the host
1377+
* port is the last port in most of the switches, but that is not the
1378+
* case for KSZ9477 or maybe KSZ9897. For LAN937X family the default
1379+
* port is port 5, the first RGMII port. It is okay for LAN9370, a
1380+
* 5-port switch, but may not be correct for the other 8-port
1381+
* versions. It is necessary to update the whole table to forward to
1382+
* the right ports.
1383+
* Furthermore PTP messages can use a reserved multicast address and
1384+
* the host will not receive them if this table is not correct.
1385+
*/
1386+
for (i = 0; i < RESV_MCAST_CNT; i++) {
1387+
data = reserved_mcast_map[i] <<
1388+
dev->info->shifts[ALU_STAT_INDEX];
1389+
data |= ALU_STAT_START |
1390+
masks[ALU_STAT_DIRECT] |
1391+
masks[ALU_RESV_MCAST_ADDR] |
1392+
masks[ALU_STAT_READ];
1393+
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1394+
if (ret < 0)
1395+
return ret;
13741396

1375-
data = ALU_STAT_START | ALU_RESV_MCAST_ADDR | masks[ALU_STAT_WRITE];
1397+
/* wait to be finished */
1398+
ret = ksz9477_wait_alu_sta_ready(dev);
1399+
if (ret < 0)
1400+
return ret;
13761401

1377-
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1378-
if (ret < 0)
1379-
return ret;
1402+
ret = ksz_read32(dev, REG_SW_ALU_VAL_B, &data);
1403+
if (ret < 0)
1404+
return ret;
13801405

1381-
/* wait to be finished */
1382-
ret = ksz9477_wait_alu_sta_ready(dev);
1383-
if (ret < 0) {
1384-
dev_err(dev->dev, "Failed to update Reserved Multicast table\n");
1385-
return ret;
1406+
override = false;
1407+
ports = data & dev->port_mask;
1408+
switch (i) {
1409+
case 0:
1410+
case 6:
1411+
/* Change the host port. */
1412+
update = BIT(dev->cpu_port);
1413+
override = true;
1414+
break;
1415+
case 2:
1416+
/* Change the host port. */
1417+
update = BIT(dev->cpu_port);
1418+
break;
1419+
case 4:
1420+
case 5:
1421+
case 7:
1422+
/* Skip the host port. */
1423+
update = dev->port_mask & ~BIT(dev->cpu_port);
1424+
break;
1425+
default:
1426+
update = ports;
1427+
break;
1428+
}
1429+
if (update != ports || override) {
1430+
data &= ~dev->port_mask;
1431+
data |= update;
1432+
/* Set Override bit to receive frame even when port is
1433+
* closed.
1434+
*/
1435+
if (override)
1436+
data |= ALU_V_OVERRIDE;
1437+
ret = ksz_write32(dev, REG_SW_ALU_VAL_B, data);
1438+
if (ret < 0)
1439+
return ret;
1440+
1441+
data = reserved_mcast_map[i] <<
1442+
dev->info->shifts[ALU_STAT_INDEX];
1443+
data |= ALU_STAT_START |
1444+
masks[ALU_STAT_DIRECT] |
1445+
masks[ALU_RESV_MCAST_ADDR] |
1446+
masks[ALU_STAT_WRITE];
1447+
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1448+
if (ret < 0)
1449+
return ret;
1450+
1451+
/* wait to be finished */
1452+
ret = ksz9477_wait_alu_sta_ready(dev);
1453+
if (ret < 0)
1454+
return ret;
1455+
}
13861456
}
13871457

13881458
return 0;

drivers/net/dsa/microchip/ksz9477_reg.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Microchip KSZ9477 register definitions
44
*
5-
* Copyright (C) 2017-2024 Microchip Technology Inc.
5+
* Copyright (C) 2017-2025 Microchip Technology Inc.
66
*/
77

88
#ifndef __KSZ9477_REGS_H
@@ -397,7 +397,6 @@
397397

398398
#define ALU_RESV_MCAST_INDEX_M (BIT(6) - 1)
399399
#define ALU_STAT_START BIT(7)
400-
#define ALU_RESV_MCAST_ADDR BIT(1)
401400

402401
#define REG_SW_ALU_VAL_A 0x0420
403402

drivers/net/dsa/microchip/ksz_common.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ static const u16 ksz9477_regs[] = {
808808
static const u32 ksz9477_masks[] = {
809809
[ALU_STAT_WRITE] = 0,
810810
[ALU_STAT_READ] = 1,
811+
[ALU_STAT_DIRECT] = 0,
812+
[ALU_RESV_MCAST_ADDR] = BIT(1),
811813
[P_MII_TX_FLOW_CTRL] = BIT(5),
812814
[P_MII_RX_FLOW_CTRL] = BIT(3),
813815
};
@@ -835,6 +837,8 @@ static const u8 ksz9477_xmii_ctrl1[] = {
835837
static const u32 lan937x_masks[] = {
836838
[ALU_STAT_WRITE] = 1,
837839
[ALU_STAT_READ] = 2,
840+
[ALU_STAT_DIRECT] = BIT(3),
841+
[ALU_RESV_MCAST_ADDR] = BIT(2),
838842
[P_MII_TX_FLOW_CTRL] = BIT(5),
839843
[P_MII_RX_FLOW_CTRL] = BIT(3),
840844
};

drivers/net/dsa/microchip/ksz_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ enum ksz_masks {
294294
DYNAMIC_MAC_TABLE_TIMESTAMP,
295295
ALU_STAT_WRITE,
296296
ALU_STAT_READ,
297+
ALU_STAT_DIRECT,
298+
ALU_RESV_MCAST_ADDR,
297299
P_MII_TX_FLOW_CTRL,
298300
P_MII_RX_FLOW_CTRL,
299301
};

0 commit comments

Comments
 (0)