I'd like to know if this diff helps with iwm(4) performance issues
some people have been reporting.

This is not done yet and some details don't really make sense, especially
the #if 0 hiding of what should be correct code -- yet, enabling that code
makes the problem come back.

But hopefully this is generally going in the right direction.

Thank you, Edward Wandasiewicz, for pointing out that reverting if_iwm.c
r1.85 restores performance. That was the door to this rabbit hole :-)

Index: dev/pci/if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.132
diff -u -p -r1.132 if_iwm.c
--- dev/pci/if_iwm.c    12 Sep 2016 10:18:26 -0000      1.132
+++ dev/pci/if_iwm.c    20 Sep 2016 00:17:38 -0000
@@ -402,10 +402,8 @@ int        iwm_config_umac_scan(struct iwm_soft
 int    iwm_umac_scan(struct iwm_softc *);
 void   iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);
 void   iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
-           struct iwm_mac_ctx_cmd *, uint32_t);
-void   iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *, struct iwm_node *,
-           struct iwm_mac_data_sta *, int);
-int    iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t);
+           struct iwm_mac_ctx_cmd *, uint32_t, int);
+int    iwm_mac_ctxt_cmd(struct iwm_softc *, struct iwm_node *, uint32_t, int);
 int    iwm_update_quotas(struct iwm_softc *, struct iwm_node *);
 int    iwm_auth(struct iwm_softc *);
 int    iwm_assoc(struct iwm_softc *);
@@ -2428,7 +2426,7 @@ iwm_htprot_task(void *arg)
        int err;
 
        /* This call updates HT protection based on in->in_ni.ni_htop1. */
-       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
+       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
        if (err)
                printf("%s: could not change HT protection: error %d\n",
                    DEVNAME(sc), err);
@@ -4203,14 +4201,15 @@ void
 iwm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
     struct iwm_mac_power_cmd *cmd)
 {
-       struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_node *ni = &in->in_ni;
-       int dtimper, dtimper_msec;
-       int keep_alive;
+       int dtim_period, dtim_msec, keep_alive;
 
        cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(in->in_id,
            in->in_color));
-       dtimper = ic->ic_dtim_period ?: 1;
+       if (ni->ni_dtimperiod)
+               dtim_period = ni->ni_dtimperiod;
+       else
+               dtim_period = 1;
 
        /*
         * Regardless of power management state the driver must set
@@ -4218,9 +4217,8 @@ iwm_power_build_cmd(struct iwm_softc *sc
         * immediately after association. Check that keep alive period
         * is at least 3 * DTIM.
         */
-       dtimper_msec = dtimper * ni->ni_intval;
-       keep_alive
-           = MAX(3 * dtimper_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
+       dtim_msec = dtim_period * ni->ni_intval * IEEE80211_DUR_TU;
+       keep_alive = MAX(3 * dtim_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
        keep_alive = roundup(keep_alive, 1000) / 1000;
        cmd->keep_alive_seconds = htole16(keep_alive);
 }
@@ -4249,14 +4247,12 @@ iwm_power_mac_update_mode(struct iwm_sof
 int
 iwm_power_update_device(struct iwm_softc *sc)
 {
-       struct iwm_device_power_cmd cmd = {
-               .flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
-       };
+       struct iwm_device_power_cmd cmd;
 
        if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
                return 0;
 
-       cmd.flags |= htole16(IWM_DEVICE_POWER_FLAGS_CAM_MSK);
+       cmd.flags = htole16(IWM_DEVICE_POWER_FLAGS_CAM_MSK);
 
        return iwm_send_cmd_pdu(sc,
            IWM_POWER_TABLE_CMD, 0, sizeof(cmd), &cmd);
@@ -4975,7 +4971,7 @@ iwm_ack_rates(struct iwm_softc *sc, stru
 
 void
 iwm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
-    struct iwm_mac_ctx_cmd *cmd, uint32_t action)
+    struct iwm_mac_ctx_cmd *cmd, uint32_t action, int assoc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_node *ni = ic->ic_bss;
@@ -4987,14 +4983,17 @@ iwm_mac_ctxt_cmd_common(struct iwm_softc
        cmd->action = htole32(action);
 
        cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
-       cmd->tsf_id = htole32(in->in_tsfid);
+       cmd->tsf_id = htole32(IWM_TSF_ID_A);
 
        IEEE80211_ADDR_COPY(cmd->node_addr, ic->ic_myaddr);
-       if (in->in_assoc) {
+
+#if 0 /* For some reason setting our BSSID here causes Rx problems. */
+       if (assoc)
                IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
-       } else {
+       else
+#endif
                IEEE80211_ADDR_COPY(cmd->bssid_addr, etherbroadcastaddr);
-       }
+
        iwm_ack_rates(sc, in, &cck_ack_rates, &ofdm_ack_rates);
        cmd->cck_rates = htole32(cck_ack_rates);
        cmd->ofdm_rates = htole32(ofdm_ack_rates);
@@ -5040,47 +5039,44 @@ iwm_mac_ctxt_cmd_common(struct iwm_softc
        if (ic->ic_flags & IEEE80211_F_USEPROT)
                cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT);
 
-       cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP);
-}
-
-void
-iwm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,
-    struct iwm_mac_data_sta *ctxt_sta, int force_assoc_off)
-{
-       struct ieee80211_node *ni = &in->in_ni;
-       struct ieee80211com *ic = &sc->sc_ic;
-
-       ctxt_sta->is_assoc = htole32(0);
-       ctxt_sta->bi = htole32(ni->ni_intval);
-       ctxt_sta->bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
-       ctxt_sta->dtim_interval = htole32(ni->ni_intval * ic->ic_dtim_period);
-       ctxt_sta->dtim_reciprocal =
-           htole32(iwm_reciprocal(ni->ni_intval * ic->ic_dtim_period));
-
-       /* 10 = CONN_MAX_LISTEN_INTERVAL */
-       ctxt_sta->listen_interval = htole32(10);
-       ctxt_sta->assoc_id = htole32(ni->ni_associd);
+       cmd->filter_flags |= htole32(IWM_MAC_FILTER_ACCEPT_GRP);
 }
 
 int
-iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
+iwm_mac_ctxt_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action,
+    int assoc)
 {
+       struct ieee80211_node *ni = &in->in_ni;
        struct iwm_mac_ctx_cmd cmd;
 
        memset(&cmd, 0, sizeof(cmd));
 
-       iwm_mac_ctxt_cmd_common(sc, in, &cmd, action);
+       iwm_mac_ctxt_cmd_common(sc, in, &cmd, action, assoc);
 
-       /* Allow beacons to pass through as long as we are not associated or we
-        * do not have dtim period information */
-       if (!in->in_assoc || !sc->sc_ic.ic_dtim_period)
+       /* Allow beacons to pass through as long as we are not associated
+        * or we do not have dtim period information */
+       if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod) {
                cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
-       else
-               cmd.filter_flags &= ~htole32(IWM_MAC_FILTER_IN_BEACON);
-
-       /* Fill the data specific for station mode */
-       iwm_mac_ctxt_cmd_fill_sta(sc, in,
-           &cmd.sta, action == IWM_FW_CTXT_ACTION_ADD);
+       } else {
+               /* Fill in the data specific for station mode. */
+               uint32_t dtim_off;
+               uint64_t tsf;
+
+               dtim_off = ni->ni_nextdtim * ni->ni_intval * IEEE80211_DUR_TU;
+               cmd.sta.dtim_time = htole32(ni->ni_rstamp + dtim_off);
+               memcpy(&tsf, ni->ni_tstamp, sizeof(ni->ni_tstamp));
+               tsf = letoh64(tsf);
+               cmd.sta.dtim_tsf = htole64(tsf + dtim_off);
+               cmd.sta.bi = htole32(ni->ni_intval);
+               cmd.sta.bi_reciprocal = htole32(iwm_reciprocal(ni->ni_intval));
+               cmd.sta.dtim_interval =
+                   htole32(ni->ni_intval * ni->ni_dtimperiod);
+               cmd.sta.dtim_reciprocal =
+                   htole32(iwm_reciprocal(ni->ni_intval * ni->ni_dtimperiod));
+               cmd.sta.is_assoc = htole32(1);
+               cmd.sta.listen_interval = htole32(10);
+               cmd.sta.assoc_id = htole32(ni->ni_associd);
+       }
 
        return iwm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, 0, sizeof(cmd),
            &cmd);
@@ -5157,8 +5153,6 @@ iwm_auth(struct iwm_softc *sc)
        uint32_t duration;
        int err;
 
-       in->in_assoc = 0;
-
        err = iwm_sf_config(sc, IWM_SF_FULL_ON);
        if (err)
                return err;
@@ -5182,7 +5176,7 @@ iwm_auth(struct iwm_softc *sc)
        if (err)
                return err;
 
-       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
+       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 0);
        if (err) {
                printf("%s: failed to update MAC\n", DEVNAME(sc));
                return err;
@@ -5211,14 +5205,6 @@ iwm_assoc(struct iwm_softc *sc)
        if (err)
                return err;
 
-       in->in_assoc = 1;
-
-       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY);
-       if (err) {
-               printf("%s: failed to update MAC\n", DEVNAME(sc));
-               return err;
-       }
-
        return 0;
 }
 
@@ -5422,10 +5408,6 @@ iwm_newstate_task(void *psc)
        /* Reset the device if moving out of AUTH, ASSOC, or RUN. */
        /* XXX Is there a way to switch states without a full reset? */
        if (ostate > IEEE80211_S_SCAN && nstate < ostate) {
-               in = (struct iwm_node *)ic->ic_bss;
-               if (in)
-                       in->in_assoc = 0;
-
                iwm_stop_device(sc);
                iwm_init_hw(sc);
 
@@ -5479,7 +5461,13 @@ iwm_newstate_task(void *psc)
 
        case IEEE80211_S_RUN:
                in = (struct iwm_node *)ic->ic_bss;
-               iwm_power_mac_update_mode(sc, in);
+
+               err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_MODIFY, 1);
+               if (err) {
+                       printf("%s: failed to update MAC\n", DEVNAME(sc));
+                       return;
+               }
+
 #ifdef notyet
                /* 
                 * Disabled for now. Default beacon filter settings
@@ -5487,6 +5475,7 @@ iwm_newstate_task(void *psc)
                 * updates from beacons.
                 */
                iwm_enable_beacon_filter(sc, in);
+               iwm_power_mac_update_mode(sc, in);
 #endif
                iwm_update_quotas(sc, in);
 
@@ -5853,7 +5842,7 @@ iwm_init_hw(struct iwm_softc *sc)
                }
        }
 
-       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
+       err = iwm_mac_ctxt_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD, 0);
        if (err) {
                printf("%s: could not add MAC context (error %d)\n",
                    DEVNAME(sc), err);
@@ -6009,7 +5998,6 @@ iwm_stop(struct ifnet *ifp, int disable)
        ifq_clr_oactive(&ifp->if_snd);
 
        in->in_phyctxt = NULL;
-       in->in_assoc = 0;
 
        task_del(systq, &sc->init_task);
        task_del(sc->sc_nswq, &sc->newstate_task);
Index: dev/pci/if_iwmreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwmreg.h,v
retrieving revision 1.18
diff -u -p -r1.18 if_iwmreg.h
--- dev/pci/if_iwmreg.h 10 Sep 2016 09:32:33 -0000      1.18
+++ dev/pci/if_iwmreg.h 19 Sep 2016 22:41:13 -0000
@@ -3503,7 +3503,7 @@ struct iwm_ac_qos {
  * @id_and_color: ID and color of the MAC
  * @action: action to perform, one of IWM_FW_CTXT_ACTION_*
  * @mac_type: one of IWM_FW_MAC_TYPE_*
- * @tsd_id: TSF HW timer, one of IWM_TSF_ID_*
+ * @tsf_id: TSF HW timer, one of IWM_TSF_ID_*
  * @node_addr: MAC address
  * @bssid_addr: BSSID
  * @cck_rates: basic rates available for CCK
Index: dev/pci/if_iwmvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.23
diff -u -p -r1.23 if_iwmvar.h
--- dev/pci/if_iwmvar.h 12 Sep 2016 10:18:26 -0000      1.23
+++ dev/pci/if_iwmvar.h 19 Sep 2016 22:41:13 -0000
@@ -501,10 +501,6 @@ struct iwm_node {
 
        uint16_t in_id;
        uint16_t in_color;
-       int in_tsfid;
-
-       /* status "bits" */
-       int in_assoc;
 
        struct iwm_lq_cmd in_lq;
        struct ieee80211_amrr_node in_amn;
Index: net80211/ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.178
diff -u -p -r1.178 ieee80211_input.c
--- net80211/ieee80211_input.c  18 May 2016 08:15:28 -0000      1.178
+++ net80211/ieee80211_input.c  19 Sep 2016 22:41:25 -0000
@@ -1393,7 +1393,7 @@ ieee80211_recv_probe_resp(struct ieee802
        const u_int8_t *tstamp, *ssid, *rates, *xrates, *edcaie, *wmmie;
        const u_int8_t *rsnie, *wpaie, *htcaps, *htop;
        u_int16_t capinfo, bintval;
-       u_int8_t chan, bchan, erp;
+       u_int8_t chan, bchan, erp, dtim_count, dtim_period;
        int is_new;
 
        /*
@@ -1436,6 +1436,7 @@ ieee80211_recv_probe_resp(struct ieee802
        bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        chan = bchan;
        erp = 0;
+       dtim_count = dtim_period = 0;
        while (frm + 2 <= efrm) {
                if (frm + 2 + frm[1] > efrm) {
                        ic->ic_stats.is_rx_elem_toosmall++;
@@ -1477,6 +1478,12 @@ ieee80211_recv_probe_resp(struct ieee802
                case IEEE80211_ELEMID_HTOP:
                        htop = frm;
                        break;
+               case IEEE80211_ELEMID_TIM:
+                       if (frm[1] > 2) {
+                               dtim_count = frm[2];
+                               dtim_period = frm[3];
+                       }
+                       break;
                case IEEE80211_ELEMID_VENDOR:
                        if (frm[1] < 4) {
                                ic->ic_stats.is_rx_elem_toosmall++;
@@ -1567,6 +1574,9 @@ ieee80211_recv_probe_resp(struct ieee802
                ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
        if (htop && !ieee80211_setup_htop(ni, htop + 2, htop[1]))
                htop = NULL; /* invalid HTOP */
+
+       ni->ni_dtimperiod = dtim_period;
+       ni->ni_nextdtim = dtim_count;
 
        /*
         * When operating in station mode, check for state updates
Index: net80211/ieee80211_node.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.h,v
retrieving revision 1.60
diff -u -p -r1.60 ieee80211_node.h
--- net80211/ieee80211_node.h   28 Apr 2016 08:18:10 -0000      1.60
+++ net80211/ieee80211_node.h   19 Sep 2016 22:41:25 -0000
@@ -188,7 +188,6 @@ struct ieee80211_node {
        struct ieee80211_channel *ni_chan;
        u_int8_t                ni_erp;         /* 11g only */
 
-#ifdef notyet
        /* DTIM and contention free period (CFP) */
        u_int8_t                ni_dtimperiod;
        u_int8_t                ni_cfpperiod;   /* # of DTIMs between CFPs */
@@ -196,7 +195,6 @@ struct ieee80211_node {
        u_int16_t               ni_cfpmaxduration;/* max CFP duration in TU */
        u_int16_t               ni_nextdtim;    /* time to next DTIM */
        u_int16_t               ni_timoffset;
-#endif
 
        /* power saving mode */
        u_int8_t                ni_pwrsave;


Reply via email to