net: phy: add phy_check_link_status
In few places in the state machine the state is set to PHY_RUNNING or PHY_NOLINK after doing a phy_read_status(). So factor this out to phy_check_link_status(). First use it in phy_start_aneg(): By setting the state to PHY_RUNNING or PHY_NOLINK directly we can remove the code to handle the case that we're using interrupts and aneg was finished already. Definition of phy_link_up and phy_link_down needs to be moved because they are called in the new function. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
c96469f830
Коммит
74a992b359
|
@ -62,6 +62,17 @@ static const char *phy_state_to_str(enum phy_state st)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void phy_link_up(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
phydev->phy_link_change(phydev, true, true);
|
||||||
|
phy_led_trigger_change_speed(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void phy_link_down(struct phy_device *phydev, bool do_carrier)
|
||||||
|
{
|
||||||
|
phydev->phy_link_change(phydev, false, do_carrier);
|
||||||
|
phy_led_trigger_change_speed(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* phy_print_status - Convenience function to print out the current phy status
|
* phy_print_status - Convenience function to print out the current phy status
|
||||||
|
@ -493,6 +504,34 @@ static int phy_config_aneg(struct phy_device *phydev)
|
||||||
return genphy_config_aneg(phydev);
|
return genphy_config_aneg(phydev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* phy_check_link_status - check link status and set state accordingly
|
||||||
|
* @phydev: the phy_device struct
|
||||||
|
*
|
||||||
|
* Description: Check for link and whether autoneg was triggered / is running
|
||||||
|
* and set state accordingly
|
||||||
|
*/
|
||||||
|
static int phy_check_link_status(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
WARN_ON(!mutex_is_locked(&phydev->lock));
|
||||||
|
|
||||||
|
err = phy_read_status(phydev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (phydev->link && phydev->state != PHY_RUNNING) {
|
||||||
|
phydev->state = PHY_RUNNING;
|
||||||
|
phy_link_up(phydev);
|
||||||
|
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
|
||||||
|
phydev->state = PHY_NOLINK;
|
||||||
|
phy_link_down(phydev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* phy_start_aneg - start auto-negotiation for this PHY device
|
* phy_start_aneg - start auto-negotiation for this PHY device
|
||||||
* @phydev: the phy_device struct
|
* @phydev: the phy_device struct
|
||||||
|
@ -504,7 +543,6 @@ static int phy_config_aneg(struct phy_device *phydev)
|
||||||
*/
|
*/
|
||||||
int phy_start_aneg(struct phy_device *phydev)
|
int phy_start_aneg(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
bool trigger = 0;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!phydev->drv)
|
if (!phydev->drv)
|
||||||
|
@ -524,32 +562,16 @@ int phy_start_aneg(struct phy_device *phydev)
|
||||||
|
|
||||||
if (phydev->state != PHY_HALTED) {
|
if (phydev->state != PHY_HALTED) {
|
||||||
if (AUTONEG_ENABLE == phydev->autoneg) {
|
if (AUTONEG_ENABLE == phydev->autoneg) {
|
||||||
phydev->state = PHY_AN;
|
err = phy_check_link_status(phydev);
|
||||||
phydev->link_timeout = PHY_AN_TIMEOUT;
|
|
||||||
} else {
|
} else {
|
||||||
phydev->state = PHY_FORCING;
|
phydev->state = PHY_FORCING;
|
||||||
phydev->link_timeout = PHY_FORCE_TIMEOUT;
|
phydev->link_timeout = PHY_FORCE_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-schedule a PHY state machine to check PHY status because
|
|
||||||
* negotiation may already be done and aneg interrupt may not be
|
|
||||||
* generated.
|
|
||||||
*/
|
|
||||||
if (!phy_polling_mode(phydev) && phydev->state == PHY_AN) {
|
|
||||||
err = phy_aneg_done(phydev);
|
|
||||||
if (err > 0) {
|
|
||||||
trigger = true;
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&phydev->lock);
|
mutex_unlock(&phydev->lock);
|
||||||
|
|
||||||
if (trigger)
|
|
||||||
phy_trigger_machine(phydev);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(phy_start_aneg);
|
EXPORT_SYMBOL(phy_start_aneg);
|
||||||
|
@ -893,18 +915,6 @@ void phy_start(struct phy_device *phydev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(phy_start);
|
EXPORT_SYMBOL(phy_start);
|
||||||
|
|
||||||
static void phy_link_up(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
phydev->phy_link_change(phydev, true, true);
|
|
||||||
phy_led_trigger_change_speed(phydev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void phy_link_down(struct phy_device *phydev, bool do_carrier)
|
|
||||||
{
|
|
||||||
phydev->phy_link_change(phydev, false, do_carrier);
|
|
||||||
phy_led_trigger_change_speed(phydev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* phy_state_machine - Handle the state machine
|
* phy_state_machine - Handle the state machine
|
||||||
* @work: work_struct that describes the work to be done
|
* @work: work_struct that describes the work to be done
|
||||||
|
|
Загрузка…
Ссылка в новой задаче