Newer
Older
eee_lp = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
if (eee_lp <= 0)
goto eee_exit_err;
eee_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
if (eee_adv <= 0)
goto eee_exit_err;
mmd_eee_adv_to_linkmode(adv, eee_adv);
mmd_eee_adv_to_linkmode(lp, eee_lp);
linkmode_and(common, adv, lp);
if (!phy_check_valid(phydev->speed, phydev->duplex, common))
/* Configure the PHY to stop receiving xMII
* clock while it is signaling LPI.
*/
phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
MDIO_PCS_CTRL1_CLKSTOP_EN);
}
}
EXPORT_SYMBOL(phy_init_eee);
/**
* phy_get_eee_err - report the EEE wake error count
* @phydev: target phy_device struct
*
* Description: it is to report the number of time where the PHY
* failed to complete its normal wake sequence.
*/
int phy_get_eee_err(struct phy_device *phydev)
{
if (!phydev->drv)
return -EIO;
return phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR);
}
EXPORT_SYMBOL(phy_get_eee_err);
/**
* phy_ethtool_get_eee - get EEE supported and status
* @phydev: target phy_device struct
* @data: ethtool_eee data
*
* Description: it reportes the Supported/Advertisement/LP Advertisement
* capabilities.
*/
int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
int val;
if (!phydev->drv)
return -EIO;
/* Get Supported EEE */
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
if (val < 0)
return val;
data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
/* Get advertisement EEE */
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
if (val < 0)
return val;
data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
data->eee_enabled = !!data->advertised;
/* Get LP advertisement EEE */
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
if (val < 0)
return val;
data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
data->eee_active = !!(data->advertised & data->lp_advertised);
return 0;
}
EXPORT_SYMBOL(phy_ethtool_get_eee);
/**
* phy_ethtool_set_eee - set EEE supported and status
* @phydev: target phy_device struct
* @data: ethtool_eee data
*
* Description: it is to program the Advertisement EEE register.
*/
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
int cap, old_adv, adv = 0, ret;
if (!phydev->drv)
return -EIO;
/* Get Supported EEE */
cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
if (cap < 0)
return cap;
old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
if (old_adv < 0)
return old_adv;
if (data->eee_enabled) {
adv = !data->advertised ? cap :
ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
/* Mask prohibited EEE modes */
adv &= ~phydev->eee_broken_modes;
}
if (old_adv != adv) {
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
if (ret < 0)
return ret;
/* Restart autonegotiation so the new modes get sent to the
* link partner.
*/
ret = phy_restart_aneg(phydev);
if (ret < 0)
return ret;
}
return 0;
}
EXPORT_SYMBOL(phy_ethtool_set_eee);
int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
{
if (phydev->drv && phydev->drv->set_wol)
return phydev->drv->set_wol(phydev, wol);
return -EOPNOTSUPP;
}
EXPORT_SYMBOL(phy_ethtool_set_wol);
void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
{
if (phydev->drv && phydev->drv->get_wol)
phydev->drv->get_wol(phydev, wol);
}
EXPORT_SYMBOL(phy_ethtool_get_wol);
int phy_ethtool_get_link_ksettings(struct net_device *ndev,
struct ethtool_link_ksettings *cmd)
{
struct phy_device *phydev = ndev->phydev;
if (!phydev)
return -ENODEV;
phy_ethtool_ksettings_get(phydev, cmd);
return 0;
}
EXPORT_SYMBOL(phy_ethtool_get_link_ksettings);
int phy_ethtool_set_link_ksettings(struct net_device *ndev,
const struct ethtool_link_ksettings *cmd)
{
struct phy_device *phydev = ndev->phydev;
if (!phydev)
return -ENODEV;
return phy_ethtool_ksettings_set(phydev, cmd);
}
EXPORT_SYMBOL(phy_ethtool_set_link_ksettings);
int phy_ethtool_nway_reset(struct net_device *ndev)
{
struct phy_device *phydev = ndev->phydev;
if (!phydev)
return -ENODEV;
if (!phydev->drv)
return -EIO;
return phy_restart_aneg(phydev);
}
EXPORT_SYMBOL(phy_ethtool_nway_reset);