aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pcs
diff options
context:
space:
mode:
authorClément Léger <clement.leger@bootlin.com>2022-06-29 14:20:03 +0200
committerJakub Kicinski <kuba@kernel.org>2022-07-01 19:16:00 -0700
commit90c74f4d90ad769fc84e0b91a08b5514d83aa683 (patch)
tree31b0e7a71ee3c3daa269d73b8b07f8b17f07b93b /drivers/net/pcs
parentocteontx2-af: fix operand size in bitwise operation (diff)
downloadlinux-dev-90c74f4d90ad769fc84e0b91a08b5514d83aa683.tar.xz
linux-dev-90c74f4d90ad769fc84e0b91a08b5514d83aa683.zip
net: pcs: rzn1-miic: update speed only if interface is changed
As stated by Russel King, miic_config() can be called as a result of ethtool setting the configuration while the link is already up. Since the speed is also set in this function, it could potentially modify the current speed that is set. This will only happen if there is no PHY present and we aren't using fixed-link mode. Handle that by storing the current interface mode in the miic_port structure and update the speed only if the interface mode is going to be changed. Signed-off-by: Clément Léger <clement.leger@bootlin.com> Link: https://lore.kernel.org/r/20220629122003.189397-1-clement.leger@bootlin.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/pcs')
-rw-r--r--drivers/net/pcs/pcs-rzn1-miic.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c
index d896961e48cc..c1424119e821 100644
--- a/drivers/net/pcs/pcs-rzn1-miic.c
+++ b/drivers/net/pcs/pcs-rzn1-miic.c
@@ -138,11 +138,13 @@ struct miic {
* @miic: backiling to MII converter structure
* @pcs: PCS structure associated to the port
* @port: port number
+ * @interface: interface mode of the port
*/
struct miic_port {
struct miic *miic;
struct phylink_pcs pcs;
int port;
+ phy_interface_t interface;
};
static struct miic_port *phylink_pcs_to_miic_port(struct phylink_pcs *pcs)
@@ -190,8 +192,8 @@ static int miic_config(struct phylink_pcs *pcs, unsigned int mode,
{
struct miic_port *miic_port = phylink_pcs_to_miic_port(pcs);
struct miic *miic = miic_port->miic;
+ u32 speed, conv_mode, val, mask;
int port = miic_port->port;
- u32 speed, conv_mode, val;
switch (interface) {
case PHY_INTERFACE_MODE_RMII:
@@ -216,11 +218,20 @@ static int miic_config(struct phylink_pcs *pcs, unsigned int mode,
return -EOPNOTSUPP;
}
- val = FIELD_PREP(MIIC_CONVCTRL_CONV_MODE, conv_mode) |
- FIELD_PREP(MIIC_CONVCTRL_CONV_SPEED, speed);
+ val = FIELD_PREP(MIIC_CONVCTRL_CONV_MODE, conv_mode);
+ mask = MIIC_CONVCTRL_CONV_MODE;
- miic_reg_rmw(miic, MIIC_CONVCTRL(port),
- MIIC_CONVCTRL_CONV_MODE | MIIC_CONVCTRL_CONV_SPEED, val);
+ /* Update speed only if we are going to change the interface because
+ * the link might already be up and it would break it if the speed is
+ * changed.
+ */
+ if (interface != miic_port->interface) {
+ val |= FIELD_PREP(MIIC_CONVCTRL_CONV_SPEED, speed);
+ mask |= MIIC_CONVCTRL_CONV_SPEED;
+ miic_port->interface = interface;
+ }
+
+ miic_reg_rmw(miic, MIIC_CONVCTRL(port), mask, val);
miic_converter_enable(miic_port->miic, miic_port->port, 1);
return 0;