summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Lo <kevlo@cvs.openbsd.org>2020-12-24 01:00:01 +0000
committerKevin Lo <kevlo@cvs.openbsd.org>2020-12-24 01:00:01 +0000
commit519d2e3ecc2dce33b639b70ad3334db0f16f4f6a (patch)
tree9d90f1bf4dfb5e17043b20822ca4316db0ad0b84
parentbda35853e52176dbc66a3efec57f7a744ddcd580 (diff)
Add Wake on LAN support to rge(4).
Tested by otto@ and myself.
-rw-r--r--share/man/man4/rge.413
-rw-r--r--sys/dev/pci/if_rge.c79
-rw-r--r--sys/dev/pci/if_rgereg.h10
3 files changed, 97 insertions, 5 deletions
diff --git a/share/man/man4/rge.4 b/share/man/man4/rge.4
index eeb241713a7..ccf5b4b4f5f 100644
--- a/share/man/man4/rge.4
+++ b/share/man/man4/rge.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: rge.4,v 1.4 2020/10/12 02:11:10 kevlo Exp $
+.\" $OpenBSD: rge.4,v 1.5 2020/12/24 01:00:00 kevlo Exp $
.\"
.\" Copyright (c) 2019, 2020 Kevin Lo <kevlo@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 12 2020 $
+.Dd $Mdocdate: December 24 2020 $
.Dt RGE 4
.Os
.Sh NAME
@@ -37,6 +37,15 @@ Rivet Networks Killer E3000 Adapter (2500baseT)
.It
TP-LINK TL-NG421 Adapter (2500baseT)
.El
+.Pp
+The
+.Nm
+driver additionally supports Wake on LAN (WoL).
+See
+.Xr arp 8
+and
+.Xr ifconfig 8
+for more details.
.Sh SEE ALSO
.Xr arp 4 ,
.Xr ifmedia 4 ,
diff --git a/sys/dev/pci/if_rge.c b/sys/dev/pci/if_rge.c
index 9bc4d50b26e..d7f7d48568c 100644
--- a/sys/dev/pci/if_rge.c
+++ b/sys/dev/pci/if_rge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_rge.c,v 1.9 2020/12/12 11:48:53 jan Exp $ */
+/* $OpenBSD: if_rge.c,v 1.10 2020/12/24 01:00:00 kevlo Exp $ */
/*
* Copyright (c) 2019, 2020 Kevin Lo <kevlo@openbsd.org>
@@ -59,6 +59,7 @@ int rge_debug = 0;
int rge_match(struct device *, void *, void *);
void rge_attach(struct device *, struct device *, void *);
+int rge_activate(struct device *, int);
int rge_intr(void *);
int rge_encap(struct rge_softc *, struct mbuf *, int);
int rge_ioctl(struct ifnet *, u_long, caddr_t);
@@ -111,6 +112,10 @@ int rge_get_link_status(struct rge_softc *);
void rge_txstart(void *);
void rge_tick(void *);
void rge_link_state(struct rge_softc *);
+#ifndef SMALL_KERNEL
+int rge_wol(struct ifnet *, int);
+void rge_wol_power(struct rge_softc *);
+#endif
static const struct {
uint16_t reg;
@@ -126,7 +131,7 @@ static const struct {
};
struct cfattach rge_ca = {
- sizeof(struct rge_softc), rge_match, rge_attach
+ sizeof(struct rge_softc), rge_match, rge_attach, NULL, rge_activate
};
struct cfdriver rge_cd = {
@@ -272,6 +277,11 @@ rge_attach(struct device *parent, struct device *self, void *aux)
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
#endif
+#ifndef SMALL_KERNEL
+ ifp->if_capabilities |= IFCAP_WOL;
+ ifp->if_wol = rge_wol;
+ rge_wol(ifp, 0);
+#endif
timeout_set(&sc->sc_timeout, rge_tick, sc);
task_set(&sc->sc_task, rge_txstart, sc);
@@ -288,6 +298,25 @@ rge_attach(struct device *parent, struct device *self, void *aux)
}
int
+rge_activate(struct device *self, int act)
+{
+ struct rge_softc *sc = (struct rge_softc *)self;
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_POWERDOWN:
+ rv = config_activate_children(self, act);
+#ifndef SMALL_KERNEL
+ rge_wol_power(sc);
+#endif
+ default:
+ rv = config_activate_children(self, act);
+ break;
+ }
+ return (rv);
+}
+
+int
rge_intr(void *arg)
{
struct rge_softc *sc = arg;
@@ -2025,6 +2054,7 @@ rge_hw_init(struct rge_softc *sc)
/* Set PCIe uncorrectable error status. */
rge_write_csi(sc, 0x108,
rge_read_csi(sc, 0x108) | 0x00100000);
+
}
void
@@ -2391,3 +2421,48 @@ rge_link_state(struct rge_softc *sc)
if_link_state_change(ifp);
}
}
+
+#ifndef SMALL_KERNEL
+int
+rge_wol(struct ifnet *ifp, int enable)
+{
+ struct rge_softc *sc = ifp->if_softc;
+
+ if (enable) {
+ if (!(RGE_READ_1(sc, RGE_CFG1) & RGE_CFG1_PM_EN)) {
+ printf("%s: power management is disabled, "
+ "cannot do WOL\n", sc->sc_dev.dv_xname);
+ return (ENOTSUP);
+ }
+
+ }
+
+ rge_iff(sc);
+
+ if (enable)
+ RGE_MAC_SETBIT(sc, 0xc0b6, 0x0001);
+ else
+ RGE_MAC_CLRBIT(sc, 0xc0b6, 0x0001);
+
+ RGE_SETBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG);
+ RGE_CLRBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE | RGE_CFG5_WOL_UCAST |
+ RGE_CFG5_WOL_MCAST | RGE_CFG5_WOL_BCAST);
+ RGE_CLRBIT_1(sc, RGE_CFG3, RGE_CFG3_WOL_LINK | RGE_CFG3_WOL_MAGIC);
+ if (enable)
+ RGE_SETBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE);
+ RGE_CLRBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG);
+
+ return (0);
+}
+
+void
+rge_wol_power(struct rge_softc *sc)
+{
+ /* Disable RXDV gate. */
+ RGE_CLRBIT_1(sc, RGE_PPSW, 0x08);
+ DELAY(2000);
+
+ RGE_SETBIT_1(sc, RGE_CFG1, RGE_CFG1_PM_EN);
+ RGE_SETBIT_1(sc, RGE_CFG2, RGE_CFG2_PMSTS_EN);
+}
+#endif
diff --git a/sys/dev/pci/if_rgereg.h b/sys/dev/pci/if_rgereg.h
index 55954d6d6e2..02b3a737667 100644
--- a/sys/dev/pci/if_rgereg.h
+++ b/sys/dev/pci/if_rgereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_rgereg.h,v 1.5 2020/11/22 14:06:22 otto Exp $ */
+/* $OpenBSD: if_rgereg.h,v 1.6 2020/12/24 01:00:00 kevlo Exp $ */
/*
* Copyright (c) 2019, 2020 Kevin Lo <kevlo@openbsd.org>
@@ -111,16 +111,24 @@
#define RGE_EECMD_WRITECFG 0xc0
/* Flags for register RGE_CFG1 */
+#define RGE_CFG1_PM_EN 0x01
#define RGE_CFG1_SPEED_DOWN 0x10
/* Flags for register RGE_CFG2 */
+#define RGE_CFG2_PMSTS_EN 0x20
#define RGE_CFG2_CLKREQ_EN 0x80
/* Flags for register RGE_CFG3 */
#define RGE_CFG3_RDY_TO_L23 0x02
+#define RGE_CFG3_WOL_LINK 0x10
+#define RGE_CFG3_WOL_MAGIC 0x20
/* Flags for register RGE_CFG5 */
#define RGE_CFG5_PME_STS 0x01
+#define RGE_CFG5_WOL_LANWAKE 0x02
+#define RGE_CFG5_WOL_UCAST 0x10
+#define RGE_CFG5_WOL_MCAST 0x20
+#define RGE_CFG5_WOL_BCAST 0x40
/* Flags for register RGE_CSIAR */
#define RGE_CSIAR_BYTE_EN 0x0000000f