|
@@ -1927,8 +1927,15 @@ static void sh_eth_adjust_link(struct net_device *ndev)
|
|
{
|
|
{
|
|
struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
struct phy_device *phydev = ndev->phydev;
|
|
struct phy_device *phydev = ndev->phydev;
|
|
|
|
+ unsigned long flags;
|
|
int new_state = 0;
|
|
int new_state = 0;
|
|
|
|
|
|
|
|
+ spin_lock_irqsave(&mdp->lock, flags);
|
|
|
|
+
|
|
|
|
+ /* Disable TX and RX right over here, if E-MAC change is ignored */
|
|
|
|
+ if (mdp->cd->no_psr || mdp->no_ether_link)
|
|
|
|
+ sh_eth_rcv_snd_disable(ndev);
|
|
|
|
+
|
|
if (phydev->link) {
|
|
if (phydev->link) {
|
|
if (phydev->duplex != mdp->duplex) {
|
|
if (phydev->duplex != mdp->duplex) {
|
|
new_state = 1;
|
|
new_state = 1;
|
|
@@ -1947,18 +1954,21 @@ static void sh_eth_adjust_link(struct net_device *ndev)
|
|
sh_eth_modify(ndev, ECMR, ECMR_TXF, 0);
|
|
sh_eth_modify(ndev, ECMR, ECMR_TXF, 0);
|
|
new_state = 1;
|
|
new_state = 1;
|
|
mdp->link = phydev->link;
|
|
mdp->link = phydev->link;
|
|
- if (mdp->cd->no_psr || mdp->no_ether_link)
|
|
|
|
- sh_eth_rcv_snd_enable(ndev);
|
|
|
|
}
|
|
}
|
|
} else if (mdp->link) {
|
|
} else if (mdp->link) {
|
|
new_state = 1;
|
|
new_state = 1;
|
|
mdp->link = 0;
|
|
mdp->link = 0;
|
|
mdp->speed = 0;
|
|
mdp->speed = 0;
|
|
mdp->duplex = -1;
|
|
mdp->duplex = -1;
|
|
- if (mdp->cd->no_psr || mdp->no_ether_link)
|
|
|
|
- sh_eth_rcv_snd_disable(ndev);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* Enable TX and RX right over here, if E-MAC change is ignored */
|
|
|
|
+ if ((mdp->cd->no_psr || mdp->no_ether_link) && phydev->link)
|
|
|
|
+ sh_eth_rcv_snd_enable(ndev);
|
|
|
|
+
|
|
|
|
+ mmiowb();
|
|
|
|
+ spin_unlock_irqrestore(&mdp->lock, flags);
|
|
|
|
+
|
|
if (new_state && netif_msg_link(mdp))
|
|
if (new_state && netif_msg_link(mdp))
|
|
phy_print_status(phydev);
|
|
phy_print_status(phydev);
|
|
}
|
|
}
|
|
@@ -2030,60 +2040,6 @@ static int sh_eth_phy_start(struct net_device *ndev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int sh_eth_get_link_ksettings(struct net_device *ndev,
|
|
|
|
- struct ethtool_link_ksettings *cmd)
|
|
|
|
-{
|
|
|
|
- struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
|
|
- unsigned long flags;
|
|
|
|
-
|
|
|
|
- if (!ndev->phydev)
|
|
|
|
- return -ENODEV;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&mdp->lock, flags);
|
|
|
|
- phy_ethtool_ksettings_get(ndev->phydev, cmd);
|
|
|
|
- spin_unlock_irqrestore(&mdp->lock, flags);
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int sh_eth_set_link_ksettings(struct net_device *ndev,
|
|
|
|
- const struct ethtool_link_ksettings *cmd)
|
|
|
|
-{
|
|
|
|
- struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
|
|
- unsigned long flags;
|
|
|
|
- int ret;
|
|
|
|
-
|
|
|
|
- if (!ndev->phydev)
|
|
|
|
- return -ENODEV;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&mdp->lock, flags);
|
|
|
|
-
|
|
|
|
- /* disable tx and rx */
|
|
|
|
- sh_eth_rcv_snd_disable(ndev);
|
|
|
|
-
|
|
|
|
- ret = phy_ethtool_ksettings_set(ndev->phydev, cmd);
|
|
|
|
- if (ret)
|
|
|
|
- goto error_exit;
|
|
|
|
-
|
|
|
|
- if (cmd->base.duplex == DUPLEX_FULL)
|
|
|
|
- mdp->duplex = 1;
|
|
|
|
- else
|
|
|
|
- mdp->duplex = 0;
|
|
|
|
-
|
|
|
|
- if (mdp->cd->set_duplex)
|
|
|
|
- mdp->cd->set_duplex(ndev);
|
|
|
|
-
|
|
|
|
-error_exit:
|
|
|
|
- mdelay(1);
|
|
|
|
-
|
|
|
|
- /* enable tx and rx */
|
|
|
|
- sh_eth_rcv_snd_enable(ndev);
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&mdp->lock, flags);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* If it is ever necessary to increase SH_ETH_REG_DUMP_MAX_REGS, the
|
|
/* If it is ever necessary to increase SH_ETH_REG_DUMP_MAX_REGS, the
|
|
* version must be bumped as well. Just adding registers up to that
|
|
* version must be bumped as well. Just adding registers up to that
|
|
* limit is fine, as long as the existing register indices don't
|
|
* limit is fine, as long as the existing register indices don't
|
|
@@ -2263,22 +2219,6 @@ static void sh_eth_get_regs(struct net_device *ndev, struct ethtool_regs *regs,
|
|
pm_runtime_put_sync(&mdp->pdev->dev);
|
|
pm_runtime_put_sync(&mdp->pdev->dev);
|
|
}
|
|
}
|
|
|
|
|
|
-static int sh_eth_nway_reset(struct net_device *ndev)
|
|
|
|
-{
|
|
|
|
- struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
|
|
- unsigned long flags;
|
|
|
|
- int ret;
|
|
|
|
-
|
|
|
|
- if (!ndev->phydev)
|
|
|
|
- return -ENODEV;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&mdp->lock, flags);
|
|
|
|
- ret = phy_start_aneg(ndev->phydev);
|
|
|
|
- spin_unlock_irqrestore(&mdp->lock, flags);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static u32 sh_eth_get_msglevel(struct net_device *ndev)
|
|
static u32 sh_eth_get_msglevel(struct net_device *ndev)
|
|
{
|
|
{
|
|
struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
struct sh_eth_private *mdp = netdev_priv(ndev);
|
|
@@ -2429,7 +2369,7 @@ static int sh_eth_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
|
|
static const struct ethtool_ops sh_eth_ethtool_ops = {
|
|
static const struct ethtool_ops sh_eth_ethtool_ops = {
|
|
.get_regs_len = sh_eth_get_regs_len,
|
|
.get_regs_len = sh_eth_get_regs_len,
|
|
.get_regs = sh_eth_get_regs,
|
|
.get_regs = sh_eth_get_regs,
|
|
- .nway_reset = sh_eth_nway_reset,
|
|
|
|
|
|
+ .nway_reset = phy_ethtool_nway_reset,
|
|
.get_msglevel = sh_eth_get_msglevel,
|
|
.get_msglevel = sh_eth_get_msglevel,
|
|
.set_msglevel = sh_eth_set_msglevel,
|
|
.set_msglevel = sh_eth_set_msglevel,
|
|
.get_link = ethtool_op_get_link,
|
|
.get_link = ethtool_op_get_link,
|
|
@@ -2438,8 +2378,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
|
|
.get_sset_count = sh_eth_get_sset_count,
|
|
.get_sset_count = sh_eth_get_sset_count,
|
|
.get_ringparam = sh_eth_get_ringparam,
|
|
.get_ringparam = sh_eth_get_ringparam,
|
|
.set_ringparam = sh_eth_set_ringparam,
|
|
.set_ringparam = sh_eth_set_ringparam,
|
|
- .get_link_ksettings = sh_eth_get_link_ksettings,
|
|
|
|
- .set_link_ksettings = sh_eth_set_link_ksettings,
|
|
|
|
|
|
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
|
|
|
|
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
|
|
.get_wol = sh_eth_get_wol,
|
|
.get_wol = sh_eth_get_wol,
|
|
.set_wol = sh_eth_set_wol,
|
|
.set_wol = sh_eth_set_wol,
|
|
};
|
|
};
|