diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 127 |
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 | */ | ||
624 | static 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 | */ | ||
641 | static 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 | |||
665 | phy_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 | */ | ||
674 | void 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 | */ | ||
658 | static 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) | |||
711 | EXPORT_SYMBOL(phy_stop_interrupts); | 754 | EXPORT_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 | */ | ||
717 | void 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 | |||
741 | phy_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 | */ | ||
749 | void 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 | */ |