diff options
| author | françois romieu <romieu@fr.zoreil.com> | 2011-10-13 20:57:45 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-10-19 17:08:21 -0400 |
| commit | 649b3b8c4e8681de443b4dc9e387c3036369e02e (patch) | |
| tree | 2074058f98c291e154f707b0593ca06a09bb70b9 | |
| parent | 34b1901abdf8793cd679d0e48012d3d7570f88d6 (diff) | |
r8169: fix driver shutdown WoL regression.
Due to commit 92fc43b4159b518f5baae57301f26d770b0834c9 ("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>
| -rw-r--r-- | drivers/net/r8169.c | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c23667017922..24219ec0de13 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -3316,6 +3316,37 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) | |||
| 3316 | } | 3316 | } |
| 3317 | } | 3317 | } |
| 3318 | 3318 | ||
| 3319 | static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) | ||
| 3320 | { | ||
| 3321 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 3322 | |||
| 3323 | switch (tp->mac_version) { | ||
| 3324 | case RTL_GIGA_MAC_VER_29: | ||
| 3325 | case RTL_GIGA_MAC_VER_30: | ||
| 3326 | case RTL_GIGA_MAC_VER_32: | ||
| 3327 | case RTL_GIGA_MAC_VER_33: | ||
| 3328 | case RTL_GIGA_MAC_VER_34: | ||
| 3329 | RTL_W32(RxConfig, RTL_R32(RxConfig) | | ||
| 3330 | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); | ||
| 3331 | break; | ||
| 3332 | default: | ||
| 3333 | break; | ||
| 3334 | } | ||
| 3335 | } | ||
| 3336 | |||
| 3337 | static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) | ||
| 3338 | { | ||
| 3339 | if (!(__rtl8169_get_wol(tp) & WAKE_ANY)) | ||
| 3340 | return false; | ||
| 3341 | |||
| 3342 | rtl_writephy(tp, 0x1f, 0x0000); | ||
| 3343 | rtl_writephy(tp, MII_BMCR, 0x0000); | ||
| 3344 | |||
| 3345 | rtl_wol_suspend_quirk(tp); | ||
| 3346 | |||
| 3347 | return true; | ||
| 3348 | } | ||
| 3349 | |||
| 3319 | static void r810x_phy_power_down(struct rtl8169_private *tp) | 3350 | static void r810x_phy_power_down(struct rtl8169_private *tp) |
| 3320 | { | 3351 | { |
| 3321 | rtl_writephy(tp, 0x1f, 0x0000); | 3352 | rtl_writephy(tp, 0x1f, 0x0000); |
| @@ -3330,18 +3361,8 @@ static void r810x_phy_power_up(struct rtl8169_private *tp) | |||
| 3330 | 3361 | ||
| 3331 | static void r810x_pll_power_down(struct rtl8169_private *tp) | 3362 | static void r810x_pll_power_down(struct rtl8169_private *tp) |
| 3332 | { | 3363 | { |
| 3333 | void __iomem *ioaddr = tp->mmio_addr; | 3364 | if (rtl_wol_pll_power_down(tp)) |
| 3334 | |||
| 3335 | if (__rtl8169_get_wol(tp) & WAKE_ANY) { | ||
| 3336 | rtl_writephy(tp, 0x1f, 0x0000); | ||
| 3337 | rtl_writephy(tp, MII_BMCR, 0x0000); | ||
| 3338 | |||
| 3339 | if (tp->mac_version == RTL_GIGA_MAC_VER_29 || | ||
| 3340 | tp->mac_version == RTL_GIGA_MAC_VER_30) | ||
| 3341 | RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | | ||
| 3342 | AcceptMulticast | AcceptMyPhys); | ||
| 3343 | return; | 3365 | return; |
| 3344 | } | ||
| 3345 | 3366 | ||
| 3346 | r810x_phy_power_down(tp); | 3367 | r810x_phy_power_down(tp); |
| 3347 | } | 3368 | } |
| @@ -3430,17 +3451,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) | |||
| 3430 | tp->mac_version == RTL_GIGA_MAC_VER_33) | 3451 | tp->mac_version == RTL_GIGA_MAC_VER_33) |
| 3431 | rtl_ephy_write(ioaddr, 0x19, 0xff64); | 3452 | rtl_ephy_write(ioaddr, 0x19, 0xff64); |
| 3432 | 3453 | ||
| 3433 | if (__rtl8169_get_wol(tp) & WAKE_ANY) { | 3454 | if (rtl_wol_pll_power_down(tp)) |
| 3434 | rtl_writephy(tp, 0x1f, 0x0000); | ||
| 3435 | rtl_writephy(tp, MII_BMCR, 0x0000); | ||
| 3436 | |||
| 3437 | if (tp->mac_version == RTL_GIGA_MAC_VER_32 || | ||
| 3438 | tp->mac_version == RTL_GIGA_MAC_VER_33 || | ||
| 3439 | tp->mac_version == RTL_GIGA_MAC_VER_34) | ||
| 3440 | RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | | ||
| 3441 | AcceptMulticast | AcceptMyPhys); | ||
| 3442 | return; | 3455 | return; |
| 3443 | } | ||
| 3444 | 3456 | ||
| 3445 | r8168_phy_power_down(tp); | 3457 | r8168_phy_power_down(tp); |
| 3446 | 3458 | ||
| @@ -5788,11 +5800,30 @@ static const struct dev_pm_ops rtl8169_pm_ops = { | |||
| 5788 | 5800 | ||
| 5789 | #endif /* !CONFIG_PM */ | 5801 | #endif /* !CONFIG_PM */ |
| 5790 | 5802 | ||
| 5803 | static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp) | ||
| 5804 | { | ||
| 5805 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 5806 | |||
| 5807 | /* WoL fails with 8168b when the receiver is disabled. */ | ||
| 5808 | switch (tp->mac_version) { | ||
| 5809 | case RTL_GIGA_MAC_VER_11: | ||
| 5810 | case RTL_GIGA_MAC_VER_12: | ||
| 5811 | case RTL_GIGA_MAC_VER_17: | ||
| 5812 | pci_clear_master(tp->pci_dev); | ||
| 5813 | |||
| 5814 | RTL_W8(ChipCmd, CmdRxEnb); | ||
| 5815 | /* PCI commit */ | ||
| 5816 | RTL_R8(ChipCmd); | ||
| 5817 | break; | ||
| 5818 | default: | ||
| 5819 | break; | ||
| 5820 | } | ||
| 5821 | } | ||
| 5822 | |||
| 5791 | static void rtl_shutdown(struct pci_dev *pdev) | 5823 | static void rtl_shutdown(struct pci_dev *pdev) |
| 5792 | { | 5824 | { |
| 5793 | struct net_device *dev = pci_get_drvdata(pdev); | 5825 | struct net_device *dev = pci_get_drvdata(pdev); |
| 5794 | struct rtl8169_private *tp = netdev_priv(dev); | 5826 | struct rtl8169_private *tp = netdev_priv(dev); |
| 5795 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 5796 | 5827 | ||
| 5797 | rtl8169_net_suspend(dev); | 5828 | rtl8169_net_suspend(dev); |
| 5798 | 5829 | ||
| @@ -5806,16 +5837,9 @@ static void rtl_shutdown(struct pci_dev *pdev) | |||
| 5806 | spin_unlock_irq(&tp->lock); | 5837 | spin_unlock_irq(&tp->lock); |
| 5807 | 5838 | ||
| 5808 | if (system_state == SYSTEM_POWER_OFF) { | 5839 | if (system_state == SYSTEM_POWER_OFF) { |
| 5809 | /* WoL fails with 8168b when the receiver is disabled. */ | 5840 | if (__rtl8169_get_wol(tp) & WAKE_ANY) { |
| 5810 | if ((tp->mac_version == RTL_GIGA_MAC_VER_11 || | 5841 | rtl_wol_suspend_quirk(tp); |
| 5811 | tp->mac_version == RTL_GIGA_MAC_VER_12 || | 5842 | rtl_wol_shutdown_quirk(tp); |
| 5812 | tp->mac_version == RTL_GIGA_MAC_VER_17) && | ||
| 5813 | (tp->features & RTL_FEATURE_WOL)) { | ||
| 5814 | pci_clear_master(pdev); | ||
| 5815 | |||
| 5816 | RTL_W8(ChipCmd, CmdRxEnb); | ||
| 5817 | /* PCI commit */ | ||
| 5818 | RTL_R8(ChipCmd); | ||
| 5819 | } | 5843 | } |
| 5820 | 5844 | ||
| 5821 | pci_wake_from_d3(pdev, true); | 5845 | pci_wake_from_d3(pdev, true); |
