diff options
author | David S. Miller <davem@davemloft.net> | 2024-06-23 10:06:58 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2024-06-23 10:06:58 +0100 |
commit | 4ae2c67840a0a3c88cd71fc3013f958d60f7e50c (patch) | |
tree | 19519e3b3014daf32dbe22c7bca3019e7b9eae3d /drivers/net/dsa/microchip/ksz9477.c | |
parent | 42354e3c3150cf886457f3354af0acefc56b53a2 (diff) | |
parent | bf1bff11e497a01b0cc6cb2afcff734340ae95f8 (diff) | |
download | linux-4ae2c67840a0a3c88cd71fc3013f958d60f7e50c.tar.gz linux-4ae2c67840a0a3c88cd71fc3013f958d60f7e50c.tar.bz2 linux-4ae2c67840a0a3c88cd71fc3013f958d60f7e50c.zip |
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 <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/microchip/ksz9477.c')
-rw-r--r-- | drivers/net/dsa/microchip/ksz9477.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 2231128eef8b..425e20daf1e9 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -427,6 +427,57 @@ void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze) mutex_unlock(&p->mib.cnt_mutex); } +int ksz9477_errata_monitor(struct ksz_device *dev, int port, + u64 tx_late_col) +{ + u32 pmavbc; + u8 status; + u16 pqm; + int ret; + + ret = ksz_pread8(dev, port, REG_PORT_STATUS_0, &status); + if (ret) + return ret; + if (!(FIELD_GET(PORT_INTF_SPEED_MASK, status) == PORT_INTF_SPEED_NONE) && + !(status & PORT_INTF_FULL_DUPLEX)) { + /* Errata DS80000754 recommends monitoring potential faults in + * half-duplex mode. The switch might not be able to communicate anymore + * in these states. + * If you see this message, please read the errata-sheet for more information: + * https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9477S-Errata-DS80000754.pdf + * To workaround this issue, half-duplex mode should be avoided. + * A software reset could be implemented to recover from this state. + */ + dev_warn_once(dev->dev, + "Half-duplex detected on port %d, transmission halt may occur\n", + port); + if (tx_late_col != 0) { + /* Transmission halt with late collisions */ + dev_crit_once(dev->dev, + "TX late collisions detected, transmission may be halted on port %d\n", + port); + } + ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &status); + if (ret) + return ret; + if (status & SW_VLAN_ENABLE) { + ret = ksz_pread16(dev, port, REG_PORT_QM_TX_CNT_0__4, &pqm); + if (ret) + return ret; + ret = ksz_read32(dev, REG_PMAVBC, &pmavbc); + if (ret) + return ret; + if ((FIELD_GET(PMAVBC_MASK, pmavbc) <= PMAVBC_MIN) || + (FIELD_GET(PORT_QM_TX_CNT_M, pqm) >= PORT_QM_TX_CNT_MAX)) { + /* Transmission halt with Half-Duplex and VLAN */ + dev_crit_once(dev->dev, + "resources out of limits, transmission may be halted\n"); + } + } + } + return ret; +} + void ksz9477_port_init_cnt(struct ksz_device *dev, int port) { struct ksz_port_mib *mib = &dev->ports[port].mib; @@ -1297,6 +1348,10 @@ int ksz9477_setup(struct dsa_switch *ds) /* Enable REG_SW_MTU__2 reg by setting SW_JUMBO_PACKET */ ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true); + /* Use collision based back pressure mode. */ + ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_BACK_PRESSURE, + SW_BACK_PRESSURE_COLLISION); + /* Now we can configure default MTU value */ ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK, VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); |