mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
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>
This commit is contained in:
parent
196d675934
commit
f210e87b6d
1 changed files with 80 additions and 1 deletions
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue