I found that my 8260 iwm(4) device has trouble associating to my 5 GHz AP,
which runs OpenBSD with athn(4) in hostap mode. Most of the time it won't
even get a DHCP lease. Some frames it believes it has sent are not even
visible on the air.

The iwm driver still has a copy of code from Linux that sends DTIM TSF
information to the firmware. I believe this depends on Linux mac80211
behaviour details and is bogus with our stack, and we should just let
firmware handle TSF synchronization details by itself (and just look
at those glories comments...)

Also, clear in_assoc when going down, as it effects early behaviour
when coming up, before association (found by Imre).

I'm now getting much better results when switching between networks
with the 8260. Doesn't cause problems on 7260 and 7265.

ok?

Index: if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.88
diff -u -p -r1.88 if_iwm.c
--- if_iwm.c    19 Jun 2016 12:05:25 -0000      1.88
+++ if_iwm.c    20 Jun 2016 10:15:35 -0000
@@ -5723,58 +5723,14 @@ iwm_mvm_mac_ctxt_cmd_fill_sta(struct iwm
        struct iwm_mac_data_sta *ctxt_sta, int force_assoc_off)
 {
        struct ieee80211_node *ni = &in->in_ni;
-       unsigned dtim_period, dtim_count;
        struct ieee80211com *ic = &sc->sc_ic;
 
-       /* will this work? */
-       dtim_period = ic->ic_dtim_period;
-       dtim_count = ic->ic_dtim_count;
-       DPRINTF(("dtim %d %d\n", dtim_period, dtim_count));
-
-       /* We need the dtim_period to set the MAC as associated */
-       if (in->in_assoc && dtim_period && !force_assoc_off) {
-               uint64_t tsf;
-               uint32_t dtim_offs;
-
-               /*
-                * The DTIM count counts down, so when it is N that means N
-                * more beacon intervals happen until the DTIM TBTT. Therefore
-                * add this to the current time. If that ends up being in the
-                * future, the firmware will handle it.
-                *
-                * Also note that the system_timestamp (which we get here as
-                * "sync_device_ts") and TSF timestamp aren't at exactly the
-                * same offset in the frame -- the TSF is at the first symbol
-                * of the TSF, the system timestamp is at signal acquisition
-                * time. This means there's an offset between them of at most
-                * a few hundred microseconds (24 * 8 bits + PLCP time gives
-                * 384us in the longest case), this is currently not relevant
-                * as the firmware wakes up around 2ms before the TBTT.
-                */
-               dtim_offs = dtim_count * ni->ni_intval;
-               /* convert TU to usecs */
-               dtim_offs *= 1024;
-
-               /* XXX: byte order? */
-               memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));
-
-               ctxt_sta->dtim_tsf = htole64(tsf + dtim_offs);
-               ctxt_sta->dtim_time = htole64(ni->ni_rstamp + dtim_offs);
-
-               DPRINTF(("DTIM TBTT is 0x%llx/0x%x, offset %d\n",
-                   (long long)le64toh(ctxt_sta->dtim_tsf),
-                   le32toh(ctxt_sta->dtim_time), dtim_offs));
-
-               ctxt_sta->is_assoc = htole32(1);
-       } else {
-               ctxt_sta->is_assoc = htole32(0);
-       }
-
+       ctxt_sta->is_assoc = htole32(0);
        ctxt_sta->bi = htole32(ni->ni_intval);
        ctxt_sta->bi_reciprocal = htole32(iwm_mvm_reciprocal(ni->ni_intval));
-       ctxt_sta->dtim_interval = htole32(ni->ni_intval * dtim_period);
+       ctxt_sta->dtim_interval = htole32(ni->ni_intval * ic->ic_dtim_period);
        ctxt_sta->dtim_reciprocal =
-           htole32(iwm_mvm_reciprocal(ni->ni_intval * dtim_period));
+           htole32(iwm_mvm_reciprocal(ni->ni_intval * ic->ic_dtim_period));
 
        /* 10 = CONN_MAX_LISTEN_INTERVAL */
        ctxt_sta->listen_interval = htole32(10);
@@ -6884,6 +6840,9 @@ iwm_stop(struct ifnet *ifp, int disable)
        ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
        ifp->if_flags &= ~IFF_RUNNING;
        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);

Reply via email to