The "link quality" (LQ) command for iwm firmware is used to tell the
firmware about our Tx rate selection decisions, among other things.

The driver currently avoids sending this command directly from interrupt
context. Instead it schedules a task which will send the command.

The driver usually defers to a task when it needs to wait for a
response to the command from the firmware, and runs in a context
where sleeping (i.e. waiting) isn't allowed.

The LQ command requires no actual response handling, and works just fine
when sent asynchrounously. So get rid of the task and just send the LQ
command directly from interrupt context.

This simplifies the driver a bit and means we have less potential delay
between our decision to use a new Tx rate and getting the firmware's
rate retry table updated for our new Tx rate.

ok?

diff 960b1fc5c6485d1b9e9fe9d73b34986dd0a3a942 
50417a34cf53a2cdd32a025c586789525bfa9d00
blob - c6963275801e8f8b962721bcd81fd3b1a541b46f (mode 644)
blob + cb582fd301f6a85569c578a83e49daeffa087724 (mode 600)
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -453,8 +453,7 @@ int iwm_run(struct iwm_softc *);
 int    iwm_run_stop(struct iwm_softc *);
 struct ieee80211_node *iwm_node_alloc(struct ieee80211com *);
 void   iwm_calib_timeout(void *);
-void   iwm_setrates_task(void *);
-void   iwm_setrates(struct iwm_node *);
+void   iwm_setrates(struct iwm_node *, int);
 int    iwm_media_change(struct ifnet *);
 void   iwm_newstate_task(void *);
 int    iwm_newstate(struct ieee80211com *, enum ieee80211_state, int);
@@ -4206,7 +4205,7 @@ iwm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_
                        best_mcs = ieee80211_mira_get_best_mcs(&in->in_mn);
                        if (best_mcs != in->chosen_txmcs) {
                                in->chosen_txmcs = best_mcs;
-                               iwm_add_task(sc, systq, &sc->setrates_task);
+                               iwm_setrates(in, 1);
                        }
 
                        /* Fall back to CCK rates if MCS 0 is failing. */
@@ -6736,7 +6735,7 @@ iwm_run(struct iwm_softc *sc)
        in->in_ni.ni_txmcs = 0;
        in->chosen_txrate = 0;
        in->chosen_txmcs = 0;
-       iwm_setrates(in);
+       iwm_setrates(in, 0);
 
        timeout_add_msec(&sc->sc_calib_to, 500);
        iwm_led_enable(sc);
@@ -6817,7 +6816,7 @@ iwm_calib_timeout(void *arg)
                 */
                if (ni->ni_txrate != in->chosen_txrate) {
                        in->chosen_txrate = ni->ni_txrate;
-                       iwm_add_task(sc, systq, &sc->setrates_task);
+                       iwm_setrates(in, 1);
                }
                if (in->ht_force_cck) {
                        struct ieee80211_rateset *rs = &ni->ni_rates;
@@ -6834,28 +6833,8 @@ iwm_calib_timeout(void *arg)
 }
 
 void
-iwm_setrates_task(void *arg)
+iwm_setrates(struct iwm_node *in, int async)
 {
-       struct iwm_softc *sc = arg;
-       struct ieee80211com *ic = &sc->sc_ic;
-       struct iwm_node *in = (struct iwm_node *)ic->ic_bss;
-       int s = splnet();
-
-       if (sc->sc_flags & IWM_FLAG_SHUTDOWN) {
-               refcnt_rele_wake(&sc->task_refs);
-               splx(s);
-               return;
-       }
-
-       /* Update rates table based on new TX rate determined by AMRR. */
-       iwm_setrates(in);
-       refcnt_rele_wake(&sc->task_refs);
-       splx(s);
-}
-
-void
-iwm_setrates(struct iwm_node *in)
-{
        struct ieee80211_node *ni = &in->in_ni;
        struct ieee80211com *ic = ni->ni_ic;
        struct iwm_softc *sc = IC2IFP(ic)->if_softc;
@@ -6867,6 +6846,8 @@ iwm_setrates(struct iwm_node *in)
                .len = { sizeof(lqcmd), },
        };
 
+       cmd.flags = async ? IWM_CMD_ASYNC : 0;
+
        memset(&lqcmd, 0, sizeof(lqcmd));
        lqcmd.sta_id = IWM_STATION_ID;
 
@@ -7111,7 +7092,6 @@ iwm_newstate(struct ieee80211com *ic, enum ieee80211_s
                ieee80211_mira_cancel_timeouts(&in->in_mn);
                iwm_del_task(sc, systq, &sc->ba_task);
                iwm_del_task(sc, systq, &sc->htprot_task);
-               iwm_del_task(sc, systq, &sc->setrates_task);
        }
 
        sc->ns_nstate = nstate;
@@ -7885,7 +7865,6 @@ iwm_stop(struct ifnet *ifp)
        /* Cancel scheduled tasks and let any stale tasks finish up. */
        task_del(systq, &sc->init_task);
        iwm_del_task(sc, sc->sc_nswq, &sc->newstate_task);
-       iwm_del_task(sc, systq, &sc->setrates_task);
        iwm_del_task(sc, systq, &sc->ba_task);
        iwm_del_task(sc, systq, &sc->htprot_task);
        KASSERT(sc->task_refs.refs >= 1);
@@ -9313,7 +9292,6 @@ iwm_attach(struct device *parent, struct device *self,
        timeout_set(&sc->sc_led_blink_to, iwm_led_blink_timeout, sc);
        task_set(&sc->init_task, iwm_init_task, sc);
        task_set(&sc->newstate_task, iwm_newstate_task, sc);
-       task_set(&sc->setrates_task, iwm_setrates_task, sc);
        task_set(&sc->ba_task, iwm_ba_task, sc);
        task_set(&sc->htprot_task, iwm_htprot_task, sc);
 
blob - ec579e3f75095d6c28ea14293bd75d257971c66f
blob + 5034497e1d10a9124f4f254105f251955e9cd534
--- sys/dev/pci/if_iwmvar.h
+++ sys/dev/pci/if_iwmvar.h
@@ -375,7 +375,6 @@ struct iwm_softc {
        struct task             init_task; /* NB: not reference-counted */
        struct refcnt           task_refs;
        struct task             newstate_task;
-       struct task             setrates_task;
        enum ieee80211_state    ns_nstate;
        int                     ns_arg;
 

Reply via email to