@@ -664,7 +664,7 @@ static void phy_error(struct phy_device *phydev)
664664 * @phy_dat: phy_device pointer
665665 *
666666 * Description: When a PHY interrupt occurs, the handler disables
667- * interrupts, and schedules a work task to clear the interrupt.
667+ * interrupts, and uses phy_change to handle the interrupt.
668668 */
669669static irqreturn_t phy_interrupt (int irq , void * phy_dat )
670670{
@@ -673,15 +673,10 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
673673 if (PHY_HALTED == phydev -> state )
674674 return IRQ_NONE ; /* It can't be ours. */
675675
676- /* The MDIO bus is not allowed to be written in interrupt
677- * context, so we need to disable the irq here. A work
678- * queue will write the PHY to disable and clear the
679- * interrupt, and then reenable the irq line.
680- */
681676 disable_irq_nosync (irq );
682677 atomic_inc (& phydev -> irq_disable );
683678
684- queue_work ( system_power_efficient_wq , & phydev -> phy_queue );
679+ phy_change ( phydev );
685680
686681 return IRQ_HANDLED ;
687682}
@@ -766,12 +761,6 @@ int phy_stop_interrupts(struct phy_device *phydev)
766761
767762 free_irq (phydev -> irq , phydev );
768763
769- /* Cannot call flush_scheduled_work() here as desired because
770- * of rtnl_lock(), but we do not really care about what would
771- * be done, except from enable_irq(), so cancel any work
772- * possibly pending and take care of the matter below.
773- */
774- cancel_work_sync (& phydev -> phy_queue );
775764 /* If work indeed has been cancelled, disable_irq() will have
776765 * been left unbalanced from phy_interrupt() and enable_irq()
777766 * has to be called so that other devices on the line work.
@@ -784,14 +773,11 @@ int phy_stop_interrupts(struct phy_device *phydev)
784773EXPORT_SYMBOL (phy_stop_interrupts );
785774
786775/**
787- * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
788- * @work: work_struct that describes the work to be done
776+ * phy_change - Called by the phy_interrupt to handle PHY changes
777+ * @phydev: phy_device struct that interrupted
789778 */
790- void phy_change (struct work_struct * work )
779+ void phy_change (struct phy_device * phydev )
791780{
792- struct phy_device * phydev =
793- container_of (work , struct phy_device , phy_queue );
794-
795781 if (phy_interrupt_is_valid (phydev )) {
796782 if (phydev -> drv -> did_interrupt &&
797783 !phydev -> drv -> did_interrupt (phydev ))
@@ -832,6 +818,18 @@ void phy_change(struct work_struct *work)
832818 phy_error (phydev );
833819}
834820
821+ /**
822+ * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
823+ * @work: work_struct that describes the work to be done
824+ */
825+ void phy_change_work (struct work_struct * work )
826+ {
827+ struct phy_device * phydev =
828+ container_of (work , struct phy_device , phy_queue );
829+
830+ phy_change (phydev );
831+ }
832+
835833/**
836834 * phy_stop - Bring down the PHY link, and stop checking the status
837835 * @phydev: target phy_device struct
@@ -1116,6 +1114,15 @@ void phy_state_machine(struct work_struct *work)
11161114 PHY_STATE_TIME * HZ );
11171115}
11181116
1117+ /**
1118+ * phy_mac_interrupt - MAC says the link has changed
1119+ * @phydev: phy_device struct with changed link
1120+ * @new_link: Link is Up/Down.
1121+ *
1122+ * Description: The MAC layer is able indicate there has been a change
1123+ * in the PHY link status. Set the new link status, and trigger the
1124+ * state machine, work a work queue.
1125+ */
11191126void phy_mac_interrupt (struct phy_device * phydev , int new_link )
11201127{
11211128 phydev -> link = new_link ;
0 commit comments