diff options
author | Denis Kirjanov <kda@linux-powerpc.org> | 2012-12-01 03:39:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-12-03 13:32:15 -0500 |
commit | f210e87b6d3aab1fb3eb51a006f4502c1a7a2494 (patch) | |
tree | fb7a1adaec39bf559fa656d587b9d44134e3a5ec /drivers/net | |
parent | 196d67593439b03088913227093e374235596e33 (diff) |
sundance: Enable WoL support
Enable WoL support.
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/dlink/sundance.c | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 3b83588e51f6..bbeb4c7a85ba 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c | |||
@@ -259,6 +259,7 @@ enum alta_offsets { | |||
259 | EECtrl = 0x36, | 259 | EECtrl = 0x36, |
260 | FlashAddr = 0x40, | 260 | FlashAddr = 0x40, |
261 | FlashData = 0x44, | 261 | FlashData = 0x44, |
262 | WakeEvent = 0x45, | ||
262 | TxStatus = 0x46, | 263 | TxStatus = 0x46, |
263 | TxFrameId = 0x47, | 264 | TxFrameId = 0x47, |
264 | DownCounter = 0x18, | 265 | DownCounter = 0x18, |
@@ -333,6 +334,14 @@ enum mac_ctrl1_bits { | |||
333 | RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000, | 334 | RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000, |
334 | }; | 335 | }; |
335 | 336 | ||
337 | /* Bits in WakeEvent register. */ | ||
338 | enum wake_event_bits { | ||
339 | WakePktEnable = 0x01, | ||
340 | MagicPktEnable = 0x02, | ||
341 | LinkEventEnable = 0x04, | ||
342 | WolEnable = 0x80, | ||
343 | }; | ||
344 | |||
336 | /* The Rx and Tx buffer descriptors. */ | 345 | /* The Rx and Tx buffer descriptors. */ |
337 | /* Note that using only 32 bit fields simplifies conversion to big-endian | 346 | /* Note that using only 32 bit fields simplifies conversion to big-endian |
338 | architectures. */ | 347 | architectures. */ |
@@ -392,6 +401,7 @@ struct netdev_private { | |||
392 | unsigned int default_port:4; /* Last dev->if_port value. */ | 401 | unsigned int default_port:4; /* Last dev->if_port value. */ |
393 | unsigned int an_enable:1; | 402 | unsigned int an_enable:1; |
394 | unsigned int speed; | 403 | unsigned int speed; |
404 | unsigned int wol_enabled:1; /* Wake on LAN enabled */ | ||
395 | struct tasklet_struct rx_tasklet; | 405 | struct tasklet_struct rx_tasklet; |
396 | struct tasklet_struct tx_tasklet; | 406 | struct tasklet_struct tx_tasklet; |
397 | int budget; | 407 | int budget; |
@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev) | |||
829 | unsigned long flags; | 839 | unsigned long flags; |
830 | int i; | 840 | int i; |
831 | 841 | ||
832 | /* Do we need to reset the chip??? */ | 842 | sundance_reset(dev, 0x00ff << 16); |
833 | 843 | ||
834 | i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev); | 844 | i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev); |
835 | if (i) | 845 | if (i) |
@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev) | |||
877 | 887 | ||
878 | iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); | 888 | iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); |
879 | 889 | ||
890 | /* Disable Wol */ | ||
891 | iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent); | ||
892 | np->wol_enabled = 0; | ||
893 | |||
880 | if (netif_msg_ifup(np)) | 894 | if (netif_msg_ifup(np)) |
881 | printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " | 895 | printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " |
882 | "MAC Control %x, %4.4x %4.4x.\n", | 896 | "MAC Control %x, %4.4x %4.4x.\n", |
@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev, | |||
1715 | data[i++] = np->xstats.rx_mcasts; | 1729 | data[i++] = np->xstats.rx_mcasts; |
1716 | } | 1730 | } |
1717 | 1731 | ||
1732 | #ifdef CONFIG_PM | ||
1733 | |||
1734 | static void sundance_get_wol(struct net_device *dev, | ||
1735 | struct ethtool_wolinfo *wol) | ||
1736 | { | ||
1737 | struct netdev_private *np = netdev_priv(dev); | ||
1738 | void __iomem *ioaddr = np->base; | ||
1739 | u8 wol_bits; | ||
1740 | |||
1741 | wol->wolopts = 0; | ||
1742 | |||
1743 | wol->supported = (WAKE_PHY | WAKE_MAGIC); | ||
1744 | if (!np->wol_enabled) | ||
1745 | return; | ||
1746 | |||
1747 | wol_bits = ioread8(ioaddr + WakeEvent); | ||
1748 | if (wol_bits & MagicPktEnable) | ||
1749 | wol->wolopts |= WAKE_MAGIC; | ||
1750 | if (wol_bits & LinkEventEnable) | ||
1751 | wol->wolopts |= WAKE_PHY; | ||
1752 | } | ||
1753 | |||
1754 | static int sundance_set_wol(struct net_device *dev, | ||
1755 | struct ethtool_wolinfo *wol) | ||
1756 | { | ||
1757 | struct netdev_private *np = netdev_priv(dev); | ||
1758 | void __iomem *ioaddr = np->base; | ||
1759 | u8 wol_bits; | ||
1760 | |||
1761 | if (!device_can_wakeup(&np->pci_dev->dev)) | ||
1762 | return -EOPNOTSUPP; | ||
1763 | |||
1764 | np->wol_enabled = !!(wol->wolopts); | ||
1765 | wol_bits = ioread8(ioaddr + WakeEvent); | ||
1766 | wol_bits &= ~(WakePktEnable | MagicPktEnable | | ||
1767 | LinkEventEnable | WolEnable); | ||
1768 | |||
1769 | if (np->wol_enabled) { | ||
1770 | if (wol->wolopts & WAKE_MAGIC) | ||
1771 | wol_bits |= (MagicPktEnable | WolEnable); | ||
1772 | if (wol->wolopts & WAKE_PHY) | ||
1773 | wol_bits |= (LinkEventEnable | WolEnable); | ||
1774 | } | ||
1775 | iowrite8(wol_bits, ioaddr + WakeEvent); | ||
1776 | |||
1777 | device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled); | ||
1778 | |||
1779 | return 0; | ||
1780 | } | ||
1781 | #else | ||
1782 | #define sundance_get_wol NULL | ||
1783 | #define sundance_set_wol NULL | ||
1784 | #endif /* CONFIG_PM */ | ||
1785 | |||
1718 | static const struct ethtool_ops ethtool_ops = { | 1786 | static const struct ethtool_ops ethtool_ops = { |
1719 | .begin = check_if_running, | 1787 | .begin = check_if_running, |
1720 | .get_drvinfo = get_drvinfo, | 1788 | .get_drvinfo = get_drvinfo, |
@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = { | |||
1722 | .set_settings = set_settings, | 1790 | .set_settings = set_settings, |
1723 | .nway_reset = nway_reset, | 1791 | .nway_reset = nway_reset, |
1724 | .get_link = get_link, | 1792 | .get_link = get_link, |
1793 | .get_wol = sundance_get_wol, | ||
1794 | .set_wol = sundance_set_wol, | ||
1725 | .get_msglevel = get_msglevel, | 1795 | .get_msglevel = get_msglevel, |
1726 | .set_msglevel = set_msglevel, | 1796 | .set_msglevel = set_msglevel, |
1727 | .get_strings = get_strings, | 1797 | .get_strings = get_strings, |
@@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) | |||
1867 | static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) | 1937 | static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) |
1868 | { | 1938 | { |
1869 | struct net_device *dev = pci_get_drvdata(pci_dev); | 1939 | struct net_device *dev = pci_get_drvdata(pci_dev); |
1940 | struct netdev_private *np = netdev_priv(dev); | ||
1941 | void __iomem *ioaddr = np->base; | ||
1870 | 1942 | ||
1871 | if (!netif_running(dev)) | 1943 | if (!netif_running(dev)) |
1872 | return 0; | 1944 | return 0; |
@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
1875 | netif_device_detach(dev); | 1947 | netif_device_detach(dev); |
1876 | 1948 | ||
1877 | pci_save_state(pci_dev); | 1949 | pci_save_state(pci_dev); |
1950 | if (np->wol_enabled) { | ||
1951 | iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode); | ||
1952 | iowrite16(RxEnable, ioaddr + MACCtrl1); | ||
1953 | } | ||
1954 | pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), | ||
1955 | np->wol_enabled); | ||
1878 | pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); | 1956 | pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); |
1879 | 1957 | ||
1880 | return 0; | 1958 | return 0; |
@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev) | |||
1890 | 1968 | ||
1891 | pci_set_power_state(pci_dev, PCI_D0); | 1969 | pci_set_power_state(pci_dev, PCI_D0); |
1892 | pci_restore_state(pci_dev); | 1970 | pci_restore_state(pci_dev); |
1971 | pci_enable_wake(pci_dev, PCI_D0, 0); | ||
1893 | 1972 | ||
1894 | err = netdev_open(dev); | 1973 | err = netdev_open(dev); |
1895 | if (err) { | 1974 | if (err) { |