diff options
author | Kevin Lo <kevlo@cvs.openbsd.org> | 2020-12-24 01:00:01 +0000 |
---|---|---|
committer | Kevin Lo <kevlo@cvs.openbsd.org> | 2020-12-24 01:00:01 +0000 |
commit | 519d2e3ecc2dce33b639b70ad3334db0f16f4f6a (patch) | |
tree | 9d90f1bf4dfb5e17043b20822ca4316db0ad0b84 | |
parent | bda35853e52176dbc66a3efec57f7a744ddcd580 (diff) |
Add Wake on LAN support to rge(4).
Tested by otto@ and myself.
-rw-r--r-- | share/man/man4/rge.4 | 13 | ||||
-rw-r--r-- | sys/dev/pci/if_rge.c | 79 | ||||
-rw-r--r-- | sys/dev/pci/if_rgereg.h | 10 |
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 |