netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net: phy: Make sure PHY_RESUMING state change is always processed
@ 2015-05-13  1:55 Tim Beale
  2015-05-13  2:44 ` Florian Fainelli
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Tim Beale @ 2015-05-13  1:55 UTC (permalink / raw)
  To: f.fainelli; +Cc: netdev, Tim Beale

If phy_start_aneg() was called while the phydev is in the PHY_RESUMING
state, then its state would immediately transition to PHY_AN (or
PHY_FORCING). This meant the phy_state_machine() never processed the
PHY_RESUMING state change, which meant interrupts weren't enabled for the
PHY. If the PHY used low-power mode (i.e. using BMCR_PDOWN), then the
physical link wouldn't get powered up again.

There seems no point for phy_start_aneg() to make the PHY_RESUMING -->
PHY_AN transition, as the state machine will do this anyway. I'm not sure
about the case where autoneg is disabled, as my patch will change
behaviour so that the PHY goes to PHY_NOLINK instead of PHY_FORCING. An
alternative solution would be to move the phy_config_interrupt() and
phy_resume() work out of the state machine and into phy_start().

The background behind this: we're running linux v3.16.7 and from user-space
we want to enable the eth port (i.e. do a SIOCSIFFLAGS ioctl with the
IFF_UP flag) and immediately afterward set the interface's speed/duplex.
Enabling the interface calls .ndo_open() then phy_start() and the PHY
transitions PHY_HALTED --> PHY_RESUMING. Setting the speed/duplex ends up
calling phy_ethtool_sset(), which calls phy_start_aneg() (meanwhile the
phy_state_machine() hasn't processed the PHY_RESUMING state change yet).

Signed-off-by: Tim Beale <tim.beale@alliedtelesis.co.nz>
---
 drivers/net/phy/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 52cd8db..9855b96 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -465,7 +465,7 @@ int phy_start_aneg(struct phy_device *phydev)
 	if (err < 0)
 		goto out_unlock;
 
-	if (phydev->state != PHY_HALTED) {
+	if (phydev->state != PHY_HALTED && phydev->state != PHY_RESUMING) {
 		if (AUTONEG_ENABLE == phydev->autoneg) {
 			phydev->state = PHY_AN;
 			phydev->link_timeout = PHY_AN_TIMEOUT;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-05-21 20:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-13  1:55 [PATCH] net: phy: Make sure PHY_RESUMING state change is always processed Tim Beale
2015-05-13  2:44 ` Florian Fainelli
2015-05-15 21:25 ` Florian Fainelli
2015-05-16 21:16   ` David Miller
2015-05-18  3:38   ` Tim Beale
2015-05-18  3:38 ` [PATCH] net: phy: Make sure phy_start() always re-enables the phy interrupts Tim Beale
2015-05-21 20:50   ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).