Author: avg
Date: Thu Jun  4 13:03:13 2020
New Revision: 361786
URL: https://svnweb.freebsd.org/changeset/base/361786

Log:
  MFC r361273: 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.

Modified:
  stable/12/sys/dev/iwm/if_iwm.c
  stable/12/sys/dev/iwm/if_iwmvar.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/iwm/if_iwm.c
==============================================================================
--- stable/12/sys/dev/iwm/if_iwm.c      Thu Jun  4 12:23:15 2020        
(r361785)
+++ stable/12/sys/dev/iwm/if_iwm.c      Thu Jun  4 13:03:13 2020        
(r361786)
@@ -5059,20 +5059,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
  */
@@ -5809,12 +5837,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);
        }
 
        /*
@@ -6019,7 +6042,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;
@@ -6585,6 +6618,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: stable/12/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- stable/12/sys/dev/iwm/if_iwmvar.h   Thu Jun  4 12:23:15 2020        
(r361785)
+++ stable/12/sys/dev/iwm/if_iwmvar.h   Thu Jun  4 13:03:13 2020        
(r361786)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to