Пример #1
0
static int hns3_set_link_ksettings(struct net_device *netdev,
				   const struct ethtool_link_ksettings *cmd)
{
	/* Only support ksettings_set for netdev with phy attached for now */
	if (netdev->phydev)
		return phy_ethtool_ksettings_set(netdev->phydev, cmd);

	return -EOPNOTSUPP;
}
Пример #2
0
static int
uec_set_ksettings(struct net_device *netdev,
		  const struct ethtool_link_ksettings *cmd)
{
	struct ucc_geth_private *ugeth = netdev_priv(netdev);
	struct phy_device *phydev = ugeth->phydev;

	if (!phydev)
		return -ENODEV;

	return phy_ethtool_ksettings_set(phydev, cmd);
}
Пример #3
0
/**
 *hns_nic_set_link_settings - implement ethtool set link ksettings
 *@net_dev: net_device
 *@cmd: ethtool_link_ksettings
 *retuen 0 - success , negative --fail
 */
static int hns_nic_set_link_ksettings(struct net_device *net_dev,
				      const struct ethtool_link_ksettings *cmd)
{
	struct hns_nic_priv *priv = netdev_priv(net_dev);
	struct hnae_handle *h;
	u32 speed;

	if (!netif_running(net_dev))
		return -ESRCH;

	if (!priv || !priv->ae_handle || !priv->ae_handle->dev ||
	    !priv->ae_handle->dev->ops)
		return -ENODEV;

	h = priv->ae_handle;
	speed = cmd->base.speed;

	if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
		if (cmd->base.autoneg == AUTONEG_ENABLE ||
		    speed != SPEED_10000 ||
		    cmd->base.duplex != DUPLEX_FULL)
			return -EINVAL;
	} else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
		if (!net_dev->phydev && cmd->base.autoneg == AUTONEG_ENABLE)
			return -EINVAL;

		if (speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
			return -EINVAL;
		if (net_dev->phydev)
			return phy_ethtool_ksettings_set(net_dev->phydev, cmd);

		if ((speed != SPEED_10 && speed != SPEED_100 &&
		     speed != SPEED_1000) || (cmd->base.duplex != DUPLEX_HALF &&
		     cmd->base.duplex != DUPLEX_FULL))
			return -EINVAL;
	} else {
		netdev_err(net_dev, "Not supported!");
		return -ENOTSUPP;
	}

	if (h->dev->ops->adjust_link) {
		netif_carrier_off(net_dev);
		h->dev->ops->adjust_link(h, (int)speed, cmd->base.duplex);
		netif_carrier_on(net_dev);
		return 0;
	}

	netdev_err(net_dev, "Not supported!");
	return -ENOTSUPP;
}
Пример #4
0
static int xgene_set_link_ksettings(struct net_device *ndev,
				    const struct ethtool_link_ksettings *cmd)
{
	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
	struct phy_device *phydev = ndev->phydev;

	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
		if (!phydev)
			return -ENODEV;

		return phy_ethtool_ksettings_set(phydev, cmd);
	}

	if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
		if (pdata->mdio_driver) {
			if (!phydev)
				return -ENODEV;

			return phy_ethtool_ksettings_set(phydev, cmd);
		}
	}

	return -EINVAL;
}
Пример #5
0
static int dpaa_set_link_ksettings(struct net_device *net_dev,
				   const struct ethtool_link_ksettings *cmd)
{
	int err;

	if (!net_dev->phydev) {
		netdev_err(net_dev, "phy device not initialized\n");
		return -ENODEV;
	}

	err = phy_ethtool_ksettings_set(net_dev->phydev, cmd);
	if (err < 0)
		netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err);

	return err;
}
Пример #6
0
int phylink_ethtool_ksettings_set(struct phylink *pl,
				  const struct ethtool_link_ksettings *kset)
{
	struct ethtool_link_ksettings our_kset;
	struct phylink_link_state config;
	int ret;

	WARN_ON(!lockdep_rtnl_is_held());

	if (kset->base.autoneg != AUTONEG_DISABLE &&
	    kset->base.autoneg != AUTONEG_ENABLE)
		return -EINVAL;

	config = pl->link_config;

	/* Mask out unsupported advertisments */
	linkmode_and(config.advertising, kset->link_modes.advertising,
		     pl->supported);

	/* FIXME: should we reject autoneg if phy/mac does not support it? */
	if (kset->base.autoneg == AUTONEG_DISABLE) {
		const struct phy_setting *s;

		/* Autonegotiation disabled, select a suitable speed and
		 * duplex.
		 */
		s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
				       pl->supported,
				       __ETHTOOL_LINK_MODE_MASK_NBITS, false);
		if (!s)
			return -EINVAL;

		/* If we have a fixed link (as specified by firmware), refuse
		 * to change link parameters.
		 */
		if (pl->link_an_mode == MLO_AN_FIXED &&
		    (s->speed != pl->link_config.speed ||
		     s->duplex != pl->link_config.duplex))
			return -EINVAL;

		config.speed = s->speed;
		config.duplex = s->duplex;
		config.an_enabled = false;

		__clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
	} else {
		/* If we have a fixed link, refuse to enable autonegotiation */
		if (pl->link_an_mode == MLO_AN_FIXED)
			return -EINVAL;

		config.speed = SPEED_UNKNOWN;
		config.duplex = DUPLEX_UNKNOWN;
		config.an_enabled = true;

		__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
	}

	if (phylink_validate(pl, pl->supported, &config))
		return -EINVAL;

	/* If autonegotiation is enabled, we must have an advertisment */
	if (config.an_enabled && phylink_is_empty_linkmode(config.advertising))
		return -EINVAL;

	our_kset = *kset;
	linkmode_copy(our_kset.link_modes.advertising, config.advertising);
	our_kset.base.speed = config.speed;
	our_kset.base.duplex = config.duplex;

	/* If we have a PHY, configure the phy */
	if (pl->phydev) {
		ret = phy_ethtool_ksettings_set(pl->phydev, &our_kset);
		if (ret)
			return ret;
	}

	mutex_lock(&pl->state_mutex);
	/* Configure the MAC to match the new settings */
	linkmode_copy(pl->link_config.advertising, our_kset.link_modes.advertising);
	pl->link_config.speed = our_kset.base.speed;
	pl->link_config.duplex = our_kset.base.duplex;
	pl->link_config.an_enabled = our_kset.base.autoneg != AUTONEG_DISABLE;

	if (!test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
		phylink_mac_config(pl, &pl->link_config);
		phylink_mac_an_restart(pl);
	}
	mutex_unlock(&pl->state_mutex);

	return 0;
}