r8169: fix driver shutdown WoL regression.
Due to commit 92fc43b415
("r8169: modify the
flow of the hw reset."), rtl8169_hw_reset stomps during driver shutdown on
RxConfig bits which are needed for WOL on some versions of the hardware.
As these bits were formerly set from the r81{0x, 68}_pll_power_down methods,
factor them out for use in the driver shutdown (rtl_shutdown) handler.
I favored __rtl8169_get_wol() -hardware state indication- over
RTL_FEATURE_WOL as the latter has become a good candidate for removal.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Hayes <hayeswang@realtek.com>
Tested-by: Marc Ballarin <ballarin.marc@gmx.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
34b1901abd
commit
649b3b8c4e
1 changed files with 56 additions and 32 deletions
|
@ -3316,6 +3316,37 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
|
||||||
|
{
|
||||||
|
void __iomem *ioaddr = tp->mmio_addr;
|
||||||
|
|
||||||
|
switch (tp->mac_version) {
|
||||||
|
case RTL_GIGA_MAC_VER_29:
|
||||||
|
case RTL_GIGA_MAC_VER_30:
|
||||||
|
case RTL_GIGA_MAC_VER_32:
|
||||||
|
case RTL_GIGA_MAC_VER_33:
|
||||||
|
case RTL_GIGA_MAC_VER_34:
|
||||||
|
RTL_W32(RxConfig, RTL_R32(RxConfig) |
|
||||||
|
AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
|
||||||
|
{
|
||||||
|
if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rtl_writephy(tp, 0x1f, 0x0000);
|
||||||
|
rtl_writephy(tp, MII_BMCR, 0x0000);
|
||||||
|
|
||||||
|
rtl_wol_suspend_quirk(tp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void r810x_phy_power_down(struct rtl8169_private *tp)
|
static void r810x_phy_power_down(struct rtl8169_private *tp)
|
||||||
{
|
{
|
||||||
rtl_writephy(tp, 0x1f, 0x0000);
|
rtl_writephy(tp, 0x1f, 0x0000);
|
||||||
|
@ -3330,18 +3361,8 @@ static void r810x_phy_power_up(struct rtl8169_private *tp)
|
||||||
|
|
||||||
static void r810x_pll_power_down(struct rtl8169_private *tp)
|
static void r810x_pll_power_down(struct rtl8169_private *tp)
|
||||||
{
|
{
|
||||||
void __iomem *ioaddr = tp->mmio_addr;
|
if (rtl_wol_pll_power_down(tp))
|
||||||
|
|
||||||
if (__rtl8169_get_wol(tp) & WAKE_ANY) {
|
|
||||||
rtl_writephy(tp, 0x1f, 0x0000);
|
|
||||||
rtl_writephy(tp, MII_BMCR, 0x0000);
|
|
||||||
|
|
||||||
if (tp->mac_version == RTL_GIGA_MAC_VER_29 ||
|
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_30)
|
|
||||||
RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast |
|
|
||||||
AcceptMulticast | AcceptMyPhys);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
r810x_phy_power_down(tp);
|
r810x_phy_power_down(tp);
|
||||||
}
|
}
|
||||||
|
@ -3430,17 +3451,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_33)
|
tp->mac_version == RTL_GIGA_MAC_VER_33)
|
||||||
rtl_ephy_write(ioaddr, 0x19, 0xff64);
|
rtl_ephy_write(ioaddr, 0x19, 0xff64);
|
||||||
|
|
||||||
if (__rtl8169_get_wol(tp) & WAKE_ANY) {
|
if (rtl_wol_pll_power_down(tp))
|
||||||
rtl_writephy(tp, 0x1f, 0x0000);
|
|
||||||
rtl_writephy(tp, MII_BMCR, 0x0000);
|
|
||||||
|
|
||||||
if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
|
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_33 ||
|
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_34)
|
|
||||||
RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast |
|
|
||||||
AcceptMulticast | AcceptMyPhys);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
r8168_phy_power_down(tp);
|
r8168_phy_power_down(tp);
|
||||||
|
|
||||||
|
@ -5788,11 +5800,30 @@ static const struct dev_pm_ops rtl8169_pm_ops = {
|
||||||
|
|
||||||
#endif /* !CONFIG_PM */
|
#endif /* !CONFIG_PM */
|
||||||
|
|
||||||
|
static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
|
||||||
|
{
|
||||||
|
void __iomem *ioaddr = tp->mmio_addr;
|
||||||
|
|
||||||
|
/* WoL fails with 8168b when the receiver is disabled. */
|
||||||
|
switch (tp->mac_version) {
|
||||||
|
case RTL_GIGA_MAC_VER_11:
|
||||||
|
case RTL_GIGA_MAC_VER_12:
|
||||||
|
case RTL_GIGA_MAC_VER_17:
|
||||||
|
pci_clear_master(tp->pci_dev);
|
||||||
|
|
||||||
|
RTL_W8(ChipCmd, CmdRxEnb);
|
||||||
|
/* PCI commit */
|
||||||
|
RTL_R8(ChipCmd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void rtl_shutdown(struct pci_dev *pdev)
|
static void rtl_shutdown(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct net_device *dev = pci_get_drvdata(pdev);
|
struct net_device *dev = pci_get_drvdata(pdev);
|
||||||
struct rtl8169_private *tp = netdev_priv(dev);
|
struct rtl8169_private *tp = netdev_priv(dev);
|
||||||
void __iomem *ioaddr = tp->mmio_addr;
|
|
||||||
|
|
||||||
rtl8169_net_suspend(dev);
|
rtl8169_net_suspend(dev);
|
||||||
|
|
||||||
|
@ -5806,16 +5837,9 @@ static void rtl_shutdown(struct pci_dev *pdev)
|
||||||
spin_unlock_irq(&tp->lock);
|
spin_unlock_irq(&tp->lock);
|
||||||
|
|
||||||
if (system_state == SYSTEM_POWER_OFF) {
|
if (system_state == SYSTEM_POWER_OFF) {
|
||||||
/* WoL fails with 8168b when the receiver is disabled. */
|
if (__rtl8169_get_wol(tp) & WAKE_ANY) {
|
||||||
if ((tp->mac_version == RTL_GIGA_MAC_VER_11 ||
|
rtl_wol_suspend_quirk(tp);
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_12 ||
|
rtl_wol_shutdown_quirk(tp);
|
||||||
tp->mac_version == RTL_GIGA_MAC_VER_17) &&
|
|
||||||
(tp->features & RTL_FEATURE_WOL)) {
|
|
||||||
pci_clear_master(pdev);
|
|
||||||
|
|
||||||
RTL_W8(ChipCmd, CmdRxEnb);
|
|
||||||
/* PCI commit */
|
|
||||||
RTL_R8(ChipCmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_wake_from_d3(pdev, true);
|
pci_wake_from_d3(pdev, true);
|
||||||
|
|
Loading…
Reference in a new issue