Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74371272 authored by Jose Abreu's avatar Jose Abreu Committed by David S. Miller
Browse files

net: stmmac: Convert to phylink and remove phylib logic



Convert everything to phylink.

Signed-off-by: default avatarJose Abreu <joabreu@synopsys.com>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eeef2f6b
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@ config STMMAC_ETH
	tristate "STMicroelectronics 10/100/1000/EQOS Ethernet driver"
	depends on HAS_IOMEM && HAS_DMA
	select MII
	select PHYLIB
	select PHYLINK
	select CRC32
	imply PTP_1588_CLOCK
@@ -42,7 +41,6 @@ if STMMAC_PLATFORM

config DWMAC_DWC_QOS_ETH
	tristate "Support for snps,dwc-qos-ethernet.txt DT binding."
	select PHYLIB
	select CRC32
	select MII
	depends on OF && HAS_DMA
+0 −3
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@

#include <linux/clk.h>
#include <linux/stmmac.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/pci.h>
#include "common.h"
@@ -148,9 +147,7 @@ struct stmmac_priv {
	/* Generic channel for NAPI */
	struct stmmac_channel channel[STMMAC_CH_MAX];

	bool oldlink;
	int speed;
	int oldduplex;
	unsigned int flow_ctrl;
	unsigned int pause;
	struct mii_bus *mii;
+17 −64
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@
#include <linux/ethtool.h>
#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/net_tstamp.h>
#include <asm/io.h>

@@ -274,7 +274,6 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
					     struct ethtool_link_ksettings *cmd)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct phy_device *phy = dev->phydev;

	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
	    priv->hw->pcs & STMMAC_PCS_SGMII) {
@@ -353,18 +352,7 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
		return 0;
	}

	if (phy == NULL) {
		pr_err("%s: %s: PHY is not registered\n",
		       __func__, dev->name);
		return -ENODEV;
	}
	if (!netif_running(dev)) {
		pr_err("%s: interface is disabled: we cannot track "
		"link speed / duplex setting\n", dev->name);
		return -EBUSY;
	}
	phy_ethtool_ksettings_get(phy, cmd);
	return 0;
	return phylink_ethtool_ksettings_get(priv->phylink, cmd);
}

static int
@@ -372,8 +360,6 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
				  const struct ethtool_link_ksettings *cmd)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct phy_device *phy = dev->phydev;
	int rc;

	if (priv->hw->pcs & STMMAC_PCS_RGMII ||
	    priv->hw->pcs & STMMAC_PCS_SGMII) {
@@ -397,9 +383,7 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
		return 0;
	}

	rc = phy_ethtool_ksettings_set(phy, cmd);

	return rc;
	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
}

static u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
@@ -443,6 +427,13 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
	       NUM_DWMAC1000_DMA_REGS * 4);
}

static int stmmac_nway_reset(struct net_device *dev)
{
	struct stmmac_priv *priv = netdev_priv(dev);

	return phylink_ethtool_nway_reset(priv->phylink);
}

static void
stmmac_get_pauseparam(struct net_device *netdev,
		      struct ethtool_pauseparam *pause)
@@ -450,28 +441,13 @@ stmmac_get_pauseparam(struct net_device *netdev,
	struct stmmac_priv *priv = netdev_priv(netdev);
	struct rgmii_adv adv_lp;

	pause->rx_pause = 0;
	pause->tx_pause = 0;

	if (priv->hw->pcs && !stmmac_pcs_get_adv_lp(priv, priv->ioaddr, &adv_lp)) {
		pause->autoneg = 1;
		if (!adv_lp.pause)
			return;
	} else {
		if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
				       netdev->phydev->supported) ||
		    !linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
				      netdev->phydev->supported))
			return;
		phylink_ethtool_get_pauseparam(priv->phylink, pause);
	}

	pause->autoneg = netdev->phydev->autoneg;

	if (priv->flow_ctrl & FLOW_RX)
		pause->rx_pause = 1;
	if (priv->flow_ctrl & FLOW_TX)
		pause->tx_pause = 1;

}

static int
@@ -479,39 +455,16 @@ stmmac_set_pauseparam(struct net_device *netdev,
		      struct ethtool_pauseparam *pause)
{
	struct stmmac_priv *priv = netdev_priv(netdev);
	u32 tx_cnt = priv->plat->tx_queues_to_use;
	struct phy_device *phy = netdev->phydev;
	int new_pause = FLOW_OFF;
	struct rgmii_adv adv_lp;

	if (priv->hw->pcs && !stmmac_pcs_get_adv_lp(priv, priv->ioaddr, &adv_lp)) {
		pause->autoneg = 1;
		if (!adv_lp.pause)
			return -EOPNOTSUPP;
		return 0;
	} else {
		if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
				       phy->supported) ||
		    !linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
				      phy->supported))
			return -EOPNOTSUPP;
		return phylink_ethtool_set_pauseparam(priv->phylink, pause);
	}

	if (pause->rx_pause)
		new_pause |= FLOW_RX;
	if (pause->tx_pause)
		new_pause |= FLOW_TX;

	priv->flow_ctrl = new_pause;
	phy->autoneg = pause->autoneg;

	if (phy->autoneg) {
		if (netif_running(netdev))
			return phy_start_aneg(phy);
	}

	stmmac_flow_ctrl(priv, priv->hw, phy->duplex, priv->flow_ctrl,
			priv->pause, tx_cnt);
	return 0;
}

static void stmmac_get_ethtool_stats(struct net_device *dev,
@@ -549,7 +502,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
			}
		}
		if (priv->eee_enabled) {
			int val = phy_get_eee_err(dev->phydev);
			int val = phylink_get_eee_err(priv->phylink);
			if (val)
				priv->xstats.phy_eee_wakeup_error_n = val;
		}
@@ -694,7 +647,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
	edata->eee_active = priv->eee_active;
	edata->tx_lpi_timer = priv->tx_lpi_timer;

	return phy_ethtool_get_eee(dev->phydev, edata);
	return phylink_ethtool_get_eee(priv->phylink, edata);
}

static int stmmac_ethtool_op_set_eee(struct net_device *dev,
@@ -715,7 +668,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
			return -EOPNOTSUPP;
	}

	ret = phy_ethtool_set_eee(dev->phydev, edata);
	ret = phylink_ethtool_set_eee(priv->phylink, edata);
	if (ret)
		return ret;

@@ -892,7 +845,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
	.get_regs = stmmac_ethtool_gregs,
	.get_regs_len = stmmac_ethtool_get_regs_len,
	.get_link = ethtool_op_get_link,
	.nway_reset = phy_ethtool_nway_reset,
	.nway_reset = stmmac_nway_reset,
	.get_pauseparam = stmmac_get_pauseparam,
	.set_pauseparam = stmmac_set_pauseparam,
	.self_test = stmmac_selftest_run,
+114 −250
Original line number Diff line number Diff line
@@ -328,21 +328,6 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)
	return dirty;
}

/**
 * stmmac_hw_fix_mac_speed - callback for speed selection
 * @priv: driver private structure
 * Description: on some platforms (e.g. ST), some HW system configuration
 * registers have to be set according to the link speed negotiated.
 */
static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
{
	struct net_device *ndev = priv->dev;
	struct phy_device *phydev = ndev->phydev;

	if (likely(priv->plat->fix_mac_speed))
		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
}

/**
 * stmmac_enable_eee_mode - check and enter in LPI mode
 * @priv: driver private structure
@@ -406,14 +391,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
 */
bool stmmac_eee_init(struct stmmac_priv *priv)
{
	struct net_device *ndev = priv->dev;
	int interface = priv->plat->interface;
	bool ret = false;

	if ((interface != PHY_INTERFACE_MODE_MII) &&
	    (interface != PHY_INTERFACE_MODE_GMII) &&
	    !phy_interface_mode_is_rgmii(interface))
		goto out;
	int tx_lpi_timer = priv->tx_lpi_timer;

	/* Using PCS we cannot dial with the phy registers at this stage
	 * so we do not support extra feature like EEE.
@@ -421,52 +399,32 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
	if ((priv->hw->pcs == STMMAC_PCS_RGMII) ||
	    (priv->hw->pcs == STMMAC_PCS_TBI) ||
	    (priv->hw->pcs == STMMAC_PCS_RTBI))
		goto out;
		return false;

	/* MAC core supports the EEE feature. */
	if (priv->dma_cap.eee) {
		int tx_lpi_timer = priv->tx_lpi_timer;
	/* Check if MAC core supports the EEE feature. */
	if (!priv->dma_cap.eee)
		return false;

		/* Check if the PHY supports EEE */
		if (phy_init_eee(ndev->phydev, 1)) {
			/* To manage at run-time if the EEE cannot be supported
			 * anymore (for example because the lp caps have been
			 * changed).
			 * In that case the driver disable own timers.
			 */
	mutex_lock(&priv->lock);
			if (priv->eee_active) {

	/* Check if it needs to be deactivated */
	if (!priv->eee_active && priv->eee_enabled) {
		netdev_dbg(priv->dev, "disable EEE\n");
		del_timer_sync(&priv->eee_ctrl_timer);
				stmmac_set_eee_timer(priv, priv->hw, 0,
						tx_lpi_timer);
			}
			priv->eee_active = 0;
			mutex_unlock(&priv->lock);
			goto out;
		stmmac_set_eee_timer(priv, priv->hw, 0, tx_lpi_timer);
		return false;
	}
		/* Activate the EEE and start timers */
		mutex_lock(&priv->lock);
		if (!priv->eee_active) {
			priv->eee_active = 1;
			timer_setup(&priv->eee_ctrl_timer,
				    stmmac_eee_ctrl_timer, 0);
			mod_timer(&priv->eee_ctrl_timer,
				  STMMAC_LPI_T(eee_timer));

			stmmac_set_eee_timer(priv, priv->hw,
					STMMAC_DEFAULT_LIT_LS, tx_lpi_timer);
	if (priv->eee_active && !priv->eee_enabled) {
		timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0);
		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
		stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
				     tx_lpi_timer);
	}
		/* Set HW EEE according to the speed */
		stmmac_set_eee_pls(priv, priv->hw, ndev->phydev->link);

		ret = true;
	mutex_unlock(&priv->lock);

	netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
	}
out:
	return ret;
	return true;
}

/* stmmac_get_tx_hwtstamp - get HW TX timestamps
@@ -882,18 +840,16 @@ static int stmmac_mac_link_state(struct phylink_config *config,
	return -EOPNOTSUPP;
}

static void stmmac_mac_config(struct net_device *dev)
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
			      const struct phylink_link_state *state)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
	u32 ctrl;

	ctrl = readl(priv->ioaddr + MAC_CTRL_REG);

	if (phydev->speed != priv->speed) {
	ctrl &= ~priv->hw->link.speed_mask;

		switch (phydev->speed) {
	switch (state->speed) {
	case SPEED_1000:
		ctrl |= priv->hw->link.speed1000;
		break;
@@ -904,32 +860,22 @@ static void stmmac_mac_config(struct net_device *dev)
		ctrl |= priv->hw->link.speed10;
		break;
	default:
			netif_warn(priv, link, priv->dev,
				   "broken speed: %d\n", phydev->speed);
			phydev->speed = SPEED_UNKNOWN;
			break;
		return;
	}

		if (phydev->speed != SPEED_UNKNOWN)
			stmmac_hw_fix_mac_speed(priv);
	priv->speed = state->speed;

		priv->speed = phydev->speed;
	}
	if (priv->plat->fix_mac_speed)
		priv->plat->fix_mac_speed(priv->plat->bsp_priv, state->speed);

	/* Now we make sure that we can be in full duplex mode.
	 * If not, we operate in half-duplex mode. */
	if (phydev->duplex != priv->oldduplex) {
		if (!phydev->duplex)
	if (!state->duplex)
		ctrl &= ~priv->hw->link.duplex;
	else
		ctrl |= priv->hw->link.duplex;

		priv->oldduplex = phydev->duplex;
	}

	/* Flow Control operation */
	if (phydev->pause)
		stmmac_mac_flow_ctrl(priv, phydev->duplex);
	if (state->pause)
		stmmac_mac_flow_ctrl(priv, state->duplex);

	writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
}
@@ -939,85 +885,40 @@ static void stmmac_mac_an_restart(struct phylink_config *config)
	/* Not Supported */
}

static void stmmac_mac_link_down(struct net_device *dev, bool autoneg)
static void stmmac_mac_link_down(struct phylink_config *config,
				 unsigned int mode, phy_interface_t interface)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));

	stmmac_mac_set(priv, priv->ioaddr, false);
	priv->eee_active = false;
	stmmac_eee_init(priv);
	stmmac_set_eee_pls(priv, priv->hw, false);
}

static void stmmac_mac_link_up(struct net_device *dev, bool autoneg)
static void stmmac_mac_link_up(struct phylink_config *config,
			       unsigned int mode, phy_interface_t interface,
			       struct phy_device *phy)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));

	stmmac_mac_set(priv, priv->ioaddr, true);
	if (phy) {
		priv->eee_active = phy_init_eee(phy, 1) >= 0;
		priv->eee_enabled = stmmac_eee_init(priv);
		stmmac_set_eee_pls(priv, priv->hw, true);
	}
}

static const struct phylink_mac_ops __maybe_unused stmmac_phylink_mac_ops = {
static const struct phylink_mac_ops stmmac_phylink_mac_ops = {
	.validate = stmmac_validate,
	.mac_link_state = stmmac_mac_link_state,
	.mac_config = NULL, /* TO BE FILLED */
	.mac_config = stmmac_mac_config,
	.mac_an_restart = stmmac_mac_an_restart,
	.mac_link_down = NULL, /* TO BE FILLED */
	.mac_link_up = NULL, /* TO BE FILLED */
	.mac_link_down = stmmac_mac_link_down,
	.mac_link_up = stmmac_mac_link_up,
};

/**
 * stmmac_adjust_link - adjusts the link parameters
 * @dev: net device structure
 * Description: this is the helper called by the physical abstraction layer
 * drivers to communicate the phy link status. According the speed and duplex
 * this driver can invoke registered glue-logic as well.
 * It also invoke the eee initialization because it could happen when switch
 * on different networks (that are eee capable).
 */
static void stmmac_adjust_link(struct net_device *dev)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	bool new_state = false;

	if (!phydev)
		return;

	mutex_lock(&priv->lock);

	if (phydev->link) {
		stmmac_mac_config(dev);

		if (!priv->oldlink) {
			new_state = true;
			priv->oldlink = true;
		}
	} else if (priv->oldlink) {
		new_state = true;
		priv->oldlink = false;
		priv->speed = SPEED_UNKNOWN;
		priv->oldduplex = DUPLEX_UNKNOWN;
	}

	if (phydev->link)
		stmmac_mac_link_up(dev, false);
	else
		stmmac_mac_link_down(dev, false);

	if (new_state && netif_msg_link(priv))
		phy_print_status(phydev);

	mutex_unlock(&priv->lock);

	if (phydev->is_pseudo_fixed_link)
		/* Stop PHY layer to call the hook to adjust the link in case
		 * of a switch is attached to the stmmac driver.
		 */
		phydev->irq = PHY_IGNORE_INTERRUPT;
	else
		/* At this stage, init the EEE if supported.
		 * Never called in case of fixed_link.
		 */
		priv->eee_enabled = stmmac_eee_init(priv);
}

/**
 * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
 * @priv: driver private structure
@@ -1054,79 +955,44 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
static int stmmac_init_phy(struct net_device *dev)
{
	struct stmmac_priv *priv = netdev_priv(dev);
	u32 tx_cnt = priv->plat->tx_queues_to_use;
	struct phy_device *phydev;
	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
	char bus_id[MII_BUS_ID_SIZE];
	int interface = priv->plat->interface;
	int max_speed = priv->plat->max_speed;
	priv->oldlink = false;
	priv->speed = SPEED_UNKNOWN;
	priv->oldduplex = DUPLEX_UNKNOWN;

	if (priv->plat->phy_node) {
		phydev = of_phy_connect(dev, priv->plat->phy_node,
					&stmmac_adjust_link, 0, interface);
	} else {
		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
			 priv->plat->bus_id);
	struct device_node *node;
	int ret;

		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
			 priv->plat->phy_addr);
		netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__,
			   phy_id_fmt);
	node = priv->plat->phy_node;

		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
				     interface);
	}
	if (node) {
		ret = phylink_of_phy_connect(priv->phylink, node, 0);
	} else {
		int addr = priv->plat->phy_addr;
		struct phy_device *phydev;

	if (IS_ERR_OR_NULL(phydev)) {
		netdev_err(priv->dev, "Could not attach to PHY\n");
		if (!phydev)
		phydev = mdiobus_get_phy(priv->mii, addr);
		if (!phydev) {
			netdev_err(priv->dev, "no phy at addr %d\n", addr);
			return -ENODEV;

		return PTR_ERR(phydev);
		}

	/* Stop Advertising 1000BASE Capability if interface is not GMII */
	if ((interface == PHY_INTERFACE_MODE_MII) ||
	    (interface == PHY_INTERFACE_MODE_RMII) ||
		(max_speed < 1000 && max_speed > 0))
		phy_set_max_speed(phydev, SPEED_100);

	/*
	 * Half-duplex mode not supported with multiqueue
	 * half-duplex can only works with single queue
	 */
	if (tx_cnt > 1) {
		phy_remove_link_mode(phydev,
				     ETHTOOL_LINK_MODE_10baseT_Half_BIT);
		phy_remove_link_mode(phydev,
				     ETHTOOL_LINK_MODE_100baseT_Half_BIT);
		phy_remove_link_mode(phydev,
				     ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
		ret = phylink_connect_phy(priv->phylink, phydev);
	}

	/*
	 * Broken HW is sometimes missing the pull-up resistor on the
	 * MDIO line, which results in reads to non-existent devices returning
	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
	 * device as well.
	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
	 */
	if (!priv->plat->phy_node && phydev->phy_id == 0) {
		phy_disconnect(phydev);
		return -ENODEV;
	return ret;
}

	/* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid
	 * subsequent PHY polling, make sure we force a link transition if
	 * we have a UP/DOWN/UP transition
	 */
	if (phydev->is_pseudo_fixed_link)
		phydev->irq = PHY_POLL;
static int stmmac_phy_setup(struct stmmac_priv *priv)
{
	struct device_node *node = priv->plat->phy_node;
	int mode = priv->plat->interface;
	struct phylink *phylink;

	phy_attached_info(phydev);
	priv->phylink_config.dev = &priv->dev->dev;
	priv->phylink_config.type = PHYLINK_NETDEV;

	phylink = phylink_create(&priv->phylink_config, of_fwnode_handle(node),
				 mode, &stmmac_phylink_mac_ops);
	if (IS_ERR(phylink))
		return PTR_ERR(phylink);

	priv->phylink = phylink;
	return 0;
}

@@ -2739,8 +2605,7 @@ static int stmmac_open(struct net_device *dev)

	stmmac_init_tx_coalesce(priv);

	if (dev->phydev)
		phy_start(dev->phydev);
	phylink_start(priv->phylink);

	/* Request the IRQ lines */
	ret = request_irq(dev->irq, stmmac_interrupt,
@@ -2787,8 +2652,7 @@ static int stmmac_open(struct net_device *dev)
wolirq_error:
	free_irq(dev->irq, dev);
irq_error:
	if (dev->phydev)
		phy_stop(dev->phydev);
	phylink_stop(priv->phylink);

	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
		del_timer_sync(&priv->tx_queue[chan].txtimer);
@@ -2797,9 +2661,7 @@ static int stmmac_open(struct net_device *dev)
init_error:
	free_dma_desc_resources(priv);
dma_desc_error:
	if (dev->phydev)
		phy_disconnect(dev->phydev);

	phylink_disconnect_phy(priv->phylink);
	return ret;
}

@@ -2818,10 +2680,8 @@ static int stmmac_release(struct net_device *dev)
		del_timer_sync(&priv->eee_ctrl_timer);

	/* Stop and disconnect the PHY */
	if (dev->phydev) {
		phy_stop(dev->phydev);
		phy_disconnect(dev->phydev);
	}
	phylink_stop(priv->phylink);
	phylink_disconnect_phy(priv->phylink);

	stmmac_stop_all_queues(priv);

@@ -3878,6 +3738,7 @@ static void stmmac_poll_controller(struct net_device *dev)
 */
static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
	struct stmmac_priv *priv = netdev_priv (dev);
	int ret = -EOPNOTSUPP;

	if (!netif_running(dev))
@@ -3887,9 +3748,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
	case SIOCGMIIPHY:
	case SIOCGMIIREG:
	case SIOCSMIIREG:
		if (!dev->phydev)
			return -EINVAL;
		ret = phy_mii_ioctl(dev->phydev, rq, cmd);
		ret = phylink_mii_ioctl(priv->phylink, rq, cmd);
		break;
	case SIOCSHWTSTAMP:
		ret = stmmac_hwtstamp_set(dev, rq);
@@ -4480,6 +4339,12 @@ int stmmac_dvr_probe(struct device *device,
		}
	}

	ret = stmmac_phy_setup(priv);
	if (ret) {
		netdev_err(ndev, "failed to setup phy (%d)\n", ret);
		goto error_phy_setup;
	}

	ret = register_netdev(ndev);
	if (ret) {
		dev_err(priv->device, "%s: ERROR %i registering the device\n",
@@ -4497,6 +4362,8 @@ int stmmac_dvr_probe(struct device *device,
	return ret;

error_netdev_register:
	phylink_destroy(priv->phylink);
error_phy_setup:
	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
	    priv->hw->pcs != STMMAC_PCS_TBI &&
	    priv->hw->pcs != STMMAC_PCS_RTBI)
@@ -4538,6 +4405,7 @@ int stmmac_dvr_remove(struct device *dev)
	stmmac_mac_set(priv, priv->ioaddr, false);
	netif_carrier_off(ndev);
	unregister_netdev(ndev);
	phylink_destroy(priv->phylink);
	if (priv->plat->stmmac_rst)
		reset_control_assert(priv->plat->stmmac_rst);
	clk_disable_unprepare(priv->plat->pclk);
@@ -4568,8 +4436,7 @@ int stmmac_suspend(struct device *dev)
	if (!ndev || !netif_running(ndev))
		return 0;

	if (ndev->phydev)
		phy_stop(ndev->phydev);
	phylink_stop(priv->phylink);

	mutex_lock(&priv->lock);

@@ -4594,9 +4461,7 @@ int stmmac_suspend(struct device *dev)
	}
	mutex_unlock(&priv->lock);

	priv->oldlink = false;
	priv->speed = SPEED_UNKNOWN;
	priv->oldduplex = DUPLEX_UNKNOWN;
	return 0;
}
EXPORT_SYMBOL_GPL(stmmac_suspend);
@@ -4680,8 +4545,7 @@ int stmmac_resume(struct device *dev)

	mutex_unlock(&priv->lock);

	if (ndev->phydev)
		phy_start(ndev->phydev);
	phylink_start(priv->phylink);

	return 0;
}
+1 −20
Original line number Diff line number Diff line
@@ -333,21 +333,6 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
		{},
	};

	/* If phy-handle property is passed from DT, use it as the PHY */
	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
	if (plat->phy_node)
		dev_dbg(dev, "Found phy-handle subnode\n");

	/* If phy-handle is not specified, check if we have a fixed-phy */
	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
		if ((of_phy_register_fixed_link(np) < 0))
			return -ENODEV;

		dev_dbg(dev, "Found fixed-link subnode\n");
		plat->phy_node = of_node_get(np);
		mdio = false;
	}

	if (of_match_node(need_mdio_ids, np)) {
		plat->mdio_node = of_get_child_by_name(np, "mdio");
	} else {
@@ -396,6 +381,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)

	*mac = of_get_mac_address(np);
	plat->interface = of_get_phy_mode(np);
	plat->phy_node = np;

	/* Get max speed of operation from device tree */
	if (of_property_read_u32(np, "max-speed", &plat->max_speed))
@@ -591,11 +577,6 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
void stmmac_remove_config_dt(struct platform_device *pdev,
			     struct plat_stmmacenet_data *plat)
{
	struct device_node *np = pdev->dev.of_node;

	if (of_phy_is_fixed_link(np))
		of_phy_deregister_fixed_link(np);
	of_node_put(plat->phy_node);
	of_node_put(plat->mdio_node);
}
#else