Commit 6b67e098 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-pcs-xpcs-cleanups-batch-1'

Russell King says:

====================
net: pcs: xpcs: cleanups batch 1

First, sorry for the bland series subject - this is the first in a
number of cleanup series to the XPCS driver. This series has some
functional changes beyond merely cleanups, notably the first patch.

This series starts off with a patch that moves the PCS reset from
the xpcs_create*() family of calls to when phylink first configures
the PHY. The motivation for this change is to get rid of the
interface argument to the xpcs_create*() functions, which I see as
unnecessary complexity. This patch should be tested on Wangxun
and STMMAC drivers.

Patch 2 removes the now unnecessary interface argument from the
internal xpcs_create() and xpcs_init_iface() functions. With this,
xpcs_init_iface() becomes a misnamed function, but patch 3 removes
this function, moving its now meager contents to xpcs_create().

Patch 4 adds xpcs_destroy_pcs() and xpcs_create_pcs_mdiodev()
functions which return and take a phylink_pcs, allowing SJA1105
and Wangxun drivers to be converted to using the phylink_pcs
structure internally.

Patches 5 through 8 convert both these drivers to that end.

Patch 9 drops the interface argument from the remaining xpcs_create*()
functions, addressing the only remaining caller of these functions,
that being the STMMAC driver.

As patch 7 removed the direct calls to the XPCS config/link-up
functions, the last patch makes these functions static.
====================

Link: https://patch.msgid.link/ZvwdKIp3oYSenGdH@shell.armlinux.org.uk


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 78997e9a faefc973
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -278,7 +278,7 @@ struct sja1105_private {
	struct mii_bus *mdio_base_t1;
	struct mii_bus *mdio_base_tx;
	struct mii_bus *mdio_pcs;
	struct dw_xpcs *xpcs[SJA1105_MAX_NUM_PORTS];
	struct phylink_pcs *pcs[SJA1105_MAX_NUM_PORTS];
	struct sja1105_ptp_data ptp_data;
	struct sja1105_tas_data tas_data;
};
+42 −43
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_mdio.h>
#include <linux/pcs/pcs-xpcs.h>
#include <linux/netdev_features.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
@@ -1257,29 +1256,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv)
	return rc;
}

/* Convert link speed from SJA1105 to ethtool encoding */
static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv,
					 u64 speed)
{
	if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS])
		return SPEED_10;
	if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS])
		return SPEED_100;
	if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS])
		return SPEED_1000;
	if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS])
		return SPEED_2500;
	return SPEED_UNKNOWN;
}

/* Set link speed in the MAC configuration for a specific port. */
static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
static int sja1105_set_port_speed(struct sja1105_private *priv, int port,
				  int speed_mbps)
{
	struct sja1105_mac_config_entry *mac;
	struct device *dev = priv->ds->dev;
	u64 speed;
	int rc;

	/* On P/Q/R/S, one can read from the device via the MAC reconfiguration
	 * tables. On E/T, MAC reconfig tables are not readable, only writable.
@@ -1313,7 +1294,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
		speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];
		break;
	default:
		dev_err(dev, "Invalid speed %iMbps\n", speed_mbps);
		dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps);
		return -EINVAL;
	}

@@ -1325,12 +1306,32 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
	 * we need to configure the PCS only (if even that).
	 */
	if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII)
		mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
		speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
	else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX)
		mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];
	else
		speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS];

	mac[port].speed = speed;

	return 0;
}

/* Write the MAC Configuration Table entry and, if necessary, the CGU settings,
 * after a link speedchange for this port.
 */
static int sja1105_set_port_config(struct sja1105_private *priv, int port)
{
	struct sja1105_mac_config_entry *mac;
	struct device *dev = priv->ds->dev;
	int rc;

	/* On P/Q/R/S, one can read from the device via the MAC reconfiguration
	 * tables. On E/T, MAC reconfig tables are not readable, only writable.
	 * We have to *know* what the MAC looks like.  For the sake of keeping
	 * the code common, we'll use the static configuration tables as a
	 * reasonable approximation for both E/T and P/Q/R/S.
	 */
	mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;

	/* Write to the dynamic reconfiguration tables */
	rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port,
					  &mac[port], true);
@@ -1356,12 +1357,8 @@ sja1105_mac_select_pcs(struct phylink_config *config, phy_interface_t iface)
{
	struct dsa_port *dp = dsa_phylink_to_port(config);
	struct sja1105_private *priv = dp->ds->priv;
	struct dw_xpcs *xpcs = priv->xpcs[dp->index];

	if (xpcs)
		return &xpcs->pcs;

	return NULL;
	return priv->pcs[dp->index];
}

static void sja1105_mac_config(struct phylink_config *config,
@@ -1390,7 +1387,8 @@ static void sja1105_mac_link_up(struct phylink_config *config,
	struct sja1105_private *priv = dp->ds->priv;
	int port = dp->index;

	sja1105_adjust_port_config(priv, port, speed);
	if (!sja1105_set_port_speed(priv, port, speed))
		sja1105_set_port_config(priv, port);

	sja1105_inhibit_tx(priv, BIT(port), false);
}
@@ -2293,8 +2291,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
{
	struct ptp_system_timestamp ptp_sts_before;
	struct ptp_system_timestamp ptp_sts_after;
	int speed_mbps[SJA1105_MAX_NUM_PORTS];
	u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0};
	u64 mac_speed[SJA1105_MAX_NUM_PORTS];
	struct sja1105_mac_config_entry *mac;
	struct dsa_switch *ds = priv->ds;
	s64 t1, t2, t3, t4;
@@ -2307,17 +2305,16 @@ int sja1105_static_config_reload(struct sja1105_private *priv,

	mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;

	/* Back up the dynamic link speed changed by sja1105_adjust_port_config
	/* Back up the dynamic link speed changed by sja1105_set_port_speed()
	 * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the
	 * switch wants to see in the static config in order to allow us to
	 * change it through the dynamic interface later.
	 */
	for (i = 0; i < ds->num_ports; i++) {
		speed_mbps[i] = sja1105_port_speed_to_ethtool(priv,
							      mac[i].speed);
		mac_speed[i] = mac[i].speed;
		mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];

		if (priv->xpcs[i])
		if (priv->pcs[i])
			bmcr[i] = mdiobus_c45_read(priv->mdio_pcs, i,
						   MDIO_MMD_VEND2, MDIO_CTRL1);
	}
@@ -2374,14 +2371,15 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
	}

	for (i = 0; i < ds->num_ports; i++) {
		struct dw_xpcs *xpcs = priv->xpcs[i];
		struct phylink_pcs *pcs = priv->pcs[i];
		unsigned int neg_mode;

		rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]);
		mac[i].speed = mac_speed[i];
		rc = sja1105_set_port_config(priv, i);
		if (rc < 0)
			goto out;

		if (!xpcs)
		if (!pcs)
			continue;

		if (bmcr[i] & BMCR_ANENABLE)
@@ -2389,7 +2387,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
		else
			neg_mode = PHYLINK_PCS_NEG_OUTBAND;

		rc = xpcs_do_config(xpcs, priv->phy_mode[i], NULL, neg_mode);
		rc = pcs->ops->pcs_config(pcs, neg_mode, priv->phy_mode[i],
					  NULL, true);
		if (rc < 0)
			goto out;

@@ -2405,7 +2404,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
			else
				speed = SPEED_10;

			xpcs_link_up(&xpcs->pcs, neg_mode, priv->phy_mode[i],
			pcs->ops->pcs_link_up(pcs, neg_mode, priv->phy_mode[i],
					      speed, DUPLEX_FULL);
		}
	}
+13 −15
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
	}

	for (port = 0; port < ds->num_ports; port++) {
		struct dw_xpcs *xpcs;
		struct phylink_pcs *pcs;

		if (dsa_is_unused_port(ds, port))
			continue;
@@ -409,13 +409,13 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
		    priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
			continue;

		xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]);
		if (IS_ERR(xpcs)) {
			rc = PTR_ERR(xpcs);
		pcs = xpcs_create_pcs_mdiodev(bus, port);
		if (IS_ERR(pcs)) {
			rc = PTR_ERR(pcs);
			goto out_pcs_free;
		}

		priv->xpcs[port] = xpcs;
		priv->pcs[port] = pcs;
	}

	priv->mdio_pcs = bus;
@@ -424,11 +424,10 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)

out_pcs_free:
	for (port = 0; port < ds->num_ports; port++) {
		if (!priv->xpcs[port])
			continue;

		xpcs_destroy(priv->xpcs[port]);
		priv->xpcs[port] = NULL;
		if (priv->pcs[port]) {
			xpcs_destroy_pcs(priv->pcs[port]);
			priv->pcs[port] = NULL;
		}
	}

	mdiobus_unregister(bus);
@@ -446,11 +445,10 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
		return;

	for (port = 0; port < ds->num_ports; port++) {
		if (!priv->xpcs[port])
			continue;

		xpcs_destroy(priv->xpcs[port]);
		priv->xpcs[port] = NULL;
		if (priv->pcs[port]) {
			xpcs_destroy_pcs(priv->pcs[port]);
			priv->pcs[port] = NULL;
		}
	}

	mdiobus_unregister(priv->mdio_pcs);
+3 −4
Original line number Diff line number Diff line
@@ -500,23 +500,22 @@ int stmmac_pcs_setup(struct net_device *ndev)
	struct fwnode_handle *devnode, *pcsnode;
	struct dw_xpcs *xpcs = NULL;
	struct stmmac_priv *priv;
	int addr, mode, ret;
	int addr, ret;

	priv = netdev_priv(ndev);
	mode = priv->plat->phy_interface;
	devnode = priv->plat->port_node;

	if (priv->plat->pcs_init) {
		ret = priv->plat->pcs_init(priv);
	} else if (fwnode_property_present(devnode, "pcs-handle")) {
		pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0);
		xpcs = xpcs_create_fwnode(pcsnode, mode);
		xpcs = xpcs_create_fwnode(pcsnode);
		fwnode_handle_put(pcsnode);
		ret = PTR_ERR_OR_ZERO(xpcs);
	} else if (priv->plat->mdio_bus_data &&
		   priv->plat->mdio_bus_data->pcs_mask) {
		addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1;
		xpcs = xpcs_create_mdiodev(priv->mii, addr, mode);
		xpcs = xpcs_create_mdiodev(priv->mii, addr);
		ret = PTR_ERR_OR_ZERO(xpcs);
	} else {
		return 0;
+9 −9
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum
static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
{
	struct mii_bus *mii_bus;
	struct dw_xpcs *xpcs;
	struct phylink_pcs *pcs;
	struct pci_dev *pdev;
	struct wx *wx;
	int ret = 0;
@@ -147,11 +147,11 @@ static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
	if (ret)
		return ret;

	xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER);
	if (IS_ERR(xpcs))
		return PTR_ERR(xpcs);
	pcs = xpcs_create_pcs_mdiodev(mii_bus, 0);
	if (IS_ERR(pcs))
		return PTR_ERR(pcs);

	txgbe->xpcs = xpcs;
	txgbe->pcs = pcs;

	return 0;
}
@@ -163,7 +163,7 @@ static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *confi
	struct txgbe *txgbe = wx->priv;

	if (interface == PHY_INTERFACE_MODE_10GBASER)
		return &txgbe->xpcs->pcs;
		return txgbe->pcs;

	return NULL;
}
@@ -302,7 +302,7 @@ irqreturn_t txgbe_link_irq_handler(int irq, void *data)
	status = rd32(wx, TXGBE_CFG_PORT_ST);
	up = !!(status & TXGBE_CFG_PORT_ST_LINK_UP);

	phylink_pcs_change(&txgbe->xpcs->pcs, up);
	phylink_pcs_change(txgbe->pcs, up);

	return IRQ_HANDLED;
}
@@ -778,7 +778,7 @@ int txgbe_init_phy(struct txgbe *txgbe)
err_destroy_phylink:
	phylink_destroy(wx->phylink);
err_destroy_xpcs:
	xpcs_destroy(txgbe->xpcs);
	xpcs_destroy_pcs(txgbe->pcs);
err_unregister_swnode:
	software_node_unregister_node_group(txgbe->nodes.group);

@@ -798,6 +798,6 @@ void txgbe_remove_phy(struct txgbe *txgbe)
	clkdev_drop(txgbe->clock);
	clk_unregister(txgbe->clk);
	phylink_destroy(txgbe->wx->phylink);
	xpcs_destroy(txgbe->xpcs);
	xpcs_destroy_pcs(txgbe->pcs);
	software_node_unregister_node_group(txgbe->nodes.group);
}
Loading