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 */

Reply via email to