Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: Check for read errors in SIOCGMIIREG

When reading registers from the PHY using the SIOCGMIIREG IOCTL any
errors returned from either mdiobus_read() or mdiobus_c45_read() are
ignored, and parts of the returned error is passed as the register value
back to user-space.

For example, if mdiobus_c45_read() is used with a bus that do not
implement the read_c45() callback -EOPNOTSUPP is returned. This is
however directly stored in mii_data->val_out and returned as the
registers content. As val_out is a u16 the error code is truncated and
returned as a plausible register value.

Fix this by first checking the return value for errors before returning
it as the register content.

Before this patch,

# phytool read eth0/0:1/0
0xffa1

After this change,

$ phytool read eth0/0:1/0
error: phy_read (-95)

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20240903171536.628930-1-niklas.soderlund+renesas@ragnatech.se
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Niklas Söderlund and committed by
Jakub Kicinski
569bf6d4 8ed6e712

+11 -6
+11 -6
drivers/net/phy/phy.c
··· 342 342 if (mdio_phy_id_is_c45(mii_data->phy_id)) { 343 343 prtad = mdio_phy_id_prtad(mii_data->phy_id); 344 344 devad = mdio_phy_id_devad(mii_data->phy_id); 345 - mii_data->val_out = mdiobus_c45_read( 346 - phydev->mdio.bus, prtad, devad, 347 - mii_data->reg_num); 345 + ret = mdiobus_c45_read(phydev->mdio.bus, prtad, devad, 346 + mii_data->reg_num); 347 + 348 348 } else { 349 - mii_data->val_out = mdiobus_read( 350 - phydev->mdio.bus, mii_data->phy_id, 351 - mii_data->reg_num); 349 + ret = mdiobus_read(phydev->mdio.bus, mii_data->phy_id, 350 + mii_data->reg_num); 352 351 } 352 + 353 + if (ret < 0) 354 + return ret; 355 + 356 + mii_data->val_out = ret; 357 + 353 358 return 0; 354 359 355 360 case SIOCSMIIREG: