Skip to content

Commit 1884402

Browse files
triha2workgregkh
authored andcommitted
net: dsa: microchip: Fix reserved multicast address table programming
[ Upstream commit 96baf48 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 6639a9c commit 1884402

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
@@ -1159,9 +1159,15 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
11591159
}
11601160
}
11611161

1162+
#define RESV_MCAST_CNT 8
1163+
1164+
static u8 reserved_mcast_map[RESV_MCAST_CNT] = { 0, 1, 3, 16, 32, 33, 2, 17 };
1165+
11621166
int ksz9477_enable_stp_addr(struct ksz_device *dev)
11631167
{
1168+
u8 i, ports, update;
11641169
const u32 *masks;
1170+
bool override;
11651171
u32 data;
11661172
int ret;
11671173

@@ -1170,23 +1176,87 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev)
11701176
/* Enable Reserved multicast table */
11711177
ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_RESV_MCAST_ENABLE, true);
11721178

1173-
/* Set the Override bit for forwarding BPDU packet to CPU */
1174-
ret = ksz_write32(dev, REG_SW_ALU_VAL_B,
1175-
ALU_V_OVERRIDE | BIT(dev->cpu_port));
1176-
if (ret < 0)
1177-
return ret;
1179+
/* The reserved multicast address table has 8 entries. Each entry has
1180+
* a default value of which port to forward. It is assumed the host
1181+
* port is the last port in most of the switches, but that is not the
1182+
* case for KSZ9477 or maybe KSZ9897. For LAN937X family the default
1183+
* port is port 5, the first RGMII port. It is okay for LAN9370, a
1184+
* 5-port switch, but may not be correct for the other 8-port
1185+
* versions. It is necessary to update the whole table to forward to
1186+
* the right ports.
1187+
* Furthermore PTP messages can use a reserved multicast address and
1188+
* the host will not receive them if this table is not correct.
1189+
*/
1190+
for (i = 0; i < RESV_MCAST_CNT; i++) {
1191+
data = reserved_mcast_map[i] <<
1192+
dev->info->shifts[ALU_STAT_INDEX];
1193+
data |= ALU_STAT_START |
1194+
masks[ALU_STAT_DIRECT] |
1195+
masks[ALU_RESV_MCAST_ADDR] |
1196+
masks[ALU_STAT_READ];
1197+
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1198+
if (ret < 0)
1199+
return ret;
11781200

1179-
data = ALU_STAT_START | ALU_RESV_MCAST_ADDR | masks[ALU_STAT_WRITE];
1201+
/* wait to be finished */
1202+
ret = ksz9477_wait_alu_sta_ready(dev);
1203+
if (ret < 0)
1204+
return ret;
11801205

1181-
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1182-
if (ret < 0)
1183-
return ret;
1206+
ret = ksz_read32(dev, REG_SW_ALU_VAL_B, &data);
1207+
if (ret < 0)
1208+
return ret;
11841209

1185-
/* wait to be finished */
1186-
ret = ksz9477_wait_alu_sta_ready(dev);
1187-
if (ret < 0) {
1188-
dev_err(dev->dev, "Failed to update Reserved Multicast table\n");
1189-
return ret;
1210+
override = false;
1211+
ports = data & dev->port_mask;
1212+
switch (i) {
1213+
case 0:
1214+
case 6:
1215+
/* Change the host port. */
1216+
update = BIT(dev->cpu_port);
1217+
override = true;
1218+
break;
1219+
case 2:
1220+
/* Change the host port. */
1221+
update = BIT(dev->cpu_port);
1222+
break;
1223+
case 4:
1224+
case 5:
1225+
case 7:
1226+
/* Skip the host port. */
1227+
update = dev->port_mask & ~BIT(dev->cpu_port);
1228+
break;
1229+
default:
1230+
update = ports;
1231+
break;
1232+
}
1233+
if (update != ports || override) {
1234+
data &= ~dev->port_mask;
1235+
data |= update;
1236+
/* Set Override bit to receive frame even when port is
1237+
* closed.
1238+
*/
1239+
if (override)
1240+
data |= ALU_V_OVERRIDE;
1241+
ret = ksz_write32(dev, REG_SW_ALU_VAL_B, data);
1242+
if (ret < 0)
1243+
return ret;
1244+
1245+
data = reserved_mcast_map[i] <<
1246+
dev->info->shifts[ALU_STAT_INDEX];
1247+
data |= ALU_STAT_START |
1248+
masks[ALU_STAT_DIRECT] |
1249+
masks[ALU_RESV_MCAST_ADDR] |
1250+
masks[ALU_STAT_WRITE];
1251+
ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
1252+
if (ret < 0)
1253+
return ret;
1254+
1255+
/* wait to be finished */
1256+
ret = ksz9477_wait_alu_sta_ready(dev);
1257+
if (ret < 0)
1258+
return ret;
1259+
}
11901260
}
11911261

11921262
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
@@ -644,6 +644,8 @@ static const u16 ksz9477_regs[] = {
644644
static const u32 ksz9477_masks[] = {
645645
[ALU_STAT_WRITE] = 0,
646646
[ALU_STAT_READ] = 1,
647+
[ALU_STAT_DIRECT] = 0,
648+
[ALU_RESV_MCAST_ADDR] = BIT(1),
647649
[P_MII_TX_FLOW_CTRL] = BIT(5),
648650
[P_MII_RX_FLOW_CTRL] = BIT(3),
649651
};
@@ -671,6 +673,8 @@ static const u8 ksz9477_xmii_ctrl1[] = {
671673
static const u32 lan937x_masks[] = {
672674
[ALU_STAT_WRITE] = 1,
673675
[ALU_STAT_READ] = 2,
676+
[ALU_STAT_DIRECT] = BIT(3),
677+
[ALU_RESV_MCAST_ADDR] = BIT(2),
674678
[P_MII_TX_FLOW_CTRL] = BIT(5),
675679
[P_MII_RX_FLOW_CTRL] = BIT(3),
676680
};

drivers/net/dsa/microchip/ksz_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ enum ksz_masks {
265265
DYNAMIC_MAC_TABLE_TIMESTAMP,
266266
ALU_STAT_WRITE,
267267
ALU_STAT_READ,
268+
ALU_STAT_DIRECT,
269+
ALU_RESV_MCAST_ADDR,
268270
P_MII_TX_FLOW_CTRL,
269271
P_MII_RX_FLOW_CTRL,
270272
};

0 commit comments

Comments
 (0)