diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
| -rw-r--r-- | drivers/net/phy/phy.c | 147 | 
1 files changed, 73 insertions, 74 deletions
| diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index e3e29c2b028b..9aabfa1a455a 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -618,6 +618,77 @@ static void phy_error(struct phy_device *phydev)  }  /** + * phy_disable_interrupts - Disable the PHY interrupts from the PHY side + * @phydev: target phy_device struct + */ +static int phy_disable_interrupts(struct phy_device *phydev) +{ +	int err; + +	/* Disable PHY interrupts */ +	err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); +	if (err) +		goto phy_err; + +	/* Clear the interrupt */ +	err = phy_clear_interrupt(phydev); +	if (err) +		goto phy_err; + +	return 0; + +phy_err: +	phy_error(phydev); + +	return err; +} + +/** + * phy_change - Called by the phy_interrupt to handle PHY changes + * @phydev: phy_device struct that interrupted + */ +static irqreturn_t phy_change(struct phy_device *phydev) +{ +	if (phy_interrupt_is_valid(phydev)) { +		if (phydev->drv->did_interrupt && +		    !phydev->drv->did_interrupt(phydev)) +			return IRQ_NONE; + +		if (phydev->state == PHY_HALTED) +			if (phy_disable_interrupts(phydev)) +				goto phy_err; +	} + +	mutex_lock(&phydev->lock); +	if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) +		phydev->state = PHY_CHANGELINK; +	mutex_unlock(&phydev->lock); + +	/* reschedule state queue work to run as soon as possible */ +	phy_trigger_machine(phydev, true); + +	if (phy_interrupt_is_valid(phydev) && phy_clear_interrupt(phydev)) +		goto phy_err; +	return IRQ_HANDLED; + +phy_err: +	phy_error(phydev); +	return IRQ_NONE; +} + +/** + * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes + * @work: work_struct that describes the work to be done + */ +void phy_change_work(struct work_struct *work) +{ +	struct phy_device *phydev = +		container_of(work, struct phy_device, phy_queue); + +	phy_change(phydev); +} + +/**   * phy_interrupt - PHY interrupt handler   * @irq: interrupt line   * @phy_dat: phy_device pointer @@ -632,9 +703,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)  	if (PHY_HALTED == phydev->state)  		return IRQ_NONE;		/* It can't be ours.  */ -	phy_change(phydev); - -	return IRQ_HANDLED; +	return phy_change(phydev);  }  /** @@ -652,32 +721,6 @@ static int phy_enable_interrupts(struct phy_device *phydev)  }  /** - * phy_disable_interrupts - Disable the PHY interrupts from the PHY side - * @phydev: target phy_device struct - */ -static int phy_disable_interrupts(struct phy_device *phydev) -{ -	int err; - -	/* Disable PHY interrupts */ -	err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); -	if (err) -		goto phy_err; - -	/* Clear the interrupt */ -	err = phy_clear_interrupt(phydev); -	if (err) -		goto phy_err; - -	return 0; - -phy_err: -	phy_error(phydev); - -	return err; -} - -/**   * phy_start_interrupts - request and enable interrupts for a PHY device   * @phydev: target phy_device struct   * @@ -720,50 +763,6 @@ int phy_stop_interrupts(struct phy_device *phydev)  EXPORT_SYMBOL(phy_stop_interrupts);  /** - * phy_change - Called by the phy_interrupt to handle PHY changes - * @phydev: phy_device struct that interrupted - */ -void phy_change(struct phy_device *phydev) -{ -	if (phy_interrupt_is_valid(phydev)) { -		if (phydev->drv->did_interrupt && -		    !phydev->drv->did_interrupt(phydev)) -			return; - -		if (phydev->state == PHY_HALTED) -			if (phy_disable_interrupts(phydev)) -				goto phy_err; -	} - -	mutex_lock(&phydev->lock); -	if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) -		phydev->state = PHY_CHANGELINK; -	mutex_unlock(&phydev->lock); - -	/* reschedule state queue work to run as soon as possible */ -	phy_trigger_machine(phydev, true); - -	if (phy_interrupt_is_valid(phydev) && phy_clear_interrupt(phydev)) -		goto phy_err; -	return; - -phy_err: -	phy_error(phydev); -} - -/** - * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes - * @work: work_struct that describes the work to be done - */ -void phy_change_work(struct work_struct *work) -{ -	struct phy_device *phydev = -		container_of(work, struct phy_device, phy_queue); - -	phy_change(phydev); -} - -/**   * phy_stop - Bring down the PHY link, and stop checking the status   * @phydev: target phy_device struct   */ @@ -819,7 +818,7 @@ void phy_start(struct phy_device *phydev)  		break;  	case PHY_HALTED:  		/* if phy was suspended, bring the physical link up again */ -		phy_resume(phydev); +		__phy_resume(phydev);  		/* make sure interrupts are re-enabled for the PHY */  		if (phy_interrupt_is_valid(phydev)) { | 

