Commit 425b0fad authored by David S. Miller's avatar David S. Miller

Merge branch 'net-stmmac-Convert-to-phylink'

Jose Abreu says:

====================
net: stmmac: Convert to phylink

This converts stmmac to use phylink. Besides the code redution this will
allow to gain more flexibility.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5948d117 74371272
......@@ -3,7 +3,7 @@ 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
select RESET_CONTROLLER
......@@ -41,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
......
......@@ -24,7 +24,7 @@
#include <linux/clk.h>
#include <linux/stmmac.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
......@@ -147,14 +147,15 @@ 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;
int mii_irq[PHY_MAX_ADDR];
struct phylink_config phylink_config;
struct phylink *phylink;
struct stmmac_extra_stats xstats ____cacheline_aligned_in_smp;
struct stmmac_safety_stats sstats;
struct plat_stmmacenet_data *plat;
......
......@@ -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,
......
......@@ -45,6 +45,7 @@
#include <linux/seq_file.h>
#endif /* CONFIG_DEBUG_FS */
#include <linux/net_tstamp.h>
#include <linux/phylink.h>
#include <net/pkt_cls.h>
#include "stmmac_ptp.h"
#include "stmmac.h"
......@@ -327,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
......@@ -405,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.
......@@ -420,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;
/* MAC core supports the EEE feature. */
if (priv->dma_cap.eee) {
int tx_lpi_timer = priv->tx_lpi_timer;
/* 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) {
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;
}
/* 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);
}
/* Set HW EEE according to the speed */
stmmac_set_eee_pls(priv, priv->hw, ndev->phydev->link);
return false;
ret = true;
mutex_unlock(&priv->lock);
/* Check if MAC core supports the EEE feature. */
if (!priv->dma_cap.eee)
return false;
mutex_lock(&priv->lock);
netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
/* 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);
return false;
}
out:
return ret;
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);
}
mutex_unlock(&priv->lock);
netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
return true;
}
/* stmmac_get_tx_hwtstamp - get HW TX timestamps
......@@ -848,97 +807,118 @@ static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
priv->pause, tx_cnt);
}
/**
* 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)
static void stmmac_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phydev = dev->phydev;
bool new_state = false;
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
int tx_cnt = priv->plat->tx_queues_to_use;
int max_speed = priv->plat->max_speed;
if (!phydev)
return;
/* Cut down 1G if asked to */
if ((max_speed > 0) && (max_speed < 1000)) {
phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 1000baseX_Full);
}
mutex_lock(&priv->lock);
/* 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);
}
if (phydev->link) {
u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
bitmap_andnot(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
bitmap_andnot(state->advertising, state->advertising, mask,
__ETHTOOL_LINK_MODE_MASK_NBITS);
}
/* 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) {
new_state = true;
if (!phydev->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 (phydev->speed != priv->speed) {
new_state = true;
ctrl &= ~priv->hw->link.speed_mask;
switch (phydev->speed) {
case SPEED_1000:
ctrl |= priv->hw->link.speed1000;
break;
case SPEED_100:
ctrl |= priv->hw->link.speed100;
break;
case SPEED_10:
ctrl |= priv->hw->link.speed10;
break;
default:
netif_warn(priv, link, priv->dev,
"broken speed: %d\n", phydev->speed);
phydev->speed = SPEED_UNKNOWN;
break;
}
if (phydev->speed != SPEED_UNKNOWN)
stmmac_hw_fix_mac_speed(priv);
priv->speed = phydev->speed;
}
static int stmmac_mac_link_state(struct phylink_config *config,
struct phylink_link_state *state)
{
return -EOPNOTSUPP;
}
writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
u32 ctrl;
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;
ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
ctrl &= ~priv->hw->link.speed_mask;
switch (state->speed) {
case SPEED_1000:
ctrl |= priv->hw->link.speed1000;
break;
case SPEED_100:
ctrl |= priv->hw->link.speed100;
break;
case SPEED_10:
ctrl |= priv->hw->link.speed10;
break;
default:
return;
}
if (new_state && netif_msg_link(priv))
phy_print_status(phydev);
priv->speed = state->speed;
mutex_unlock(&priv->lock);
if (priv->plat->fix_mac_speed)
priv->plat->fix_mac_speed(priv->plat->bsp_priv, state->speed);
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;
if (!state->duplex)
ctrl &= ~priv->hw->link.duplex;
else
/* At this stage, init the EEE if supported.
* Never called in case of fixed_link.
*/
ctrl |= priv->hw->link.duplex;
/* Flow Control operation */
if (state->pause)
stmmac_mac_flow_ctrl(priv, state->duplex);
writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
}
static void stmmac_mac_an_restart(struct phylink_config *config)
{
/* Not Supported */
}
static void stmmac_mac_link_down(struct phylink_config *config,
unsigned int mode, phy_interface_t interface)
{
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 phylink_config *config,
unsigned int mode, phy_interface_t interface,
struct phy_device *phy)
{
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 stmmac_phylink_mac_ops = {
.validate = stmmac_validate,
.mac_link_state = stmmac_mac_link_state,
.mac_config = stmmac_mac_config,
.mac_an_restart = stmmac_mac_an_restart,
.mac_link_down = stmmac_mac_link_down,
.mac_link_up = stmmac_mac_link_up,
};
/**
* stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
* @priv: driver private structure
......@@ -975,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);
ret = phylink_connect_phy(priv->phylink, 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);
return ret;
}
/*
* 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);
}
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;
/*
* 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;
}
priv->phylink_config.dev = &priv->dev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
/* 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;
phylink = phylink_create(&priv->phylink_config, of_fwnode_handle(node),
mode, &stmmac_phylink_mac_ops);
if (IS_ERR(phylink))
return PTR_ERR(phylink);
phy_attached_info(phydev);
priv->phylink = phylink;
return 0;
}
......@@ -2660,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,
......@@ -2708,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);
......@@ -2718,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;
}
......@@ -2739,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);
......@@ -3799,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))
......@@ -3808,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);
......@@ -4401,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",
......@@ -4418,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)
......@@ -4459,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);
......@@ -4489,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);
......@@ -4515,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);
......@@ -4601,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;
}
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment