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

net: phy: tja11xx: execute cable test on link up

A typical 100Base-T1 link should be always connected. If the link is in
a shot or open state, it is a failure. In most cases, we won't be able
to automatically handle this issue, but we need to log it or notify user
(if possible).

With this patch, the cable will be tested on "ip l s dev .. up" attempt
and send ethnl notification to the user space.

This patch was tested with TJA1102 PHY and "ethtool --monitor" command.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleksij Rempel and committed by
David S. Miller
ca1c933b b0ed0bbf

+43 -5
+43 -5
drivers/net/phy/nxp-tja11xx.c
··· 180 180 return genphy_soft_reset(phydev); 181 181 } 182 182 183 + static int tja11xx_config_aneg_cable_test(struct phy_device *phydev) 184 + { 185 + bool finished = false; 186 + int ret; 187 + 188 + if (phydev->link) 189 + return 0; 190 + 191 + if (!phydev->drv->cable_test_start || 192 + !phydev->drv->cable_test_get_status) 193 + return 0; 194 + 195 + ret = ethnl_cable_test_alloc(phydev); 196 + if (ret) 197 + return ret; 198 + 199 + ret = phydev->drv->cable_test_start(phydev); 200 + if (ret) 201 + return ret; 202 + 203 + /* According to the documentation this test takes 100 usec */ 204 + usleep_range(100, 200); 205 + 206 + ret = phydev->drv->cable_test_get_status(phydev, &finished); 207 + if (ret) 208 + return ret; 209 + 210 + if (finished) 211 + ethnl_cable_test_finished(phydev); 212 + 213 + return 0; 214 + } 215 + 183 216 static int tja11xx_config_aneg(struct phy_device *phydev) 184 217 { 218 + int ret, changed = 0; 185 219 u16 ctl = 0; 186 - int ret; 187 220 188 221 switch (phydev->master_slave_set) { 189 222 case MASTER_SLAVE_CFG_MASTER_FORCE: ··· 226 193 break; 227 194 case MASTER_SLAVE_CFG_UNKNOWN: 228 195 case MASTER_SLAVE_CFG_UNSUPPORTED: 229 - return 0; 196 + goto do_test; 230 197 default: 231 198 phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 232 199 return -ENOTSUPP; 233 200 } 234 201 235 - ret = phy_modify_changed(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, ctl); 236 - if (ret < 0) 202 + changed = phy_modify_changed(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, ctl); 203 + if (changed < 0) 204 + return changed; 205 + 206 + do_test: 207 + ret = tja11xx_config_aneg_cable_test(phydev); 208 + if (ret) 237 209 return ret; 238 210 239 - return __genphy_config_aneg(phydev, ret); 211 + return __genphy_config_aneg(phydev, changed); 240 212 } 241 213 242 214 static int tja11xx_config_init(struct phy_device *phydev)