I'm investigating latency issues with 11n block ack on iwn.

There's a dedicated command to update RXON flags while associated.
Use this command instead of whacking the whole firmware node table
and restoring it. The firmware node table contains block ack state
and we shouldn't mess with that.

Index: if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.164
diff -u -p -r1.164 if_iwn.c
--- if_iwn.c    13 Apr 2016 10:34:32 -0000      1.164
+++ if_iwn.c    27 Apr 2016 15:50:34 -0000
@@ -5047,93 +5047,31 @@ void
 iwn_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni)
 {
        struct iwn_softc *sc = ic->ic_softc;
-       struct iwn_ops *ops = &sc->ops;
        enum ieee80211_htprot htprot;
-       struct iwn_node_info node;
-       int error, ridx;
-
-       timeout_del(&sc->calib_to);
-
-       /* Fake a "disassociation" so we can change RXON configuration. */
-       sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
-       error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
-       if (error != 0) {
-               printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
-               return;
-       }
+       struct iwn_rxon_assoc rxon_assoc;
+       int error;
 
        /* Update HT protection mode setting. */
        htprot = (ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
            IEEE80211_HTOP1_PROT_SHIFT;
        sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3));
        sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot));
-       sc->rxon.filter |= htole32(IWN_FILTER_BSS);
-       error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
-       if (error != 0) {
-               printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
-               return;
-       }
-
-       /* 
-        * The firmware loses TX power table, node table, LQ table,
-        * and sensitivity calibration after an RXON command.
-        */
-
-       if ((error = ops->set_txpower(sc, 1)) != 0) {
-               printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
-               return;
-       }
-
-       ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
-           IWN_RIDX_OFDM6 : IWN_RIDX_CCK1;
-       if ((error = iwn_add_broadcast_node(sc, 1, ridx)) != 0) {
-               printf("%s: could not add broadcast node\n",
-                   sc->sc_dev.dv_xname);
-               return;
-       }
-
-       memset(&node, 0, sizeof node);
-       IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr);
-       node.id = IWN_ID_BSS;
-       if (ni->ni_flags & IEEE80211_NODE_HT) {
-               node.htmask = (IWN_AMDPU_SIZE_FACTOR_MASK |
-                   IWN_AMDPU_DENSITY_MASK);
-               node.htflags = htole32(
-                   IWN_AMDPU_SIZE_FACTOR(
-                       (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_LE)) |
-                   IWN_AMDPU_DENSITY(
-                       (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) >> 2));
-       }
-       error = ops->add_node(sc, &node, 1);
-       if (error != 0) {
-               printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
-               return;
-       }
-
-       if ((error = iwn_set_link_quality(sc, ni)) != 0) {
-               printf("%s: could not setup link quality for node %d\n",
-                   sc->sc_dev.dv_xname, node.id);
-               return;
-       }
-
-       if ((error = iwn_init_sensitivity(sc)) != 0) {
-               printf("%s: could not set sensitivity\n",
-                   sc->sc_dev.dv_xname);
-               return;
-       }
-
-       sc->calib.state = IWN_CALIB_STATE_ASSOC;
-       sc->calib_cnt = 0;
-       timeout_add_msec(&sc->calib_to, 500);
 
-       if ((ni->ni_flags & IEEE80211_NODE_RXPROT) &&
-           ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
-               if ((error = iwn_set_key(ic, ni, &ni->ni_pairwise_key)) != 0) {
-                       printf("%s: could not set pairwise ccmp key\n",
-                           sc->sc_dev.dv_xname);
-                       return;
-               }
-       }
+       /* Update RXON config. */
+       memset(&rxon_assoc, 0, sizeof(rxon_assoc));
+       rxon_assoc.flags = sc->rxon.flags;
+       rxon_assoc.filter = sc->rxon.filter;
+       rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;
+       rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;
+       rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;
+       rxon_assoc.ht_triple_mask = sc->rxon.ht_triple_mask;
+       rxon_assoc.rxchain = sc->rxon.rxchain;
+       rxon_assoc.acquisition = sc->rxon.acquisition;
+
+       error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &rxon_assoc,
+           sizeof(rxon_assoc), 1);
+       if (error != 0)
+               printf("%s: RXON_ASSOC command failed\n", sc->sc_dev.dv_xname);
 }
 
 /*
Index: if_iwnreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.52
diff -u -p -r1.52 if_iwnreg.h
--- if_iwnreg.h 5 Feb 2016 16:09:19 -0000       1.52
+++ if_iwnreg.h 27 Apr 2016 14:55:31 -0000
@@ -526,6 +526,22 @@ struct iwn_rxon {
        uint16_t        reserved6;
 } __packed;
 
+/* Structure for command IWN_CMD_RXON_ASSOC. */
+struct iwn_rxon_assoc {
+       uint32_t flags;
+       uint32_t filter;
+       uint8_t ofdm_mask;
+       uint8_t cck_mask;
+       uint16_t reserved1;
+       uint8_t ht_single_mask;
+       uint8_t ht_dual_mask;
+       uint8_t ht_triple_mask;
+       uint8_t reserved2;
+       uint16_t rxchain;
+       uint16_t acquisition;
+       uint32_t reserved3;
+} __packed;
+
 #define IWN4965_RXONSZ (sizeof (struct iwn_rxon) - 6)
 #define IWN5000_RXONSZ (sizeof (struct iwn_rxon))
 

Reply via email to