aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c127
1 files changed, 63 insertions, 64 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c2d9027be863..05c1e8ef15e6 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -618,6 +618,68 @@ static void phy_error(struct phy_device *phydev)
618} 618}
619 619
620/** 620/**
621 * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
622 * @phydev: target phy_device struct
623 */
624static int phy_disable_interrupts(struct phy_device *phydev)
625{
626 int err;
627
628 /* Disable PHY interrupts */
629 err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
630 if (err)
631 return err;
632
633 /* Clear the interrupt */
634 return phy_clear_interrupt(phydev);
635}
636
637/**
638 * phy_change - Called by the phy_interrupt to handle PHY changes
639 * @phydev: phy_device struct that interrupted
640 */
641static irqreturn_t phy_change(struct phy_device *phydev)
642{
643 if (phy_interrupt_is_valid(phydev)) {
644 if (phydev->drv->did_interrupt &&
645 !phydev->drv->did_interrupt(phydev))
646 return IRQ_NONE;
647
648 if (phydev->state == PHY_HALTED)
649 if (phy_disable_interrupts(phydev))
650 goto phy_err;
651 }
652
653 mutex_lock(&phydev->lock);
654 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
655 phydev->state = PHY_CHANGELINK;
656 mutex_unlock(&phydev->lock);
657
658 /* reschedule state queue work to run as soon as possible */
659 phy_trigger_machine(phydev, true);
660
661 if (phy_interrupt_is_valid(phydev) && phy_clear_interrupt(phydev))
662 goto phy_err;
663 return IRQ_HANDLED;
664
665phy_err:
666 phy_error(phydev);
667 return IRQ_NONE;
668}
669
670/**
671 * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
672 * @work: work_struct that describes the work to be done
673 */
674void phy_change_work(struct work_struct *work)
675{
676 struct phy_device *phydev =
677 container_of(work, struct phy_device, phy_queue);
678
679 phy_change(phydev);
680}
681
682/**
621 * phy_interrupt - PHY interrupt handler 683 * phy_interrupt - PHY interrupt handler
622 * @irq: interrupt line 684 * @irq: interrupt line
623 * @phy_dat: phy_device pointer 685 * @phy_dat: phy_device pointer
@@ -632,9 +694,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
632 if (PHY_HALTED == phydev->state) 694 if (PHY_HALTED == phydev->state)
633 return IRQ_NONE; /* It can't be ours. */ 695 return IRQ_NONE; /* It can't be ours. */
634 696
635 phy_change(phydev); 697 return phy_change(phydev);
636
637 return IRQ_HANDLED;
638} 698}
639 699
640/** 700/**
@@ -652,23 +712,6 @@ static int phy_enable_interrupts(struct phy_device *phydev)
652} 712}
653 713
654/** 714/**
655 * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
656 * @phydev: target phy_device struct
657 */
658static int phy_disable_interrupts(struct phy_device *phydev)
659{
660 int err;
661
662 /* Disable PHY interrupts */
663 err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
664 if (err)
665 return err;
666
667 /* Clear the interrupt */
668 return phy_clear_interrupt(phydev);
669}
670
671/**
672 * phy_start_interrupts - request and enable interrupts for a PHY device 715 * phy_start_interrupts - request and enable interrupts for a PHY device
673 * @phydev: target phy_device struct 716 * @phydev: target phy_device struct
674 * 717 *
@@ -711,50 +754,6 @@ int phy_stop_interrupts(struct phy_device *phydev)
711EXPORT_SYMBOL(phy_stop_interrupts); 754EXPORT_SYMBOL(phy_stop_interrupts);
712 755
713/** 756/**
714 * phy_change - Called by the phy_interrupt to handle PHY changes
715 * @phydev: phy_device struct that interrupted
716 */
717void phy_change(struct phy_device *phydev)
718{
719 if (phy_interrupt_is_valid(phydev)) {
720 if (phydev->drv->did_interrupt &&
721 !phydev->drv->did_interrupt(phydev))
722 return;
723
724 if (phydev->state == PHY_HALTED)
725 if (phy_disable_interrupts(phydev))
726 goto phy_err;
727 }
728
729 mutex_lock(&phydev->lock);
730 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
731 phydev->state = PHY_CHANGELINK;
732 mutex_unlock(&phydev->lock);
733
734 /* reschedule state queue work to run as soon as possible */
735 phy_trigger_machine(phydev, true);
736
737 if (phy_interrupt_is_valid(phydev) && phy_clear_interrupt(phydev))
738 goto phy_err;
739 return;
740
741phy_err:
742 phy_error(phydev);
743}
744
745/**
746 * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
747 * @work: work_struct that describes the work to be done
748 */
749void phy_change_work(struct work_struct *work)
750{
751 struct phy_device *phydev =
752 container_of(work, struct phy_device, phy_queue);
753
754 phy_change(phydev);
755}
756
757/**
758 * phy_stop - Bring down the PHY link, and stop checking the status 757 * phy_stop - Bring down the PHY link, and stop checking the status
759 * @phydev: target phy_device struct 758 * @phydev: target phy_device struct
760 */ 759 */