Commit f210e87b authored by Denis Kirjanov's avatar Denis Kirjanov Committed by David S. Miller

sundance: Enable WoL support

Enable WoL support.
Signed-off-by: default avatarDenis Kirjanov <kda@linux-powerpc.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 196d6759
...@@ -259,6 +259,7 @@ enum alta_offsets { ...@@ -259,6 +259,7 @@ enum alta_offsets {
EECtrl = 0x36, EECtrl = 0x36,
FlashAddr = 0x40, FlashAddr = 0x40,
FlashData = 0x44, FlashData = 0x44,
WakeEvent = 0x45,
TxStatus = 0x46, TxStatus = 0x46,
TxFrameId = 0x47, TxFrameId = 0x47,
DownCounter = 0x18, DownCounter = 0x18,
...@@ -333,6 +334,14 @@ enum mac_ctrl1_bits { ...@@ -333,6 +334,14 @@ enum mac_ctrl1_bits {
RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000, RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000,
}; };
/* Bits in WakeEvent register. */
enum wake_event_bits {
WakePktEnable = 0x01,
MagicPktEnable = 0x02,
LinkEventEnable = 0x04,
WolEnable = 0x80,
};
/* The Rx and Tx buffer descriptors. */ /* The Rx and Tx buffer descriptors. */
/* Note that using only 32 bit fields simplifies conversion to big-endian /* Note that using only 32 bit fields simplifies conversion to big-endian
architectures. */ architectures. */
...@@ -392,6 +401,7 @@ struct netdev_private { ...@@ -392,6 +401,7 @@ struct netdev_private {
unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int an_enable:1; unsigned int an_enable:1;
unsigned int speed; unsigned int speed;
unsigned int wol_enabled:1; /* Wake on LAN enabled */
struct tasklet_struct rx_tasklet; struct tasklet_struct rx_tasklet;
struct tasklet_struct tx_tasklet; struct tasklet_struct tx_tasklet;
int budget; int budget;
...@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev) ...@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev)
unsigned long flags; unsigned long flags;
int i; int i;
/* Do we need to reset the chip??? */ sundance_reset(dev, 0x00ff << 16);
i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev); i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (i) if (i)
...@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev) ...@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev)
iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
/* Disable Wol */
iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent);
np->wol_enabled = 0;
if (netif_msg_ifup(np)) if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
"MAC Control %x, %4.4x %4.4x.\n", "MAC Control %x, %4.4x %4.4x.\n",
...@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev, ...@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev,
data[i++] = np->xstats.rx_mcasts; data[i++] = np->xstats.rx_mcasts;
} }
#ifdef CONFIG_PM
static void sundance_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
u8 wol_bits;
wol->wolopts = 0;
wol->supported = (WAKE_PHY | WAKE_MAGIC);
if (!np->wol_enabled)
return;
wol_bits = ioread8(ioaddr + WakeEvent);
if (wol_bits & MagicPktEnable)
wol->wolopts |= WAKE_MAGIC;
if (wol_bits & LinkEventEnable)
wol->wolopts |= WAKE_PHY;
}
static int sundance_set_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
u8 wol_bits;
if (!device_can_wakeup(&np->pci_dev->dev))
return -EOPNOTSUPP;
np->wol_enabled = !!(wol->wolopts);
wol_bits = ioread8(ioaddr + WakeEvent);
wol_bits &= ~(WakePktEnable | MagicPktEnable |
LinkEventEnable | WolEnable);
if (np->wol_enabled) {
if (wol->wolopts & WAKE_MAGIC)
wol_bits |= (MagicPktEnable | WolEnable);
if (wol->wolopts & WAKE_PHY)
wol_bits |= (LinkEventEnable | WolEnable);
}
iowrite8(wol_bits, ioaddr + WakeEvent);
device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled);
return 0;
}
#else
#define sundance_get_wol NULL
#define sundance_set_wol NULL
#endif /* CONFIG_PM */
static const struct ethtool_ops ethtool_ops = { static const struct ethtool_ops ethtool_ops = {
.begin = check_if_running, .begin = check_if_running,
.get_drvinfo = get_drvinfo, .get_drvinfo = get_drvinfo,
...@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = { ...@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = {
.set_settings = set_settings, .set_settings = set_settings,
.nway_reset = nway_reset, .nway_reset = nway_reset,
.get_link = get_link, .get_link = get_link,
.get_wol = sundance_get_wol,
.set_wol = sundance_set_wol,
.get_msglevel = get_msglevel, .get_msglevel = get_msglevel,
.set_msglevel = set_msglevel, .set_msglevel = set_msglevel,
.get_strings = get_strings, .get_strings = get_strings,
...@@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) ...@@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev)
static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
{ {
struct net_device *dev = pci_get_drvdata(pci_dev); struct net_device *dev = pci_get_drvdata(pci_dev);
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
if (!netif_running(dev)) if (!netif_running(dev))
return 0; return 0;
...@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) ...@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
netif_device_detach(dev); netif_device_detach(dev);
pci_save_state(pci_dev); pci_save_state(pci_dev);
if (np->wol_enabled) {
iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
iowrite16(RxEnable, ioaddr + MACCtrl1);
}
pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state),
np->wol_enabled);
pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
return 0; return 0;
...@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev) ...@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev)
pci_set_power_state(pci_dev, PCI_D0); pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev); pci_restore_state(pci_dev);
pci_enable_wake(pci_dev, PCI_D0, 0);
err = netdev_open(dev); err = netdev_open(dev);
if (err) { if (err) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment