realtek: do not reset SerDes on link change
authorBirger Koblitz <git@birger-koblitz.de>
Sun, 24 Apr 2022 20:01:31 +0000 (22:01 +0200)
committerSander Vanheule <sander@svanheule.net>
Sat, 14 May 2022 19:26:14 +0000 (21:26 +0200)
Do not reset the RTL930x SerDes on link changes, instead set up
the SDS with internal PHYs for the SFP+ ports only.
This fixes the 8 1GBit ports on the Zyxel XGS1250 which
do not work without this patch.

A complete SerDes reset was performed on all SerDes links. For copper
1Gbit ports, this is commonly a single XGMII link to an RTL8218D. There
is however no support for setting up the XGMII link on RTL9300/RTL9310,
thereby wiping the (RX/TX) setup done by u-boot and breaking the 1GBit
ports. No SerDes reset should be done for these links.

The handling of SGMII/HiSGMII, 1000BX or 10GR links is actually entirely
different. All these modes need to be suitably RX calibrated and the
pre- main and post- amplifiers set up properly for TX.

The 10GBit SFP+ fiber links are recalibrated instead of reset, which
e.g. is necessary when someone pulls a module out and puts another in.
This makes swapping out 10GBit fiber modules possible. 1GBit modules are
not yet supported, nor any modules with an internal phy.

Tested-by: Stijn Segers <foss@volatilesystems.org>
Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
[rewrite commit message based on discussion]
Link: http://lists.infradead.org/pipermail/openwrt-devel/2022-May/038623.html
Signed-off-by: Sander Vanheule <sander@svanheule.net>
(cherry picked from commit d1b824650f1ee694ec2dbdd2f4f9ec64e650cf86)

target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl83xx.h

index 2e3ab4a805720848d15f5dc2b762bb339d1fd65f..f54fdd298ac4e4957fb46be29244a913521c98f9 100644 (file)
@@ -817,7 +817,8 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port,
                               __func__, phy_modes(state->interface));
                        return;
                }
-               rtl9300_sds_rst(sds_num, sds_mode);
+               if (state->interface == PHY_INTERFACE_MODE_10GBASER)
+                       rtl9300_serdes_setup(sds_num, state->interface);
        }
 
        reg = sw_r32(priv->r->mac_force_mode_ctrl(port));
index 0bb11f9b8b200480427f92a4892a1300f3f6d4fd..107016469c69fa7c5e646186355a9e3876c91653 100644 (file)
@@ -121,6 +121,7 @@ irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
 void rtl930x_vlan_profile_dump(int index);
 int rtl9300_sds_power(int mac, int val);
 void rtl9300_sds_rst(int sds_num, u32 mode);
+int rtl9300_serdes_setup(int sds_num, phy_interface_t phy_mode);
 void rtl930x_print_matrix(void);
 
 /* RTL931x-specific */