Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+80 −1
Original line number Diff line number Diff line
@@ -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) {