diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 8763bb20988a..5590b9c182c9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -692,25 +692,29 @@ void phy_change(struct work_struct *work) | |||
692 | struct phy_device *phydev = | 692 | struct phy_device *phydev = |
693 | container_of(work, struct phy_device, phy_queue); | 693 | container_of(work, struct phy_device, phy_queue); |
694 | 694 | ||
695 | if (phydev->drv->did_interrupt && | 695 | if (phy_interrupt_is_valid(phydev)) { |
696 | !phydev->drv->did_interrupt(phydev)) | 696 | if (phydev->drv->did_interrupt && |
697 | goto ignore; | 697 | !phydev->drv->did_interrupt(phydev)) |
698 | goto ignore; | ||
698 | 699 | ||
699 | if (phy_disable_interrupts(phydev)) | 700 | if (phy_disable_interrupts(phydev)) |
700 | goto phy_err; | 701 | goto phy_err; |
702 | } | ||
701 | 703 | ||
702 | mutex_lock(&phydev->lock); | 704 | mutex_lock(&phydev->lock); |
703 | if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) | 705 | if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) |
704 | phydev->state = PHY_CHANGELINK; | 706 | phydev->state = PHY_CHANGELINK; |
705 | mutex_unlock(&phydev->lock); | 707 | mutex_unlock(&phydev->lock); |
706 | 708 | ||
707 | atomic_dec(&phydev->irq_disable); | 709 | if (phy_interrupt_is_valid(phydev)) { |
708 | enable_irq(phydev->irq); | 710 | atomic_dec(&phydev->irq_disable); |
711 | enable_irq(phydev->irq); | ||
709 | 712 | ||
710 | /* Reenable interrupts */ | 713 | /* Reenable interrupts */ |
711 | if (PHY_HALTED != phydev->state && | 714 | if (PHY_HALTED != phydev->state && |
712 | phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) | 715 | phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED)) |
713 | goto irq_enable_err; | 716 | goto irq_enable_err; |
717 | } | ||
714 | 718 | ||
715 | /* reschedule state queue work to run as soon as possible */ | 719 | /* reschedule state queue work to run as soon as possible */ |
716 | cancel_delayed_work_sync(&phydev->state_queue); | 720 | cancel_delayed_work_sync(&phydev->state_queue); |
@@ -905,10 +909,10 @@ void phy_state_machine(struct work_struct *work) | |||
905 | phydev->adjust_link(phydev->attached_dev); | 909 | phydev->adjust_link(phydev->attached_dev); |
906 | break; | 910 | break; |
907 | case PHY_RUNNING: | 911 | case PHY_RUNNING: |
908 | /* Only register a CHANGE if we are polling or ignoring | 912 | /* Only register a CHANGE if we are polling and link changed |
909 | * interrupts and link changed since latest checking. | 913 | * since latest checking. |
910 | */ | 914 | */ |
911 | if (!phy_interrupt_is_valid(phydev)) { | 915 | if (phydev->irq == PHY_POLL) { |
912 | old_link = phydev->link; | 916 | old_link = phydev->link; |
913 | err = phy_read_status(phydev); | 917 | err = phy_read_status(phydev); |
914 | if (err) | 918 | if (err) |
@@ -1000,15 +1004,21 @@ void phy_state_machine(struct work_struct *work) | |||
1000 | phy_state_to_str(old_state), | 1004 | phy_state_to_str(old_state), |
1001 | phy_state_to_str(phydev->state)); | 1005 | phy_state_to_str(phydev->state)); |
1002 | 1006 | ||
1003 | queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, | 1007 | /* Only re-schedule a PHY state machine change if we are polling the |
1004 | PHY_STATE_TIME * HZ); | 1008 | * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving |
1009 | * between states from phy_mac_interrupt() | ||
1010 | */ | ||
1011 | if (phydev->irq == PHY_POLL) | ||
1012 | queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, | ||
1013 | PHY_STATE_TIME * HZ); | ||
1005 | } | 1014 | } |
1006 | 1015 | ||
1007 | void phy_mac_interrupt(struct phy_device *phydev, int new_link) | 1016 | void phy_mac_interrupt(struct phy_device *phydev, int new_link) |
1008 | { | 1017 | { |
1009 | cancel_work_sync(&phydev->phy_queue); | ||
1010 | phydev->link = new_link; | 1018 | phydev->link = new_link; |
1011 | schedule_work(&phydev->phy_queue); | 1019 | |
1020 | /* Trigger a state machine change */ | ||
1021 | queue_work(system_power_efficient_wq, &phydev->phy_queue); | ||
1012 | } | 1022 | } |
1013 | EXPORT_SYMBOL(phy_mac_interrupt); | 1023 | EXPORT_SYMBOL(phy_mac_interrupt); |
1014 | 1024 | ||