Skip to content

Commit c15e10e

Browse files
Tim Bealedavem330
authored andcommitted
net: phy: Make sure phy_start() always re-enables the phy interrupts
This is an alternative way of fixing: commit db9683f ("net: phy: Make sure PHY_RESUMING state change is always processed") When the PHY state transitions from PHY_HALTED to PHY_RESUMING, there are two things we need to do: 1). Re-enable interrupts (and power up the physical link, if powered down) 2). Update the PHY state and net-device based on the link status. There's no strict reason why #1 has to be done from within the main phy_state_machine() function. There is a risk that other changes to the PHY (e.g. setting speed/duplex, which calls phy_start_aneg()) could cause a subsequent state transition before phy_state_machine() has processed the PHY_RESUMING state change. This would leave the PHY with interrupts disabled and/or still in the BMCR_PDOWN/low-power mode. Moving enabling the interrupts and phy_resume() into phy_start() will guarantee this work always gets done. As the PHY is already in the HALTED state and interrupts are disabled, it shouldn't conflict with any work being done in phy_state_machine(). The downside of this change is that if the PHY_RESUMING state is ever entered from anywhere else, it'll also have to repeat this work. Signed-off-by: Tim Beale <tim.beale@alliedtelesis.co.nz> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7764b9d commit c15e10e

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

drivers/net/phy/phy.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ int phy_start_aneg(struct phy_device *phydev)
465465
if (err < 0)
466466
goto out_unlock;
467467

468-
if (phydev->state != PHY_HALTED && phydev->state != PHY_RESUMING) {
468+
if (phydev->state != PHY_HALTED) {
469469
if (AUTONEG_ENABLE == phydev->autoneg) {
470470
phydev->state = PHY_AN;
471471
phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -742,6 +742,9 @@ EXPORT_SYMBOL(phy_stop);
742742
*/
743743
void phy_start(struct phy_device *phydev)
744744
{
745+
bool do_resume = false;
746+
int err = 0;
747+
745748
mutex_lock(&phydev->lock);
746749

747750
switch (phydev->state) {
@@ -752,11 +755,22 @@ void phy_start(struct phy_device *phydev)
752755
phydev->state = PHY_UP;
753756
break;
754757
case PHY_HALTED:
758+
/* make sure interrupts are re-enabled for the PHY */
759+
err = phy_enable_interrupts(phydev);
760+
if (err < 0)
761+
break;
762+
755763
phydev->state = PHY_RESUMING;
764+
do_resume = true;
765+
break;
756766
default:
757767
break;
758768
}
759769
mutex_unlock(&phydev->lock);
770+
771+
/* if phy was suspended, bring the physical link up again */
772+
if (do_resume)
773+
phy_resume(phydev);
760774
}
761775
EXPORT_SYMBOL(phy_start);
762776

@@ -769,7 +783,7 @@ void phy_state_machine(struct work_struct *work)
769783
struct delayed_work *dwork = to_delayed_work(work);
770784
struct phy_device *phydev =
771785
container_of(dwork, struct phy_device, state_queue);
772-
bool needs_aneg = false, do_suspend = false, do_resume = false;
786+
bool needs_aneg = false, do_suspend = false;
773787
int err = 0;
774788

775789
mutex_lock(&phydev->lock);
@@ -888,14 +902,6 @@ void phy_state_machine(struct work_struct *work)
888902
}
889903
break;
890904
case PHY_RESUMING:
891-
err = phy_clear_interrupt(phydev);
892-
if (err)
893-
break;
894-
895-
err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
896-
if (err)
897-
break;
898-
899905
if (AUTONEG_ENABLE == phydev->autoneg) {
900906
err = phy_aneg_done(phydev);
901907
if (err < 0)
@@ -933,7 +939,6 @@ void phy_state_machine(struct work_struct *work)
933939
}
934940
phydev->adjust_link(phydev->attached_dev);
935941
}
936-
do_resume = true;
937942
break;
938943
}
939944

@@ -943,8 +948,6 @@ void phy_state_machine(struct work_struct *work)
943948
err = phy_start_aneg(phydev);
944949
else if (do_suspend)
945950
phy_suspend(phydev);
946-
else if (do_resume)
947-
phy_resume(phydev);
948951

949952
if (err < 0)
950953
phy_error(phydev);

0 commit comments

Comments
 (0)