Skip to content

Commit 378e8fe

Browse files
rgantoiskuba-moo
authored andcommitted
net: phy: dp83869: fix status reporting for 1000base-x autonegotiation
The DP83869 PHY transceiver supports converting from RGMII to 1000base-x. In this operation mode, autonegotiation can be performed, as described in IEEE802.3. The DP83869 has a set of fiber-specific registers located at offset 0xc00. When the transceiver is configured in RGMII-to-1000base-x mode, these registers are mapped onto offset 0, which should make reading the autonegotiation status transparent. However, the fiber registers at offset 0xc04 and 0xc05 follow the bit layout specified in Clause 37, and genphy_read_status() assumes a Clause 22 layout. Thus, genphy_read_status() doesn't properly read the capabilities advertised by the link partner, resulting in incorrect link parameters. Similarly, genphy_config_aneg() doesn't properly write advertised capabilities. Fix the 1000base-x autonegotiation procedure by replacing genphy_read_status() and genphy_config_aneg() with their Clause 37 equivalents. Fixes: a29de52 ("net: dp83869: Add ability to advertise Fiber connection") Cc: [email protected] Signed-off-by: Romain Gantois <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent cfaaa7d commit 378e8fe

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

drivers/net/phy/dp83869.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,32 @@ struct dp83869_private {
153153
int mode;
154154
};
155155

156+
static int dp83869_config_aneg(struct phy_device *phydev)
157+
{
158+
struct dp83869_private *dp83869 = phydev->priv;
159+
160+
if (dp83869->mode != DP83869_RGMII_1000_BASE)
161+
return genphy_config_aneg(phydev);
162+
163+
return genphy_c37_config_aneg(phydev);
164+
}
165+
156166
static int dp83869_read_status(struct phy_device *phydev)
157167
{
158168
struct dp83869_private *dp83869 = phydev->priv;
169+
bool changed;
159170
int ret;
160171

172+
if (dp83869->mode == DP83869_RGMII_1000_BASE)
173+
return genphy_c37_read_status(phydev, &changed);
174+
161175
ret = genphy_read_status(phydev);
162176
if (ret)
163177
return ret;
164178

165-
if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
179+
if (dp83869->mode == DP83869_RGMII_100_BASE) {
166180
if (phydev->link) {
167-
if (dp83869->mode == DP83869_RGMII_100_BASE)
168-
phydev->speed = SPEED_100;
181+
phydev->speed = SPEED_100;
169182
} else {
170183
phydev->speed = SPEED_UNKNOWN;
171184
phydev->duplex = DUPLEX_UNKNOWN;
@@ -898,6 +911,7 @@ static int dp83869_phy_reset(struct phy_device *phydev)
898911
.soft_reset = dp83869_phy_reset, \
899912
.config_intr = dp83869_config_intr, \
900913
.handle_interrupt = dp83869_handle_interrupt, \
914+
.config_aneg = dp83869_config_aneg, \
901915
.read_status = dp83869_read_status, \
902916
.get_tunable = dp83869_get_tunable, \
903917
.set_tunable = dp83869_set_tunable, \

0 commit comments

Comments
 (0)