From 87fe8c7aca6fd7c9582d8decbc2a915e887318e4 Mon Sep 17 00:00:00 2001 From: bouyer Date: Tue, 6 Jan 2015 15:39:54 +0000 Subject: [PATCH] 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. --- share/man/man9/sysmon_pswitch.9 | 5 ++- sys/dev/pci/if_wpi.c | 74 +++++++++++++++++++++++++++++++-- sys/dev/pci/if_wpivar.h | 11 ++++- sys/dev/sysmon/sysmon_power.c | 5 ++- sys/sys/power.h | 7 +++- 5 files changed, 93 insertions(+), 9 deletions(-) diff --git a/share/man/man9/sysmon_pswitch.9 b/share/man/man9/sysmon_pswitch.9 index b1876f662f33..1d6f71d9e8f6 100644 --- a/share/man/man9/sysmon_pswitch.9 +++ b/share/man/man9/sysmon_pswitch.9 @@ -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.6 2015/01/06 15:39:54 bouyer 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 diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index 594897b8c7d3..8b4a8b5b134f 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $ */ +/* $NetBSD: if_wpi.c,v 1.70 2015/01/06 15:39:54 bouyer Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,7 +18,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.70 2015/01/06 15:39:54 bouyer Exp $"); /* * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters. @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $"); #include #include #include +#include #include #include @@ -48,6 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $"); #include #include +#include + #include #include #include @@ -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, device_t self, void *aux) 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 __unused) 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 __unused) 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 */ @@ -3276,6 +3306,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 +3336,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 +3383,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); + } +} + diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h index 23c611d38e2b..6e16eaed3a3e 100644 --- a/sys/dev/pci/if_wpivar.h +++ b/sys/dev/pci/if_wpivar.h @@ -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.19 2015/01/06 15:39:54 bouyer 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; }; diff --git a/sys/dev/sysmon/sysmon_power.c b/sys/dev/sysmon/sysmon_power.c index 33828dd14f7a..4873d2647790 100644 --- a/sys/dev/sysmon/sysmon_power.c +++ b/sys/dev/sysmon/sysmon_power.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_power.c,v 1.48 2014/11/21 23:28:57 joerg Exp $ */ +/* $NetBSD: sysmon_power.c,v 1.49 2015/01/06 15:39:54 bouyer Exp $ */ /*- * Copyright (c) 2007 Juan Romero Pardines. @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.48 2014/11/21 23:28:57 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.49 2015/01/06 15:39:54 bouyer Exp $"); #include "opt_compat_netbsd.h" #include @@ -121,6 +121,7 @@ static const struct power_event_description pswitch_type_desc[] = { { PSWITCH_TYPE_RESET, "reset_button" }, { PSWITCH_TYPE_ACADAPTER, "acadapter" }, { PSWITCH_TYPE_HOTKEY, "hotkey_button" }, + { PSWITCH_TYPE_RADIO, "radio_button" }, { -1, NULL } }; diff --git a/sys/sys/power.h b/sys/sys/power.h index b9737e67e930..ba11261cedcd 100644 --- a/sys/sys/power.h +++ b/sys/sys/power.h @@ -1,4 +1,4 @@ -/* $NetBSD: power.h,v 1.19 2013/03/30 19:05:20 christos Exp $ */ +/* $NetBSD: power.h,v 1.20 2015/01/06 15:39:54 bouyer 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 */