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; }
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); }
/** *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; }
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; }
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; }
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; }