On Sun, Mar 13, 2011 at 01:03:19AM +0100, Stefan Sperling wrote:
> Now that arp(8) can send Wake On Lan frames (a.k.a. magic packets),
> it would be nice to have a way to configure WOL from the operating system.
Some man page fixes, and ifconfig now prints a "not supported" message if
the user tries to enable WOL on an interface which doesn't support WOL.
Both suggested by jmc.
Index: sbin/ifconfig/brconfig.h
===================================================================
RCS file: /cvs/src/sbin/ifconfig/brconfig.h,v
retrieving revision 1.3
diff -u -p -r1.3 brconfig.h
--- sbin/ifconfig/brconfig.h 7 Jun 2010 15:05:42 -0000 1.3
+++ sbin/ifconfig/brconfig.h 12 Mar 2011 22:48:05 -0000
@@ -68,7 +68,7 @@ int bridge_rule(int, char **, int);
#define IFFBITS \
"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
-\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST\21TXREADY\22NOINET6\23INET6_PRIVACY\24MPLS"
+\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST\21TXREADY\22NOINET6\23INET6_PRIVACY\24MPLS\25WOL"
void printb(char *, unsigned int, char *);
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.213
diff -u -p -r1.213 ifconfig.8
--- sbin/ifconfig/ifconfig.8 17 Feb 2011 08:32:29 -0000 1.213
+++ sbin/ifconfig/ifconfig.8 13 Mar 2011 10:05:35 -0000
@@ -435,6 +435,26 @@ This may be used to enable an interface
It happens automatically when setting the first address on an interface.
If the interface was reset when previously marked down,
the hardware will be re-initialized.
+.Pp
+.It Cm wol
+Enable Wake On LAN (WOL).
+When enabled, reception of a WOL frame (a.k.a. Magic Packet) will cause
+the network card to power up the system from standby or suspend mode.
+WOL frames can be sent using
+.Xr arp 8 .
+Support for WOL depends on various factors, some of which may not be under
+the control of the operating system.
+Configuration parameters in the system BIOS or firmware can affect WOL.
+.Pp
+WOL should not be enabled on interfaces that can receive traffic
+from the internet.
+It should only be enabled on dedicated management interfaces connected to
+networks where no packets can be injected by untrusted parties.
+WOL frames can be sent in routable IP packets and are not authenticated.
+.It Fl wol
+Disable WOL.
+WOL is disabled by default if possible.
+The operating system cannot disable WOL on some machines.
.El
.Pp
.Nm
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.244
diff -u -p -r1.244 ifconfig.c
--- sbin/ifconfig/ifconfig.c 1 Mar 2011 09:37:31 -0000 1.244
+++ sbin/ifconfig/ifconfig.c 12 Mar 2011 23:10:43 -0000
@@ -461,6 +461,8 @@ const struct cmd {
{ "descr", NEXTARG, 0, setifdesc },
{ "-description", 1, 0, unsetifdesc },
{ "-descr", 1, 0, unsetifdesc },
+ { "wol", IFXF_WOL, 0, setifxflags },
+ { "-wol", -IFXF_WOL, 0, setifxflags },
#else /* SMALL */
{ "group", NEXTARG, 0, setignore },
{ "powersave", NEXTARG0, 0, setignore },
@@ -474,6 +476,8 @@ const struct cmd {
{ "-inet6", IFXF_NOINET6, 0, setignore } ,
{ "description", NEXTARG, 0, setignore },
{ "descr", NEXTARG, 0, setignore },
+ { "wol", IFXF_WOL, 0, setignore },
+ { "-wol", -IFXF_WOL, 0, setignore },
#endif /* SMALL */
#if 0
/* XXX `create' special-cased below */
Index: share/man/man4/re.4
===================================================================
RCS file: /cvs/src/share/man/man4/re.4,v
retrieving revision 1.44
diff -u -p -r1.44 re.4
--- share/man/man4/re.4 8 Jul 2010 09:19:11 -0000 1.44
+++ share/man/man4/re.4 13 Mar 2011 10:17:41 -0000
@@ -168,6 +168,10 @@ Force full duplex operation.
Force half duplex operation.
.El
.Pp
+The
+.Nm
+driver supports Wake On LAN.
+.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh SEE ALSO
Index: share/man/man4/vr.4
===================================================================
RCS file: /cvs/src/share/man/man4/vr.4,v
retrieving revision 1.22
diff -u -p -r1.22 vr.4
--- share/man/man4/vr.4 16 Mar 2009 22:47:45 -0000 1.22
+++ share/man/man4/vr.4 13 Mar 2011 10:17:45 -0000
@@ -104,6 +104,11 @@ Force half duplex operation.
.Pp
Note that the 100baseTX media type is only available if supported
by the adapter.
+.Pp
+The
+.Nm
+driver supports Wake On LAN.
+.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh DIAGNOSTICS
Index: sys/dev/ic/re.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/re.c,v
retrieving revision 1.132
diff -u -p -r1.132 re.c
--- sys/dev/ic/re.c 28 Nov 2010 22:13:48 -0000 1.132
+++ sys/dev/ic/re.c 12 Mar 2011 22:44:08 -0000
@@ -194,6 +194,9 @@ void re_disable_hw_im(struct rl_softc *)
void re_disable_sim_im(struct rl_softc *);
void re_config_imtype(struct rl_softc *, int);
void re_setup_intr(struct rl_softc *, int, int);
+#ifndef SMALL_KERNEL
+int re_wol(struct ifnet*, int);
+#endif
#ifdef RE_DIAG
int re_diag(struct rl_softc *);
@@ -1118,6 +1121,11 @@ re_attach(struct rl_softc *sc, const cha
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
#endif
+#ifndef SMALL_KERNEL
+ ifp->if_capabilities |= IFCAP_WOL;
+ ifp->if_wol = re_wol;
+ re_wol(ifp, 0);
+#endif
timeout_set(&sc->timer_handle, re_tick, sc);
/* Take PHY out of power down mode. */
@@ -2335,3 +2343,53 @@ re_setup_intr(struct rl_softc *sc, int e
sc->sc_dev.dv_xname, imtype);
}
}
+
+#ifndef SMALL_KERNEL
+struct re_wolcfg {
+ u_int8_t enable;
+ u_int8_t reg;
+ u_int8_t bit;
+} re_wolcfg[] = {
+ /* Always disable all wake events expect magic packet. */
+ {0, RL_CFG5, RL_CFG5_WOL_UCAST},
+ {0, RL_CFG5, RL_CFG5_WOL_MCAST},
+ {0, RL_CFG5, RL_CFG5_WOL_BCAST},
+ {1, RL_CFG3, RL_CFG3_WOL_MAGIC},
+ {0, RL_CFG3, RL_CFG3_WOL_LINK}
+};
+
+int
+re_wol(struct ifnet *ifp, int enable)
+{
+ struct rl_softc *sc = ifp->if_softc;
+ int i;
+ u_int8_t val;
+
+ if (enable) {
+ if ((CSR_READ_1(sc, RL_CFG1) & RL_CFG1_PME) == 0) {
+ printf("%s: power management is disabled, "
+ "cannot do WOL\n", sc->sc_dev.dv_xname);
+ return (EINVAL);
+ }
+ if ((CSR_READ_1(sc, RL_CFG2) & RL_CFG2_AUXPWR) == 0)
+ printf("%s: no auxiliary power, cannot do WOL from D3 "
+ "(power-off) state\n", sc->sc_dev.dv_xname);
+ }
+
+ /* Temporarily enable write to configuration registers. */
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
+
+ for (i = 0; i < nitems(re_wolcfg); i++) {
+ val = CSR_READ_1(sc, re_wolcfg[i].reg);
+ if (enable && re_wolcfg[i].enable)
+ val |= re_wolcfg[i].bit;
+ else
+ val &= ~re_wolcfg[i].bit;
+ CSR_WRITE_1(sc, re_wolcfg[i].reg, val);
+ }
+
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+
+ return (0);
+}
+#endif
Index: sys/dev/ic/rtl81x9reg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/rtl81x9reg.h,v
retrieving revision 1.72
diff -u -p -r1.72 rtl81x9reg.h
--- sys/dev/ic/rtl81x9reg.h 28 Nov 2010 22:08:59 -0000 1.72
+++ sys/dev/ic/rtl81x9reg.h 8 Dec 2010 12:57:59 -0000
@@ -987,6 +987,7 @@ struct rl_softc {
#define RL_PCI_INTPIN 0x3D
#define RL_PCI_MINGNT 0x3E
#define RL_PCI_MINLAT 0x0F
+#define RL_PCI_PMCSR 0x44
#define RL_PCI_RESETOPT 0x48
#define RL_PCI_EEPROM_DATA 0x4C
@@ -1000,7 +1001,7 @@ struct rl_softc {
#define RL_PSTATE_D1 0x0001
#define RL_PSTATE_D2 0x0002
#define RL_PSTATE_D3 0x0003
-#define RL_PME_EN 0x0010
+#define RL_PME_EN 0x0100
#define RL_PME_STATUS 0x8000
extern int rl_attach(struct rl_softc *);
Index: sys/dev/pci/if_re_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_re_pci.c,v
retrieving revision 1.30
diff -u -p -r1.30 if_re_pci.c
--- sys/dev/pci/if_re_pci.c 7 Sep 2010 16:21:45 -0000 1.30
+++ sys/dev/pci/if_re_pci.c 21 Sep 2010 08:19:42 -0000
@@ -163,6 +163,11 @@ re_pci_attach(struct device *parent, str
pci_conf_write(pc, pa->pa_tag, RL_PCI_INTLINE, irq);
}
+#ifndef SMALL_KERNEL
+ /* Enable power management for wake on lan. */
+ pci_conf_write(pc, pa->pa_tag, RL_PCI_PMCSR, RL_PME_EN);
+#endif
+
/*
* Map control/status registers.
*/
Index: sys/dev/pci/if_vr.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vr.c,v
retrieving revision 1.107
diff -u -p -r1.107 if_vr.c
--- sys/dev/pci/if_vr.c 13 Jan 2011 11:28:14 -0000 1.107
+++ sys/dev/pci/if_vr.c 12 Mar 2011 22:42:47 -0000
@@ -137,6 +137,9 @@ void vr_reset(struct vr_softc *);
int vr_list_rx_init(struct vr_softc *);
void vr_fill_rx_ring(struct vr_softc *);
int vr_list_tx_init(struct vr_softc *);
+#ifndef SMALL_KERNEL
+int vr_wol(struct ifnet *, int);
+#endif
int vr_alloc_mbuf(struct vr_softc *, struct vr_chain_onefrag *);
@@ -643,6 +646,13 @@ vr_attach(struct device *parent, struct
if (sc->vr_quirks & VR_Q_CSUM)
ifp->if_capabilities |= IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4|
IFCAP_CSUM_UDPv4;
+#ifndef SMALL_KERNEL
+ if (sc->vr_revid >= REV_ID_VT3065_A) {
+ ifp->if_capabilities |= IFCAP_WOL;
+ ifp->if_wol = vr_wol;
+ vr_wol(ifp, 0);
+ }
+#endif
/*
* Do MII setup.
@@ -1528,6 +1538,34 @@ vr_stop(struct vr_softc *sc)
bzero((char *)&sc->vr_ldata->vr_tx_list,
sizeof(sc->vr_ldata->vr_tx_list));
}
+
+#ifndef SMALL_KERNEL
+int
+vr_wol(struct ifnet *ifp, int enable)
+{
+ struct vr_softc *sc = ifp->if_softc;
+
+ /* Clear WOL configuration */
+ CSR_WRITE_1(sc, VR_WOLCRCLR, 0xFF);
+
+ /* Clear event status bits. */
+ CSR_WRITE_1(sc, VR_PWRCSRCLR, 0xFF);
+
+ /* Disable PME# assertion upon wake event. */
+ VR_CLRBIT(sc, VR_STICKHW, VR_STICKHW_WOL_ENB);
+ VR_SETBIT(sc, VR_WOLCFGCLR, VR_WOLCFG_PMEOVR);
+
+ if (enable) {
+ VR_SETBIT(sc, VR_WOLCRSET, VR_WOLCR_MAGIC);
+
+ /* Enable PME# assertion upon wake event. */
+ VR_SETBIT(sc, VR_STICKHW, VR_STICKHW_WOL_ENB);
+ VR_SETBIT(sc, VR_WOLCFGSET, VR_WOLCFG_PMEOVR);
+ }
+
+ return (0);
+}
+#endif
int
vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r)
Index: sys/dev/pci/if_vrreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vrreg.h,v
retrieving revision 1.27
diff -u -p -r1.27 if_vrreg.h
--- sys/dev/pci/if_vrreg.h 18 Jun 2009 17:48:15 -0000 1.27
+++ sys/dev/pci/if_vrreg.h 12 Mar 2011 23:00:27 -0000
@@ -285,6 +285,21 @@
#define VR_STICKHW_WOL_STS 0x08
#define VR_STICKHW_LEGWOL_ENB 0x80
+/* Wake on Lan */
+#define VR_WOLCRSET 0xA0
+#define VR_PWRCFGSET 0xA1
+#define VR_WOLCFGSET 0xA3
+#define VR_WOLCRCLR 0xA4
+#define VR_PWRCFGCLR 0xA5
+#define VR_WOLCFGCLR 0xA7
+#define VR_PWRCSRSET 0xA8
+#define VR_PWRCSRCLR 0xAC
+#define VR_WOLCR_UCAST 0x10
+#define VR_WOLCR_MAGIC 0x20
+#define VR_WOLCR_LINKON 0x40
+#define VR_WOLCR_LINKOFF 0x80
+#define VR_WOLCFG_PMEOVR 0x80
+
/*
* BCR0 register bits. (At least for the VT6102 chip.)
*/
Index: sys/net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.233
diff -u -p -r1.233 if.c
--- sys/net/if.c 25 Jan 2011 05:44:05 -0000 1.233
+++ sys/net/if.c 13 Mar 2011 10:35:04 -0000
@@ -1357,6 +1357,31 @@ ifioctl(struct socket *so, u_long cmd, c
}
#endif
+#ifndef SMALL_KERNEL
+ if (ifp->if_capabilities & IFCAP_WOL) {
+ if (ISSET(ifr->ifr_flags, IFXF_WOL) &&
+ !ISSET(ifp->if_xflags, IFXF_WOL)) {
+ int s = splnet();
+ ifp->if_xflags |= IFXF_WOL;
+ error = ifp->if_wol(ifp, 1);
+ splx(s);
+ if (error)
+ return (error);
+ }
+ if (ISSET(ifp->if_xflags, IFXF_WOL) &&
+ !ISSET(ifr->ifr_flags, IFXF_WOL)) {
+ int s = splnet();
+ ifp->if_xflags &= ~IFXF_WOL;
+ error = ifp->if_wol(ifp, 0);
+ splx(s);
+ if (error)
+ return (error);
+ }
+ } else if (ISSET(ifr->ifr_flags, IFXF_WOL)) {
+ ifr->ifr_flags &= ~IFXF_WOL;
+ error = ENOTSUP;
+ }
+#endif
ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) |
(ifr->ifr_flags & ~IFXF_CANTCHANGE);
Index: sys/net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.121
diff -u -p -r1.121 if.h
--- sys/net/if.h 17 Nov 2010 18:51:57 -0000 1.121
+++ sys/net/if.h 12 Mar 2011 22:24:52 -0000
@@ -278,6 +278,7 @@ struct ifnet { /* and the
entries */
int (*if_stop)(struct ifnet *, int);
/* timer routine */
void (*if_watchdog)(struct ifnet *);
+ int (*if_wol)(struct ifnet *, int);
struct ifaltq if_snd; /* output queue (includes altq) */
struct sockaddr_dl *if_sadl; /* pointer to our sockaddr_dl */
@@ -329,6 +330,7 @@ struct ifnet { /* and the
entries */
#define IFXF_NOINET6 0x2 /* don't do inet6 */
#define IFXF_INET6_PRIVACY 0x4 /* autoconf privacy
extension */
#define IFXF_MPLS 0x8 /* supports MPLS */
+#define IFXF_WOL 0x10 /* wake on lan enabled
*/
#define IFXF_CANTCHANGE \
(IFXF_TXREADY)
@@ -352,6 +354,7 @@ struct ifnet { /* and the
entries */
#define IFCAP_CSUM_UDPv6 0x00000100 /* can do IPv6/UDP
checksums */
#define IFCAP_CSUM_TCPv4_Rx 0x00000200 /* can do IPv4/TCP (Rx
only) */
#define IFCAP_CSUM_UDPv4_Rx 0x00000400 /* can do IPv4/UDP (Rx
only) */
+#define IFCAP_WOL 0x00008000 /* can do wake on lan */
/*
* Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)