Skip to content

Commit 4ae2c67

Browse files
committed
Merge branch 'phy-microchip-ksz-9897-errata'
Enguerrand de Ribaucourt says: ==================== Handle new Microchip KSZ 9897 Errata These patches implement some suggested workarounds from the Microchip KSZ 9897 Errata [1]. [1] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9897R-Errata-DS80000758.pdf --- v7: - use dev_crit_once instead of dev_crit_ratelimited - add a comment to help users understand the consequences of half-duplex errors v6: https://lore.kernel.org/netdev/20240614094642.122464-1-enguerrand.de-ribaucourt@savoirfairelinux.com/ - remove KSZ9897 phy_id workaround (was a configuration issue) - use macros for checking link down in monitoring function - check if VLAN is enabled before monitoring resources v5: https://lore.kernel.org/all/20240604092304.314636-1-enguerrand.de-ribaucourt@savoirfairelinux.com/ - use macros for bitfields - rewrap comments - check ksz_pread* return values - fix spelling mistakes - remove KSZ9477 suspend/resume deletion patch v4: https://lore.kernel.org/all/20240531142430.678198-1-enguerrand.de-ribaucourt@savoirfairelinux.com/ - Rebase on net/main - Add Fixes: tags to the patches - reverse x-mas tree order - use pseudo phy_id instead of match_phy_device v3: https://lore.kernel.org/all/20240530102436.226189-1-enguerrand.de-ribaucourt@savoirfairelinux.com/ ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 42354e3 + bf1bff1 commit 4ae2c67

File tree

6 files changed

+79
-2
lines changed

6 files changed

+79
-2
lines changed

drivers/net/dsa/microchip/ksz9477.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,57 @@ void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
427427
mutex_unlock(&p->mib.cnt_mutex);
428428
}
429429

430+
int ksz9477_errata_monitor(struct ksz_device *dev, int port,
431+
u64 tx_late_col)
432+
{
433+
u32 pmavbc;
434+
u8 status;
435+
u16 pqm;
436+
int ret;
437+
438+
ret = ksz_pread8(dev, port, REG_PORT_STATUS_0, &status);
439+
if (ret)
440+
return ret;
441+
if (!(FIELD_GET(PORT_INTF_SPEED_MASK, status) == PORT_INTF_SPEED_NONE) &&
442+
!(status & PORT_INTF_FULL_DUPLEX)) {
443+
/* Errata DS80000754 recommends monitoring potential faults in
444+
* half-duplex mode. The switch might not be able to communicate anymore
445+
* in these states.
446+
* If you see this message, please read the errata-sheet for more information:
447+
* https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9477S-Errata-DS80000754.pdf
448+
* To workaround this issue, half-duplex mode should be avoided.
449+
* A software reset could be implemented to recover from this state.
450+
*/
451+
dev_warn_once(dev->dev,
452+
"Half-duplex detected on port %d, transmission halt may occur\n",
453+
port);
454+
if (tx_late_col != 0) {
455+
/* Transmission halt with late collisions */
456+
dev_crit_once(dev->dev,
457+
"TX late collisions detected, transmission may be halted on port %d\n",
458+
port);
459+
}
460+
ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &status);
461+
if (ret)
462+
return ret;
463+
if (status & SW_VLAN_ENABLE) {
464+
ret = ksz_pread16(dev, port, REG_PORT_QM_TX_CNT_0__4, &pqm);
465+
if (ret)
466+
return ret;
467+
ret = ksz_read32(dev, REG_PMAVBC, &pmavbc);
468+
if (ret)
469+
return ret;
470+
if ((FIELD_GET(PMAVBC_MASK, pmavbc) <= PMAVBC_MIN) ||
471+
(FIELD_GET(PORT_QM_TX_CNT_M, pqm) >= PORT_QM_TX_CNT_MAX)) {
472+
/* Transmission halt with Half-Duplex and VLAN */
473+
dev_crit_once(dev->dev,
474+
"resources out of limits, transmission may be halted\n");
475+
}
476+
}
477+
}
478+
return ret;
479+
}
480+
430481
void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
431482
{
432483
struct ksz_port_mib *mib = &dev->ports[port].mib;
@@ -1297,6 +1348,10 @@ int ksz9477_setup(struct dsa_switch *ds)
12971348
/* Enable REG_SW_MTU__2 reg by setting SW_JUMBO_PACKET */
12981349
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true);
12991350

1351+
/* Use collision based back pressure mode. */
1352+
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_BACK_PRESSURE,
1353+
SW_BACK_PRESSURE_COLLISION);
1354+
13001355
/* Now we can configure default MTU value */
13011356
ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK,
13021357
VLAN_ETH_FRAME_LEN + ETH_FCS_LEN);

drivers/net/dsa/microchip/ksz9477.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ int ksz9477_port_mirror_add(struct ksz_device *dev, int port,
3636
bool ingress, struct netlink_ext_ack *extack);
3737
void ksz9477_port_mirror_del(struct ksz_device *dev, int port,
3838
struct dsa_mall_mirror_tc_entry *mirror);
39+
int ksz9477_errata_monitor(struct ksz_device *dev, int port,
40+
u64 tx_late_col);
3941
void ksz9477_get_caps(struct ksz_device *dev, int port,
4042
struct phylink_config *config);
4143
int ksz9477_fdb_dump(struct ksz_device *dev, int port,

drivers/net/dsa/microchip/ksz9477_reg.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@
247247
#define REG_SW_MAC_CTRL_1 0x0331
248248

249249
#define SW_BACK_PRESSURE BIT(5)
250+
#define SW_BACK_PRESSURE_COLLISION 0
250251
#define FAIR_FLOW_CTRL BIT(4)
251252
#define NO_EXC_COLLISION_DROP BIT(3)
252253
#define SW_JUMBO_PACKET BIT(2)
@@ -842,8 +843,8 @@
842843

843844
#define REG_PORT_STATUS_0 0x0030
844845

845-
#define PORT_INTF_SPEED_M 0x3
846-
#define PORT_INTF_SPEED_S 3
846+
#define PORT_INTF_SPEED_MASK GENMASK(4, 3)
847+
#define PORT_INTF_SPEED_NONE GENMASK(1, 0)
847848
#define PORT_INTF_FULL_DUPLEX BIT(2)
848849
#define PORT_TX_FLOW_CTRL BIT(1)
849850
#define PORT_RX_FLOW_CTRL BIT(0)
@@ -1167,6 +1168,11 @@
11671168
#define PORT_RMII_CLK_SEL BIT(7)
11681169
#define PORT_MII_SEL_EDGE BIT(5)
11691170

1171+
#define REG_PMAVBC 0x03AC
1172+
1173+
#define PMAVBC_MASK GENMASK(26, 16)
1174+
#define PMAVBC_MIN 0x580
1175+
11701176
/* 4 - MAC */
11711177
#define REG_PORT_MAC_CTRL_0 0x0400
11721178

@@ -1494,6 +1500,7 @@
14941500

14951501
#define PORT_QM_TX_CNT_USED_S 0
14961502
#define PORT_QM_TX_CNT_M (BIT(11) - 1)
1503+
#define PORT_QM_TX_CNT_MAX 0x200
14971504

14981505
#define REG_PORT_QM_TX_CNT_1__4 0x0A14
14991506

drivers/net/dsa/microchip/ksz_common.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
13821382
.tc_cbs_supported = true,
13831383
.ops = &ksz9477_dev_ops,
13841384
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
1385+
.phy_errata_9477 = true,
13851386
.mib_names = ksz9477_mib_names,
13861387
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
13871388
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1416,6 +1417,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
14161417
.num_ipms = 8,
14171418
.ops = &ksz9477_dev_ops,
14181419
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
1420+
.phy_errata_9477 = true,
14191421
.mib_names = ksz9477_mib_names,
14201422
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
14211423
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1450,6 +1452,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
14501452
.num_ipms = 8,
14511453
.ops = &ksz9477_dev_ops,
14521454
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
1455+
.phy_errata_9477 = true,
14531456
.mib_names = ksz9477_mib_names,
14541457
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
14551458
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1540,6 +1543,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
15401543
.tc_cbs_supported = true,
15411544
.ops = &ksz9477_dev_ops,
15421545
.phylink_mac_ops = &ksz9477_phylink_mac_ops,
1546+
.phy_errata_9477 = true,
15431547
.mib_names = ksz9477_mib_names,
15441548
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
15451549
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1820,6 +1824,7 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)
18201824
struct rtnl_link_stats64 *stats;
18211825
struct ksz_stats_raw *raw;
18221826
struct ksz_port_mib *mib;
1827+
int ret;
18231828

18241829
mib = &dev->ports[port].mib;
18251830
stats = &mib->stats64;
@@ -1861,6 +1866,12 @@ void ksz_r_mib_stats64(struct ksz_device *dev, int port)
18611866
pstats->rx_pause_frames = raw->rx_pause;
18621867

18631868
spin_unlock(&mib->stats64_lock);
1869+
1870+
if (dev->info->phy_errata_9477) {
1871+
ret = ksz9477_errata_monitor(dev, port, raw->tx_late_col);
1872+
if (ret)
1873+
dev_err(dev->dev, "Failed to monitor transmission halt\n");
1874+
}
18641875
}
18651876

18661877
void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port)

drivers/net/dsa/microchip/ksz_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct ksz_chip_data {
6666
bool tc_cbs_supported;
6767
const struct ksz_dev_ops *ops;
6868
const struct phylink_mac_ops *phylink_mac_ops;
69+
bool phy_errata_9477;
6970
bool ksz87xx_eee_link_erratum;
7071
const struct ksz_mib_names *mib_names;
7172
int mib_cnt;

drivers/net/phy/micrel.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5607,6 +5607,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
56075607
{ PHY_ID_KSZ8081, MICREL_PHY_ID_MASK },
56085608
{ PHY_ID_KSZ8873MLL, MICREL_PHY_ID_MASK },
56095609
{ PHY_ID_KSZ886X, MICREL_PHY_ID_MASK },
5610+
{ PHY_ID_KSZ9477, MICREL_PHY_ID_MASK },
56105611
{ PHY_ID_LAN8814, MICREL_PHY_ID_MASK },
56115612
{ PHY_ID_LAN8804, MICREL_PHY_ID_MASK },
56125613
{ PHY_ID_LAN8841, MICREL_PHY_ID_MASK },

0 commit comments

Comments
 (0)