aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-02-11 20:27:37 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-12 19:08:19 -0500
commit76a423a3f8f16bfc7fb86360a620be18c775b94d (patch)
tree79afe85602c388647b06b9bf00c663ff44256244
parenta9fa6e6ac29709e7a623b60695c172da675df045 (diff)
net: phy: allow driver to implement their own aneg_done
Some PHYs out there can be very quirky with respect to how they would report the auto-negotiation is completed. Allow drivers to override the generic aneg_done() implementation by providing their own. Since not all drivers have been updated yet to use genphy_aneg_done() as aneg_done() callback, we explicitely check that this callback is valid before calling into it. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/phy.c9
-rw-r--r--drivers/net/phy/phy_device.c1
-rw-r--r--include/linux/phy.h3
3 files changed, 10 insertions, 3 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index db9c543bd2af..2fa4611709a4 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -114,12 +114,15 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
114 * phy_aneg_done - return auto-negotiation status 114 * phy_aneg_done - return auto-negotiation status
115 * @phydev: target phy_device struct 115 * @phydev: target phy_device struct
116 * 116 *
117 * Description: Reads the status register and returns 0 either if 117 * Description: Return the auto-negotiation status from this @phydev
118 * auto-negotiation is incomplete, or if there was an error. 118 * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation
119 * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done. 119 * is still pending.
120 */ 120 */
121static inline int phy_aneg_done(struct phy_device *phydev) 121static inline int phy_aneg_done(struct phy_device *phydev)
122{ 122{
123 if (phydev->drv->aneg_done)
124 return phydev->drv->aneg_done(phydev);
125
123 return genphy_aneg_done(phydev); 126 return genphy_aneg_done(phydev);
124} 127}
125 128
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 4e7db726028f..7c184208ed4d 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1267,6 +1267,7 @@ static struct phy_driver genphy_driver[] = {
1267 .config_init = genphy_config_init, 1267 .config_init = genphy_config_init,
1268 .features = 0, 1268 .features = 0,
1269 .config_aneg = genphy_config_aneg, 1269 .config_aneg = genphy_config_aneg,
1270 .aneg_done = genphy_aneg_done,
1270 .read_status = genphy_read_status, 1271 .read_status = genphy_read_status,
1271 .suspend = genphy_suspend, 1272 .suspend = genphy_suspend,
1272 .resume = genphy_resume, 1273 .resume = genphy_resume,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c572842c9029..eede6579cae7 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -417,6 +417,9 @@ struct phy_driver {
417 */ 417 */
418 int (*config_aneg)(struct phy_device *phydev); 418 int (*config_aneg)(struct phy_device *phydev);
419 419
420 /* Determines the auto negotiation result */
421 int (*aneg_done)(struct phy_device *phydev);
422
420 /* Determines the negotiated speed and duplex */ 423 /* Determines the negotiated speed and duplex */
421 int (*read_status)(struct phy_device *phydev); 424 int (*read_status)(struct phy_device *phydev);
422 425