aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDenis Kirjanov <kda@linux-powerpc.org>2012-12-01 03:39:19 -0500
committerDavid S. Miller <davem@davemloft.net>2012-12-03 13:32:15 -0500
commitf210e87b6d3aab1fb3eb51a006f4502c1a7a2494 (patch)
treefb7a1adaec39bf559fa656d587b9d44134e3a5ec /drivers/net
parent196d67593439b03088913227093e374235596e33 (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.c81
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. */
338enum 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
1734static 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
1754static 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
1718static const struct ethtool_ops ethtool_ops = { 1786static 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)
1867static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) 1937static 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) {