Module Name: src Committed By: snj Date: Mon Jan 12 21:15:12 UTC 2015
Modified Files: src/share/man/man9 [netbsd-7]: sysmon_pswitch.9 src/sys/dev/pci [netbsd-7]: if_wpi.c if_wpivar.h src/sys/dev/sysmon [netbsd-7]: sysmon_power.c src/sys/sys [netbsd-7]: power.h Log Message: Pull up following revision(s) (requested by bouyer in ticket #415): share/man/man9/sysmon_pswitch.9: revision 1.6 sys/dev/pci/if_wpi.c: revision 1.70, 1.71 sys/dev/pci/if_wpivar.h: revision 1.19 sys/dev/sysmon/sysmon_power.c: revision 1.49 sys/sys/power.h: revision 1.20 As proposed on tech-net@, introduce a new switch type, PSWITCH_TYPE_RADIO, to be used to report to userland hardware radio switch changes. powerd(8) will call a "radio_button" script to handle the event. This script can e.g. start or stop wpa_supplicant. Update wpi(4) to report PSWITCH_TYPE_RADIO events to sysmon. -- Take sc_rsw_mtx before calling wpi_getrfkill() from wpi_init(), Problem reported and patch tested by chris at chriswareham.net To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.5.4.1 src/share/man/man9/sysmon_pswitch.9 cvs rdiff -u -r1.68.2.1 -r1.68.2.2 src/sys/dev/pci/if_wpi.c cvs rdiff -u -r1.18 -r1.18.2.1 src/sys/dev/pci/if_wpivar.h cvs rdiff -u -r1.47 -r1.47.2.1 src/sys/dev/sysmon/sysmon_power.c cvs rdiff -u -r1.19 -r1.19.10.1 src/sys/sys/power.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man9/sysmon_pswitch.9 diff -u src/share/man/man9/sysmon_pswitch.9:1.5 src/share/man/man9/sysmon_pswitch.9:1.5.4.1 --- src/share/man/man9/sysmon_pswitch.9:1.5 Tue Mar 18 18:20:40 2014 +++ src/share/man/man9/sysmon_pswitch.9 Mon Jan 12 21:15:12 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: sysmon_pswitch.9,v 1.5 2014/03/18 18:20:40 riastradh Exp $ +.\" $NetBSD: sysmon_pswitch.9,v 1.5.4.1 2015/01/12 21:15:12 snj Exp $ .\" .\" Copyright (c) 2010 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 26, 2010 +.Dd January 6, 2015 .Dt SYSMON_PSWITCH 9 .Os .Sh NAME @@ -75,6 +75,7 @@ The following types are defined: .It PSWITCH_TYPE_RESET .It PSWITCH_TYPE_ACADAPTER .It PSWITCH_TYPE_HOTKEY +.It PSWITCH_TYPE_RADIO .El .Pp If the type is Index: src/sys/dev/pci/if_wpi.c diff -u src/sys/dev/pci/if_wpi.c:1.68.2.1 src/sys/dev/pci/if_wpi.c:1.68.2.2 --- src/sys/dev/pci/if_wpi.c:1.68.2.1 Sun Dec 21 19:32:48 2014 +++ src/sys/dev/pci/if_wpi.c Mon Jan 12 21:15:12 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpi.c,v 1.68.2.1 2014/12/21 19:32:48 snj Exp $ */ +/* $NetBSD: if_wpi.c,v 1.68.2.2 2015/01/12 21:15:12 snj Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.68.2.1 2014/12/21 19:32:48 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.68.2.2 2015/01/12 21:15:12 snj Exp $"); /* * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters. @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1 #include <sys/kauth.h> #include <sys/callout.h> #include <sys/proc.h> +#include <sys/kthread.h> #include <sys/bus.h> #include <machine/endian.h> @@ -48,6 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1 #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> +#include <dev/sysmon/sysmonvar.h> + #include <net/bpf.h> #include <net/if.h> #include <net/if_arp.h> @@ -153,6 +156,7 @@ static void wpi_stop(struct ifnet *, int static bool wpi_resume(device_t, const pmf_qual_t *); static int wpi_getrfkill(struct wpi_softc *); static void wpi_sysctlattach(struct wpi_softc *); +static void wpi_rsw_thread(void *); #ifdef WPI_DEBUG #define DPRINTF(x) do { if (wpi_debug > 0) printf x; } while (0) @@ -214,6 +218,22 @@ wpi_attach(device_t parent __unused, dev sc->sc_pct = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; + sc->sc_rsw_status = WPI_RSW_UNKNOWN; + sc->sc_rsw.smpsw_name = device_xname(self); + sc->sc_rsw.smpsw_type = PSWITCH_TYPE_RADIO; + error = sysmon_pswitch_register(&sc->sc_rsw); + if (error) { + aprint_error_dev(self, + "unable to register radio switch with sysmon\n"); + return; + } + mutex_init(&sc->sc_rsw_mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&sc->sc_rsw_cv, "wpirsw"); + if (kthread_create(PRI_NONE, 0, NULL, + wpi_rsw_thread, sc, &sc->sc_rsw_lwp, "%s", device_xname(self))) { + aprint_error_dev(self, "couldn't create switch thread\n"); + } + callout_init(&sc->calib_to, 0); callout_setfunc(&sc->calib_to, wpi_calib_timeout, sc); @@ -411,6 +431,13 @@ wpi_detach(device_t self, int flags __un pci_intr_disestablish(sc->sc_pct, sc->sc_ih); sc->sc_ih = NULL; } + mutex_enter(&sc->sc_rsw_mtx); + sc->sc_dying = 1; + cv_signal(&sc->sc_rsw_cv); + while (sc->sc_rsw_lwp != NULL) + cv_wait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx); + mutex_exit(&sc->sc_rsw_mtx); + sysmon_pswitch_unregister(&sc->sc_rsw); bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); @@ -418,7 +445,8 @@ wpi_detach(device_t self, int flags __un sc->fw_used = false; wpi_release_firmware(); } - + cv_destroy(&sc->sc_rsw_cv); + mutex_destroy(&sc->sc_rsw_mtx); return 0; } @@ -1688,6 +1716,8 @@ wpi_notif_intr(struct wpi_softc *sc) if (le32toh(*status) & 1) { /* the radio button has to be pushed */ + /* wake up thread to signal powerd */ + cv_signal(&sc->sc_rsw_cv); aprint_error_dev(sc->sc_dev, "Radio transmitter is off\n"); /* turn the interface down */ @@ -3167,13 +3197,16 @@ wpi_init(struct ifnet *ifp) goto fail1; /* Check the status of the radio switch */ + mutex_enter(&sc->sc_rsw_mtx); if (wpi_getrfkill(sc)) { + mutex_exit(&sc->sc_rsw_mtx); aprint_error_dev(sc->sc_dev, "radio is disabled by hardware switch\n"); ifp->if_flags &= ~IFF_UP; error = EBUSY; goto fail1; } + mutex_exit(&sc->sc_rsw_mtx); /* wait for thermal sensors to calibrate */ for (ntries = 0; ntries < 1000; ntries++) { @@ -3276,6 +3309,23 @@ wpi_getrfkill(struct wpi_softc *sc) tmp = wpi_mem_read(sc, WPI_MEM_RFKILL); wpi_mem_unlock(sc); + KASSERT(mutex_owned(&sc->sc_rsw_mtx)); + if (tmp & 0x01) { + /* switch is on */ + if (sc->sc_rsw_status != WPI_RSW_ON) { + sc->sc_rsw_status = WPI_RSW_ON; + sysmon_pswitch_event(&sc->sc_rsw, + PSWITCH_EVENT_PRESSED); + } + } else { + /* switch is off */ + if (sc->sc_rsw_status != WPI_RSW_OFF) { + sc->sc_rsw_status = WPI_RSW_OFF; + sysmon_pswitch_event(&sc->sc_rsw, + PSWITCH_EVENT_RELEASED); + } + } + return !(tmp & 0x01); } @@ -3289,7 +3339,9 @@ wpi_sysctl_radio(SYSCTLFN_ARGS) node = *rnode; sc = (struct wpi_softc *)node.sysctl_data; + mutex_enter(&sc->sc_rsw_mtx); val = !wpi_getrfkill(sc); + mutex_exit(&sc->sc_rsw_mtx); node.sysctl_data = &val; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -3334,3 +3386,22 @@ wpi_sysctlattach(struct wpi_softc *sc) err: aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } + +static void +wpi_rsw_thread(void *arg) +{ + struct wpi_softc *sc = (struct wpi_softc *)arg; + + mutex_enter(&sc->sc_rsw_mtx); + for (;;) { + cv_timedwait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx, hz); + if (sc->sc_dying) { + sc->sc_rsw_lwp = NULL; + cv_broadcast(&sc->sc_rsw_cv); + mutex_exit(&sc->sc_rsw_mtx); + kthread_exit(0); + } + wpi_getrfkill(sc); + } +} + Index: src/sys/dev/pci/if_wpivar.h diff -u src/sys/dev/pci/if_wpivar.h:1.18 src/sys/dev/pci/if_wpivar.h:1.18.2.1 --- src/sys/dev/pci/if_wpivar.h:1.18 Sat Aug 9 15:07:06 2014 +++ src/sys/dev/pci/if_wpivar.h Mon Jan 12 21:15:12 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpivar.h,v 1.18 2014/08/09 15:07:06 jmcneill Exp $ */ +/* $NetBSD: if_wpivar.h,v 1.18.2.1 2015/01/12 21:15:12 snj Exp $ */ /*- * Copyright (c) 2006 @@ -187,4 +187,13 @@ struct wpi_softc { bool is_scanning; struct sysctllog *sc_sysctllog; + struct sysmon_pswitch sc_rsw; /* for radio switch events */ + int sc_rsw_status; +#define WPI_RSW_UNKNOWN 0 +#define WPI_RSW_OFF 1 +#define WPI_RSW_ON 2 + struct lwp *sc_rsw_lwp; + struct kmutex sc_rsw_mtx; + struct kcondvar sc_rsw_cv; + int sc_dying; }; Index: src/sys/dev/sysmon/sysmon_power.c diff -u src/sys/dev/sysmon/sysmon_power.c:1.47 src/sys/dev/sysmon/sysmon_power.c:1.47.2.1 --- src/sys/dev/sysmon/sysmon_power.c:1.47 Sun Aug 10 16:44:36 2014 +++ src/sys/dev/sysmon/sysmon_power.c Mon Jan 12 21:15:12 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_power.c,v 1.47 2014/08/10 16:44:36 tls Exp $ */ +/* $NetBSD: sysmon_power.c,v 1.47.2.1 2015/01/12 21:15:12 snj Exp $ */ /*- * Copyright (c) 2007 Juan Romero Pardines. @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.47 2014/08/10 16:44:36 tls Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.47.2.1 2015/01/12 21:15:12 snj Exp $"); #include "opt_compat_netbsd.h" #include <sys/param.h> @@ -121,6 +121,7 @@ static const struct power_event_descript { PSWITCH_TYPE_RESET, "reset_button" }, { PSWITCH_TYPE_ACADAPTER, "acadapter" }, { PSWITCH_TYPE_HOTKEY, "hotkey_button" }, + { PSWITCH_TYPE_RADIO, "radio_button" }, { -1, NULL } }; Index: src/sys/sys/power.h diff -u src/sys/sys/power.h:1.19 src/sys/sys/power.h:1.19.10.1 --- src/sys/sys/power.h:1.19 Sat Mar 30 19:05:20 2013 +++ src/sys/sys/power.h Mon Jan 12 21:15:12 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: power.h,v 1.19 2013/03/30 19:05:20 christos Exp $ */ +/* $NetBSD: power.h,v 1.19.10.1 2015/01/12 21:15:12 snj Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -83,6 +83,10 @@ * of switch has state. We know if it is open * or closed. * + * Radio switch This is e.g. the switch of the transmitter + * of a wifi interface. We know if it is + * on or off. + * */ #define PSWITCH_TYPE_POWER 0 /* power button */ @@ -111,6 +115,7 @@ #define PSWITCH_HK_VOLUME_DOWN "volume-down" #define PSWITCH_HK_VOLUME_MUTE "volume-mute" #endif /* THINKPAD_NORMAL_HOTKEYS */ +#define PSWITCH_TYPE_RADIO 6 /* radio switch */ #define PSWITCH_EVENT_PRESSED 0 /* button pressed, lid closed, AC off */ #define PSWITCH_EVENT_RELEASED 1 /* button released, lid open, AC on */