Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 May 2020 08:15:09 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r361273 - head/sys/dev/iwm
Message-ID:  <202005200815.04K8F95i009854@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Wed May 20 08:15:09 2020
New Revision: 361273
URL: https://svnweb.freebsd.org/changeset/base/361273

Log:
  iwm: improve rfkill handling
  
  Previously the driver handled the bit within itself, but did not expose
  the state change to net80211 and interface layers.
  This change uses net80211 KPI for rfkill signaling.
  The code is modeled after similar code in iwn and wpi.
  
  Reviewed by:	adrian
  MFC after:	2 weeks
  Differential Revision: https://reviews.freebsd.org/D24923

Modified:
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwmvar.h

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Wed May 20 04:16:13 2020	(r361272)
+++ head/sys/dev/iwm/if_iwm.c	Wed May 20 08:15:09 2020	(r361273)
@@ -5064,20 +5064,48 @@ iwm_parent(struct ieee80211com *ic)
 {
 	struct iwm_softc *sc = ic->ic_softc;
 	int startall = 0;
+	int rfkill = 0;
 
 	IWM_LOCK(sc);
 	if (ic->ic_nrunning > 0) {
 		if (!(sc->sc_flags & IWM_FLAG_HW_INITED)) {
 			iwm_init(sc);
-			startall = 1;
+			rfkill = iwm_check_rfkill(sc);
+			if (!rfkill)
+				startall = 1;
 		}
 	} else if (sc->sc_flags & IWM_FLAG_HW_INITED)
 		iwm_stop(sc);
 	IWM_UNLOCK(sc);
 	if (startall)
 		ieee80211_start_all(ic);
+	else if (rfkill)
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task);
 }
 
+static void
+iwm_rftoggle_task(void *arg, int npending __unused)
+{
+	struct iwm_softc *sc = arg;
+	struct ieee80211com *ic = &sc->sc_ic;
+	int rfkill;
+
+	IWM_LOCK(sc);
+	rfkill = iwm_check_rfkill(sc);
+	IWM_UNLOCK(sc);
+	if (rfkill) {
+		device_printf(sc->sc_dev,
+		    "%s: rfkill switch, disabling interface\n", __func__);
+		ieee80211_suspend_all(ic);
+		ieee80211_notify_radio(ic, 0);
+	} else {
+		device_printf(sc->sc_dev,
+		    "%s: rfkill cleared, re-enabling interface\n", __func__);
+		ieee80211_resume_all(ic);
+		ieee80211_notify_radio(ic, 1);
+	}
+}
+
 /*
  * The interrupt side of things
  */
@@ -5814,12 +5842,7 @@ iwm_intr(void *arg)
 
 	if (r1 & IWM_CSR_INT_BIT_RF_KILL) {
 		handled |= IWM_CSR_INT_BIT_RF_KILL;
-		if (iwm_check_rfkill(sc)) {
-			device_printf(sc->sc_dev,
-			    "%s: rfkill switch, disabling interface\n",
-			    __func__);
-			iwm_stop(sc);
-		}
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task);
 	}
 
 	/*
@@ -6024,7 +6047,17 @@ iwm_attach(device_t dev)
 	callout_init_mtx(&sc->sc_watchdog_to, &sc->sc_mtx, 0);
 	callout_init_mtx(&sc->sc_led_blink_to, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_es_task, 0, iwm_endscan_cb, sc);
+	TASK_INIT(&sc->sc_rftoggle_task, 0, iwm_rftoggle_task, sc);
 
+	sc->sc_tq = taskqueue_create("iwm_taskq", M_WAITOK,
+	    taskqueue_thread_enqueue, &sc->sc_tq);
+	error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwm_taskq");
+	if (error != 0) {
+		device_printf(dev, "can't start taskq thread, error %d\n",
+		    error);
+		goto fail;
+	}
+
 	error = iwm_dev_check(dev);
 	if (error != 0)
 		goto fail;
@@ -6590,6 +6623,8 @@ iwm_detach_local(struct iwm_softc *sc, int do_net80211
 		ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task);
 	}
 	iwm_stop_device(sc);
+	taskqueue_drain_all(sc->sc_tq);
+	taskqueue_free(sc->sc_tq);
 	if (do_net80211) {
 		IWM_LOCK(sc);
 		iwm_xmit_queue_drain(sc);

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Wed May 20 04:16:13 2020	(r361272)
+++ head/sys/dev/iwm/if_iwmvar.h	Wed May 20 08:15:09 2020	(r361273)
@@ -499,7 +499,9 @@ struct iwm_softc {
 	uint8_t			sc_cmd_resp[IWM_CMD_RESP_MAX];
 	int			sc_wantresp;
 
+	struct taskqueue	*sc_tq;
 	struct task		sc_es_task;
+	struct task		sc_rftoggle_task;
 
 	struct iwm_rx_phy_info	sc_last_phy_info;
 	int			sc_ampdu_ref;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202005200815.04K8F95i009854>