Commit 6faaffb3 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'Decoupling-PHYLINK-from-struct-net_device'

Ioana Ciornei says:

====================
Decoupling PHYLINK from struct net_device

Following two separate discussion threads in:
  https://www.spinics.net/lists/netdev/msg569087.html
and:
  https://www.spinics.net/lists/netdev/msg570450.html

Previous RFC patch set: https://www.spinics.net/lists/netdev/msg571995.html

PHYLINK was reworked in order to accept multiple operation types,
PHYLINK_NETDEV and PHYLINK_DEV, passed through a phylink_config
structure alongside the corresponding struct device.

One of the main concerns expressed in the RFC was that using notifiers
to signal the corresponding phylink_mac_ops would break PHYLINK's API
unity and that it would become harder to grep for its users.
Using the current approach, we maintain a common API for all users.
Also, printing useful information in PHYLINK, when decoupled from a
net_device, is achieved using dev_err&co on the struct device received
(in DSA's case is the device corresponding to the dsa_switch).

PHYLIB (which PHYLINK uses) was reworked to the extent that it does not
crash when connecting to a PHY and the net_device pointer is NULL.

Lastly, DSA has been reworked in its way that it handles PHYs for ports
that lack a net_device (CPU and DSA ports).  For these, it was
previously using PHYLIB and is now using the PHYLINK_DEV operation type.
Previously, a driver that wanted to support PHY operations on CPU/DSA
ports has to implement .adjust_link(). This patch set not only gives
drivers the options to use PHYLINK uniformly but also urges them to
convert to it. For compatibility, the old code is kept but it will be
removed once all drivers switch over.

The patchset was tested on the NXP LS1021A-TSN board having the
following Ethernet layout:
  https://lkml.org/lkml/2019/5/5/279


The CPU port was moved from the internal RGMII fixed-link (enet2 ->
switch port 4) to an external loopback Cat5 cable between the enet1 port
and the front-facing swp2 SJA1105 port. In this mode, both the master
and the CPU port have an attached PHY which detects link change events:

[   49.105426] fsl-gianfar soc:ethernet@2d50000 eth1: Link is Down
[   50.305486] sja1105 spi0.1: Link is Down
[   53.265596] fsl-gianfar soc:ethernet@2d50000 eth1: Link is Up - 1Gbps/Full - flow control off
[   54.466304] sja1105 spi0.1: Link is Up - 1Gbps/Full - flow control off

Changes in v2:
  - fixed sparse warnings
  - updated 'Documentation/ABI/testing/sysfs-class-net-phydev'
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 24ec483c af7cd036
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -34,3 +34,11 @@ Description:
		xgmii, moca, qsgmii, trgmii, 1000base-x, 2500base-x, rxaui,
		xaui, 10gbase-kr, unknown

What:		/sys/class/mdio_bus/<bus>/<device>/phy_standalone
Date:		May 2019
KernelVersion:	5.3
Contact:	netdev@vger.kernel.org
Description:
		Boolean value indicating whether the PHY device is used in
		standalone mode, without a net_device associated, by PHYLINK.
		Attribute created only when this is the case.
+4 −1
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ this documentation.
4. Add::

	struct phylink *phylink;
	struct phylink_config phylink_config;

   to the driver's private data structure.  We shall refer to the
   driver's private data pointer as ``priv`` below, and the driver's
@@ -223,8 +224,10 @@ this documentation.
   .. code-block:: c

	struct phylink *phylink;
	priv->phylink_config.dev = &dev.dev;
	priv->phylink_config.type = PHYLINK_NETDEV;

	phylink = phylink_create(dev, node, phy_mode, &phylink_ops);
	phylink = phylink_create(&priv->phylink_config, node, phy_mode, &phylink_ops);
	if (IS_ERR(phylink)) {
		err = PTR_ERR(phylink);
		fail probe;
+6 −5
Original line number Diff line number Diff line
@@ -734,15 +734,16 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
	return sja1105_clocking_setup_port(priv, port);
}

static void sja1105_adjust_link(struct dsa_switch *ds, int port,
				struct phy_device *phydev)
static void sja1105_mac_config(struct dsa_switch *ds, int port,
			       unsigned int link_an_mode,
			       const struct phylink_link_state *state)
{
	struct sja1105_private *priv = ds->priv;

	if (!phydev->link)
	if (!state->link)
		sja1105_adjust_port_config(priv, port, 0, false);
	else
		sja1105_adjust_port_config(priv, port, phydev->speed, true);
		sja1105_adjust_port_config(priv, port, state->speed, true);
}

static void sja1105_phylink_validate(struct dsa_switch *ds, int port,
@@ -1515,9 +1516,9 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds,
static const struct dsa_switch_ops sja1105_switch_ops = {
	.get_tag_protocol	= sja1105_get_tag_protocol,
	.setup			= sja1105_setup,
	.adjust_link		= sja1105_adjust_link,
	.set_ageing_time	= sja1105_set_ageing_time,
	.phylink_validate	= sja1105_phylink_validate,
	.phylink_mac_config	= sja1105_mac_config,
	.get_strings		= sja1105_get_strings,
	.get_ethtool_stats	= sja1105_get_ethtool_stats,
	.get_sset_count		= sja1105_get_sset_count,
+24 −12
Original line number Diff line number Diff line
@@ -437,6 +437,7 @@ struct mvneta_port {
	struct device_node *dn;
	unsigned int tx_csum_limit;
	struct phylink *phylink;
	struct phylink_config phylink_config;
	struct phy *comphy;

	struct mvneta_bm *bm_priv;
@@ -3356,9 +3357,11 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
	return 0;
}

static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
static void mvneta_validate(struct phylink_config *config,
			    unsigned long *supported,
			    struct phylink_link_state *state)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };

@@ -3408,9 +3411,10 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
	phylink_helper_basex_speed(state);
}

static int mvneta_mac_link_state(struct net_device *ndev,
static int mvneta_mac_link_state(struct phylink_config *config,
				 struct phylink_link_state *state)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	u32 gmac_stat;

@@ -3438,8 +3442,9 @@ static int mvneta_mac_link_state(struct net_device *ndev,
	return 1;
}

static void mvneta_mac_an_restart(struct net_device *ndev)
static void mvneta_mac_an_restart(struct phylink_config *config)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);

@@ -3449,9 +3454,10 @@ static void mvneta_mac_an_restart(struct net_device *ndev)
		    gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN);
}

static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
			      const struct phylink_link_state *state)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
	u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
@@ -3581,9 +3587,10 @@ static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
	mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
}

static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode,
				 phy_interface_t interface)
static void mvneta_mac_link_down(struct phylink_config *config,
				 unsigned int mode, phy_interface_t interface)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	u32 val;

@@ -3600,10 +3607,11 @@ static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode,
	mvneta_set_eee(pp, false);
}

static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode,
			       phy_interface_t interface,
			       struct phy_device *phy)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mvneta_port *pp = netdev_priv(ndev);
	u32 val;

@@ -4500,8 +4508,14 @@ static int mvneta_probe(struct platform_device *pdev)
		comphy = NULL;
	}

	phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode,
				 &mvneta_phylink_ops);
	pp = netdev_priv(dev);
	spin_lock_init(&pp->lock);

	pp->phylink_config.dev = &dev->dev;
	pp->phylink_config.type = PHYLINK_NETDEV;

	phylink = phylink_create(&pp->phylink_config, pdev->dev.fwnode,
				 phy_mode, &mvneta_phylink_ops);
	if (IS_ERR(phylink)) {
		err = PTR_ERR(phylink);
		goto err_free_irq;
@@ -4513,8 +4527,6 @@ static int mvneta_probe(struct platform_device *pdev)

	dev->ethtool_ops = &mvneta_eth_tool_ops;

	pp = netdev_priv(dev);
	spin_lock_init(&pp->lock);
	pp->phylink = phylink;
	pp->comphy = comphy;
	pp->phy_interface = phy_mode;
+1 −0
Original line number Diff line number Diff line
@@ -915,6 +915,7 @@ struct mvpp2_port {

	phy_interface_t phy_interface;
	struct phylink *phylink;
	struct phylink_config phylink_config;
	struct phy *comphy;

	struct mvpp2_bm_pool *pool_long;
Loading