diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/r8169.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 999fd6cef77e..8cc0d0bbdf50 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -290,7 +290,15 @@ enum RTL8169_register_content { | |||
| 290 | /* Config1 register p.24 */ | 290 | /* Config1 register p.24 */ |
| 291 | PMEnable = (1 << 0), /* Power Management Enable */ | 291 | PMEnable = (1 << 0), /* Power Management Enable */ |
| 292 | 292 | ||
| 293 | /* Config3 register p.25 */ | ||
| 294 | MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ | ||
| 295 | LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ | ||
| 296 | |||
| 293 | /* Config5 register p.27 */ | 297 | /* Config5 register p.27 */ |
| 298 | BWF = (1 << 6), /* Accept Broadcast wakeup frame */ | ||
| 299 | MWF = (1 << 5), /* Accept Multicast wakeup frame */ | ||
| 300 | UWF = (1 << 4), /* Accept Unicast wakeup frame */ | ||
| 301 | LanWake = (1 << 1), /* LanWake enable/disable */ | ||
| 294 | PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ | 302 | PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ |
| 295 | 303 | ||
| 296 | /* TBICSR p.28 */ | 304 | /* TBICSR p.28 */ |
| @@ -439,6 +447,7 @@ struct rtl8169_private { | |||
| 439 | unsigned int (*phy_reset_pending)(void __iomem *); | 447 | unsigned int (*phy_reset_pending)(void __iomem *); |
| 440 | unsigned int (*link_ok)(void __iomem *); | 448 | unsigned int (*link_ok)(void __iomem *); |
| 441 | struct work_struct task; | 449 | struct work_struct task; |
| 450 | unsigned wol_enabled : 1; | ||
| 442 | }; | 451 | }; |
| 443 | 452 | ||
| 444 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); | 453 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); |
| @@ -613,6 +622,80 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) | |||
| 613 | *duplex = p->duplex; | 622 | *duplex = p->duplex; |
| 614 | } | 623 | } |
| 615 | 624 | ||
| 625 | static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
| 626 | { | ||
| 627 | struct rtl8169_private *tp = netdev_priv(dev); | ||
| 628 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 629 | u8 options; | ||
| 630 | |||
| 631 | wol->wolopts = 0; | ||
| 632 | |||
| 633 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) | ||
| 634 | wol->supported = WAKE_ANY; | ||
| 635 | |||
| 636 | spin_lock_irq(&tp->lock); | ||
| 637 | |||
| 638 | options = RTL_R8(Config1); | ||
| 639 | if (!(options & PMEnable)) | ||
| 640 | goto out_unlock; | ||
| 641 | |||
| 642 | options = RTL_R8(Config3); | ||
| 643 | if (options & LinkUp) | ||
| 644 | wol->wolopts |= WAKE_PHY; | ||
| 645 | if (options & MagicPacket) | ||
| 646 | wol->wolopts |= WAKE_MAGIC; | ||
| 647 | |||
| 648 | options = RTL_R8(Config5); | ||
| 649 | if (options & UWF) | ||
| 650 | wol->wolopts |= WAKE_UCAST; | ||
| 651 | if (options & BWF) | ||
| 652 | wol->wolopts |= WAKE_BCAST; | ||
| 653 | if (options & MWF) | ||
| 654 | wol->wolopts |= WAKE_MCAST; | ||
| 655 | |||
| 656 | out_unlock: | ||
| 657 | spin_unlock_irq(&tp->lock); | ||
| 658 | } | ||
| 659 | |||
| 660 | static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
| 661 | { | ||
| 662 | struct rtl8169_private *tp = netdev_priv(dev); | ||
| 663 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 664 | int i; | ||
| 665 | static struct { | ||
| 666 | u32 opt; | ||
| 667 | u16 reg; | ||
| 668 | u8 mask; | ||
| 669 | } cfg[] = { | ||
| 670 | { WAKE_ANY, Config1, PMEnable }, | ||
| 671 | { WAKE_PHY, Config3, LinkUp }, | ||
| 672 | { WAKE_MAGIC, Config3, MagicPacket }, | ||
| 673 | { WAKE_UCAST, Config5, UWF }, | ||
| 674 | { WAKE_BCAST, Config5, BWF }, | ||
| 675 | { WAKE_MCAST, Config5, MWF }, | ||
| 676 | { WAKE_ANY, Config5, LanWake } | ||
| 677 | }; | ||
| 678 | |||
| 679 | spin_lock_irq(&tp->lock); | ||
| 680 | |||
| 681 | RTL_W8(Cfg9346, Cfg9346_Unlock); | ||
| 682 | |||
| 683 | for (i = 0; i < ARRAY_SIZE(cfg); i++) { | ||
| 684 | u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; | ||
| 685 | if (wol->wolopts & cfg[i].opt) | ||
| 686 | options |= cfg[i].mask; | ||
| 687 | RTL_W8(cfg[i].reg, options); | ||
| 688 | } | ||
| 689 | |||
| 690 | RTL_W8(Cfg9346, Cfg9346_Lock); | ||
| 691 | |||
| 692 | tp->wol_enabled = (wol->wolopts) ? 1 : 0; | ||
| 693 | |||
| 694 | spin_unlock_irq(&tp->lock); | ||
| 695 | |||
| 696 | return 0; | ||
| 697 | } | ||
| 698 | |||
| 616 | static void rtl8169_get_drvinfo(struct net_device *dev, | 699 | static void rtl8169_get_drvinfo(struct net_device *dev, |
| 617 | struct ethtool_drvinfo *info) | 700 | struct ethtool_drvinfo *info) |
| 618 | { | 701 | { |
| @@ -1031,6 +1114,8 @@ static struct ethtool_ops rtl8169_ethtool_ops = { | |||
| 1031 | .get_tso = ethtool_op_get_tso, | 1114 | .get_tso = ethtool_op_get_tso, |
| 1032 | .set_tso = ethtool_op_set_tso, | 1115 | .set_tso = ethtool_op_set_tso, |
| 1033 | .get_regs = rtl8169_get_regs, | 1116 | .get_regs = rtl8169_get_regs, |
| 1117 | .get_wol = rtl8169_get_wol, | ||
| 1118 | .set_wol = rtl8169_set_wol, | ||
| 1034 | .get_strings = rtl8169_get_strings, | 1119 | .get_strings = rtl8169_get_strings, |
| 1035 | .get_stats_count = rtl8169_get_stats_count, | 1120 | .get_stats_count = rtl8169_get_stats_count, |
| 1036 | .get_ethtool_stats = rtl8169_get_ethtool_stats, | 1121 | .get_ethtool_stats = rtl8169_get_ethtool_stats, |
| @@ -2692,6 +2777,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 2692 | spin_unlock_irq(&tp->lock); | 2777 | spin_unlock_irq(&tp->lock); |
| 2693 | 2778 | ||
| 2694 | pci_save_state(pdev); | 2779 | pci_save_state(pdev); |
| 2780 | pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); | ||
| 2695 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 2781 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
| 2696 | out: | 2782 | out: |
| 2697 | return 0; | 2783 | return 0; |
| @@ -2708,6 +2794,7 @@ static int rtl8169_resume(struct pci_dev *pdev) | |||
| 2708 | 2794 | ||
| 2709 | pci_set_power_state(pdev, PCI_D0); | 2795 | pci_set_power_state(pdev, PCI_D0); |
| 2710 | pci_restore_state(pdev); | 2796 | pci_restore_state(pdev); |
| 2797 | pci_enable_wake(pdev, PCI_D0, 0); | ||
| 2711 | 2798 | ||
| 2712 | rtl8169_schedule_work(dev, rtl8169_reset_task); | 2799 | rtl8169_schedule_work(dev, rtl8169_reset_task); |
| 2713 | out: | 2800 | out: |
