Skip to content

Commit

Permalink
sundance: Enable WoL support
Browse files Browse the repository at this point in the history
Enable WoL support.

Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Denis Kirjanov authored and David S. Miller committed Dec 3, 2012
1 parent 196d675 commit f210e87
Showing 1 changed file with 80 additions and 1 deletion.
81 changes: 80 additions & 1 deletion drivers/net/ethernet/dlink/sundance.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ enum alta_offsets {
EECtrl = 0x36,
FlashAddr = 0x40,
FlashData = 0x44,
WakeEvent = 0x45,
TxStatus = 0x46,
TxFrameId = 0x47,
DownCounter = 0x18,
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -1715,13 +1729,69 @@ 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,
.get_settings = get_settings,
.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,
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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) {
Expand Down

0 comments on commit f210e87

Please sign in to comment.