Commit 92c3807b authored by Russell King (Oracle)'s avatar Russell King (Oracle) Committed by David S. Miller
Browse files

net: stmmac: convert to phylink_get_linkmodes()



Add the MAC speed, duplex and pause capabilities to the phylink_config
structure, and switch stmmac_validate() to use phylink_get_linkmodes()
to generate the mask of supported ethtool link modes.

Tested-by: default avatarWong Vee Khee &lt;vee.khee.wong@linux.intel.com&gt; # Intel EHL Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent be6ec5b7
Loading
Loading
Loading
Loading
+42 −83
Original line number Diff line number Diff line
@@ -942,95 +942,22 @@ static void stmmac_validate(struct phylink_config *config,
{
	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mac_supported) = { 0, };
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
	int tx_cnt = priv->plat->tx_queues_to_use;
	int max_speed = priv->plat->max_speed;

	phylink_set(mac_supported, 10baseT_Half);
	phylink_set(mac_supported, 10baseT_Full);
	phylink_set(mac_supported, 100baseT_Half);
	phylink_set(mac_supported, 100baseT_Full);
	phylink_set(mac_supported, 1000baseT_Half);
	phylink_set(mac_supported, 1000baseT_Full);
	phylink_set(mac_supported, 1000baseKX_Full);

	/* This is very similar to phylink_generic_validate() except that
	 * we always use PHY_INTERFACE_MODE_INTERNAL to get all capabilities.
	 * This is because we don't always have config->supported_interfaces
	 * populated (only when we have the XPCS.)
	 *
	 * When we do have an XPCS, we could pass state->interface, as XPCS
	 * limits to a subset of the ethtool link modes allowed here.
	 */
	phylink_set(mac_supported, Autoneg);
	phylink_set(mac_supported, Pause);
	phylink_set(mac_supported, Asym_Pause);
	phylink_set_port_modes(mac_supported);

	/* Cut down 1G if asked to */
	if ((max_speed > 0) && (max_speed < 1000)) {
		phylink_set(mask, 1000baseT_Full);
		phylink_set(mask, 1000baseX_Full);
	} else if (priv->plat->has_gmac4) {
		if (!max_speed || max_speed >= 2500) {
			phylink_set(mac_supported, 2500baseT_Full);
			phylink_set(mac_supported, 2500baseX_Full);
		}
	} else if (priv->plat->has_xgmac) {
		if (!max_speed || (max_speed >= 2500)) {
			phylink_set(mac_supported, 2500baseT_Full);
			phylink_set(mac_supported, 2500baseX_Full);
		}
		if (!max_speed || (max_speed >= 5000)) {
			phylink_set(mac_supported, 5000baseT_Full);
		}
		if (!max_speed || (max_speed >= 10000)) {
			phylink_set(mac_supported, 10000baseSR_Full);
			phylink_set(mac_supported, 10000baseLR_Full);
			phylink_set(mac_supported, 10000baseER_Full);
			phylink_set(mac_supported, 10000baseLRM_Full);
			phylink_set(mac_supported, 10000baseT_Full);
			phylink_set(mac_supported, 10000baseKX4_Full);
			phylink_set(mac_supported, 10000baseKR_Full);
		}
		if (!max_speed || (max_speed >= 25000)) {
			phylink_set(mac_supported, 25000baseCR_Full);
			phylink_set(mac_supported, 25000baseKR_Full);
			phylink_set(mac_supported, 25000baseSR_Full);
		}
		if (!max_speed || (max_speed >= 40000)) {
			phylink_set(mac_supported, 40000baseKR4_Full);
			phylink_set(mac_supported, 40000baseCR4_Full);
			phylink_set(mac_supported, 40000baseSR4_Full);
			phylink_set(mac_supported, 40000baseLR4_Full);
		}
		if (!max_speed || (max_speed >= 50000)) {
			phylink_set(mac_supported, 50000baseCR2_Full);
			phylink_set(mac_supported, 50000baseKR2_Full);
			phylink_set(mac_supported, 50000baseSR2_Full);
			phylink_set(mac_supported, 50000baseKR_Full);
			phylink_set(mac_supported, 50000baseSR_Full);
			phylink_set(mac_supported, 50000baseCR_Full);
			phylink_set(mac_supported, 50000baseLR_ER_FR_Full);
			phylink_set(mac_supported, 50000baseDR_Full);
		}
		if (!max_speed || (max_speed >= 100000)) {
			phylink_set(mac_supported, 100000baseKR4_Full);
			phylink_set(mac_supported, 100000baseSR4_Full);
			phylink_set(mac_supported, 100000baseCR4_Full);
			phylink_set(mac_supported, 100000baseLR4_ER4_Full);
			phylink_set(mac_supported, 100000baseKR2_Full);
			phylink_set(mac_supported, 100000baseSR2_Full);
			phylink_set(mac_supported, 100000baseCR2_Full);
			phylink_set(mac_supported, 100000baseLR2_ER2_FR2_Full);
			phylink_set(mac_supported, 100000baseDR2_Full);
		}
	}

	/* Half-Duplex can only work with single queue */
	if (tx_cnt > 1) {
		phylink_set(mask, 10baseT_Half);
		phylink_set(mask, 100baseT_Half);
		phylink_set(mask, 1000baseT_Half);
	}
	phylink_get_linkmodes(mac_supported, PHY_INTERFACE_MODE_INTERNAL,
			      config->mac_capabilities);

	linkmode_and(supported, supported, mac_supported);
	linkmode_andnot(supported, supported, mask);

	linkmode_and(state->advertising, state->advertising, mac_supported);
	linkmode_andnot(state->advertising, state->advertising, mask);

	/* If PCS is supported, check which modes it supports. */
	if (priv->hw->xpcs)
@@ -1253,6 +1180,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
{
	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
	struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node);
	int max_speed = priv->plat->max_speed;
	int mode = priv->plat->phy_interface;
	struct phylink *phylink;

@@ -1266,6 +1194,37 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
	if (!fwnode)
		fwnode = dev_fwnode(priv->device);

	priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
		MAC_10 | MAC_100;

	if (!max_speed || max_speed >= 1000)
		priv->phylink_config.mac_capabilities |= MAC_1000;

	if (priv->plat->has_gmac4) {
		if (!max_speed || max_speed >= 2500)
			priv->phylink_config.mac_capabilities |= MAC_2500FD;
	} else if (priv->plat->has_xgmac) {
		if (!max_speed || max_speed >= 2500)
			priv->phylink_config.mac_capabilities |= MAC_2500FD;
		if (!max_speed || max_speed >= 5000)
			priv->phylink_config.mac_capabilities |= MAC_5000FD;
		if (!max_speed || max_speed >= 10000)
			priv->phylink_config.mac_capabilities |= MAC_10000FD;
		if (!max_speed || max_speed >= 25000)
			priv->phylink_config.mac_capabilities |= MAC_25000FD;
		if (!max_speed || max_speed >= 40000)
			priv->phylink_config.mac_capabilities |= MAC_40000FD;
		if (!max_speed || max_speed >= 50000)
			priv->phylink_config.mac_capabilities |= MAC_50000FD;
		if (!max_speed || max_speed >= 100000)
			priv->phylink_config.mac_capabilities |= MAC_100000FD;
	}

	/* Half-Duplex can only work with single queue */
	if (priv->plat->tx_queues_to_use > 1)
		priv->phylink_config.mac_capabilities &=
			~(MAC_10HD | MAC_100HD | MAC_1000HD);

	phylink = phylink_create(&priv->phylink_config, fwnode,
				 mode, &stmmac_phylink_mac_ops);
	if (IS_ERR(phylink))