All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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 {
EECtrl = 0x36,
FlashAddr = 0x40,
FlashData = 0x44,
WakeEvent = 0x45,
TxStatus = 0x46,
TxFrameId = 0x47,
DownCounter = 0x18,
......@@ -333,6 +334,14 @@ enum mac_ctrl1_bits {
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. */
/* Note that using only 32 bit fields simplifies conversion to big-endian
architectures. */
......@@ -392,6 +401,7 @@ struct netdev_private {
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int an_enable:1;
unsigned int speed;
unsigned int wol_enabled:1; /* Wake on LAN enabled */
struct tasklet_struct rx_tasklet;
struct tasklet_struct tx_tasklet;
int budget;
......@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev)
unsigned long flags;
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);
if (i)
......@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev)
iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
/* Disable Wol */
iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent);
np->wol_enabled = 0;
if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
"MAC Control %x, %4.4x %4.4x.\n",
......@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev,
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 = {
.begin = check_if_running,
.get_drvinfo = get_drvinfo,
......@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = {
.set_settings = set_settings,
.nway_reset = nway_reset,
.get_link = get_link,
.get_wol = sundance_get_wol,
.set_wol = sundance_set_wol,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
.get_strings = get_strings,
......@@ -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)
{
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))
return 0;
......@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
netif_device_detach(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));
return 0;
......@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev)
pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
pci_enable_wake(pci_dev, PCI_D0, 0);
err = netdev_open(dev);
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