From: Roger Luethi <rl@hellgate.ch>
To: Jeff Garzik <jgarzik@pobox.com>, Andrew Morton <akpm@osdl.org>
Cc: netdev@oss.sgi.com
Subject: [9/9][PATCH 2.6] Add WOL support
Date: Tue, 15 Jun 2004 19:50:03 +0200 [thread overview]
Message-ID: <20040615175003.GA11382@k3.hellgate.ch> (raw)
In-Reply-To: <20040615174732.GA10241@k3.hellgate.ch>
Add rhine_shutdown callback to prepare Rhine power registers for
shutdown.
Add rhine_get_wol/rhine_set_wol for ethtool ioctl.
Signed-off-by: Roger Luethi <rl@hellgate.ch>
--- 2.6-mm/drivers/net/via-rhine.c.orig 2004-06-15 18:34:21.000000000 +0200
+++ 2.6-mm/drivers/net/via-rhine.c 2004-06-15 18:36:12.000000000 +0200
@@ -394,8 +394,8 @@
ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
StickyHW=0x83, IntrStatus2=0x84,
- WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6,
- WOLcgClr=0xA7,
+ WOLcrSet=0xA0, PwcfgSet=0xA1, WOLcgSet=0xA3, WOLcrClr=0xA4,
+ WOLcrClr1=0xA6, WOLcgClr=0xA7,
PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD,
};
@@ -427,6 +427,15 @@
IntrTxErrSummary=0x082218,
};
+/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
+enum wol_bits {
+ WOLucast = 0x10,
+ WOLmagic = 0x20,
+ WOLbmcast = 0x30,
+ WOLlnkon = 0x40,
+ WOLlnkoff = 0x80,
+};
+
/* The Rx and Tx buffer descriptors. */
struct rx_desc {
s32 rx_status;
@@ -491,8 +500,8 @@
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int cur_tx, dirty_tx;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ u8 wolopts;
- /* These values are keep track of the transceiver/media in use. */
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if;
@@ -512,6 +521,7 @@
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct ethtool_ops netdev_ethtool_ops;
static int rhine_close(struct net_device *dev);
+static void rhine_shutdown (struct device *gdev);
#define RHINE_WAIT_FOR(condition) do { \
int i=1024; \
@@ -537,12 +547,13 @@
/*
* Get power related registers into sane state.
- * Returns content of power-event (WOL) registers.
+ * Notify user about past WOL event.
*/
static void rhine_power_init(struct net_device *dev)
{
long ioaddr = dev->base_addr;
struct rhine_private *rp = netdev_priv(dev);
+ u16 wolstat;
if (rp->quirks & rqWOL) {
/* Make sure chip is in power state D0 */
@@ -557,10 +568,40 @@
if (rp->quirks & rq6patterns)
writeb(0x03, ioaddr + WOLcrClr1);
+ /* Save power-event status bits */
+ wolstat = readb(ioaddr + PwrcsrSet);
+ if (rp->quirks & rq6patterns)
+ wolstat |= (readb(ioaddr + PwrcsrSet1) & 0x03) << 8;
+
/* Clear power-event status bits */
writeb(0xFF, ioaddr + PwrcsrClr);
if (rp->quirks & rq6patterns)
writeb(0x03, ioaddr + PwrcsrClr1);
+
+ if (wolstat) {
+ char *reason;
+ switch (wolstat) {
+ case WOLmagic:
+ reason = "Magic packet";
+ break;
+ case WOLlnkon:
+ reason = "Link went up";
+ break;
+ case WOLlnkoff:
+ reason = "Link went down";
+ break;
+ case WOLucast:
+ reason = "Unicast packet";
+ break;
+ case WOLbmcast:
+ reason = "Multicast/broadcast packet";
+ break;
+ default:
+ reason = "Unknown";
+ }
+ printk("%s: Woke system up. Reason: %s.\n",
+ DRV_NAME, reason);
+ }
}
}
@@ -1766,6 +1807,39 @@
debug = value;
}
+static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct rhine_private *rp = netdev_priv(dev);
+
+ if (!(rp->quirks & rqWOL))
+ return;
+
+ spin_lock_irq(&rp->lock);
+ wol->supported = WAKE_PHY | WAKE_MAGIC |
+ WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; /* Untested */
+ wol->wolopts = rp->wolopts;
+ spin_unlock_irq(&rp->lock);
+}
+
+static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct rhine_private *rp = netdev_priv(dev);
+ u32 support = WAKE_PHY | WAKE_MAGIC |
+ WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; /* Untested */
+
+ if (!(rp->quirks & rqWOL))
+ return -EINVAL;
+
+ if (wol->wolopts & ~support)
+ return -EINVAL;
+
+ spin_lock_irq(&rp->lock);
+ rp->wolopts = wol->wolopts;
+ spin_unlock_irq(&rp->lock);
+
+ return 0;
+}
+
static struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
.get_settings = netdev_get_settings,
@@ -1774,6 +1848,8 @@
.get_link = netdev_get_link,
.get_msglevel = netdev_get_msglevel,
.set_msglevel = netdev_set_msglevel,
+ .get_wol = rhine_get_wol,
+ .set_wol = rhine_set_wol,
.get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
};
@@ -1844,12 +1920,51 @@
pci_set_drvdata(pdev, NULL);
}
+static void rhine_shutdown (struct device *gendev)
+{
+ struct pci_dev *pdev = to_pci_dev(gendev);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rhine_private *rp = netdev_priv(dev);
+
+ long ioaddr = dev->base_addr;
+
+ rhine_power_init(dev);
+
+ /* Make sure we use pattern 0, 1 and not 4, 5 */
+ if (rp->quirks & rq6patterns)
+ writeb(0x04, ioaddr + 0xA7);
+
+ if (rp->wolopts & WAKE_MAGIC)
+ writeb(WOLmagic, ioaddr + WOLcrSet);
+
+ if (rp->wolopts & (WAKE_BCAST|WAKE_MCAST))
+ writeb(WOLbmcast, ioaddr + WOLcgSet);
+
+ if (rp->wolopts & WAKE_PHY)
+ writeb(WOLlnkon | WOLlnkoff, ioaddr + WOLcrSet);
+
+ if (rp->wolopts & WAKE_UCAST)
+ writeb(WOLucast, ioaddr + WOLcrSet);
+
+ /* Enable legacy WOL (for old motherboards) */
+ writeb(0x01, ioaddr + PwcfgSet);
+ writeb(readb(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW);
+
+ /* Hit power state D3 (sleep) */
+ writeb(readb(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+
+ /* TODO: Check use of pci_enable_wake() */
+
+}
static struct pci_driver rhine_driver = {
.name = DRV_NAME,
.id_table = rhine_pci_tbl,
.probe = rhine_init_one,
.remove = __devexit_p(rhine_remove_one),
+ .driver = {
+ .shutdown = rhine_shutdown,
+ }
};
next prev parent reply other threads:[~2004-06-15 17:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-06-15 17:47 [0/9] via-rhine: Major surgery Roger Luethi
2004-06-15 17:48 ` [1/9][PATCH 2.6] Restructure reset code Roger Luethi
2004-06-15 17:48 ` [2/9][PATCH 2.6] fix mc_filter on big-endian arch Roger Luethi
2004-06-15 17:48 ` [3/9][PATCH 2.6] Remove lingering PHY special casing Roger Luethi
2004-06-15 17:49 ` [4/9][PATCH 2.6] Rewrite PHY detection Roger Luethi
2004-06-15 17:49 ` [5/9][PATCH 2.6] Remove options, full_duplex parameters Roger Luethi
2004-06-15 17:49 ` [7/9][PATCH 2.6] Media mode rewrite Roger Luethi
2004-06-19 21:24 ` Jeff Garzik
2004-06-19 22:20 ` Roger Luethi
2004-06-15 17:49 ` [8/9][PATCH 2.6] Small fixes and clean-up Roger Luethi
[not found] ` <40D4AFE1.6020508@pobox.com>
2004-06-19 22:23 ` Roger Luethi
2004-06-15 17:50 ` Roger Luethi [this message]
2004-06-19 21:29 ` [9/9][PATCH 2.6] Add WOL support Jeff Garzik
2004-06-19 22:15 ` Roger Luethi
2004-06-16 15:03 ` [0/9] via-rhine: Major surgery Jeff Garzik
2004-06-19 21:20 ` Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040615175003.GA11382@k3.hellgate.ch \
--to=rl@hellgate.ch \
--cc=akpm@osdl.org \
--cc=jgarzik@pobox.com \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).