Make iwn, iwm, and iwx keep track of beacon parameters at run-time.
authorstsp <stsp@openbsd.org>
Thu, 29 Apr 2021 21:43:46 +0000 (21:43 +0000)
committerstsp <stsp@openbsd.org>
Thu, 29 Apr 2021 21:43:46 +0000 (21:43 +0000)
- HT protection settings (this was already implemented)
- ERP (11g) protection setting
- short slottime setting
- short preamble setting
- EDCA (QoS) parameters

All of these parameters are communicated in beacons and hardware is
now kept up-to-date with them.

Prompted by a problem report from Christian Ehrhardt regarding ERP.

Tested:
iwn 6205: stsp, Josh Grosse
iwm 7265: trondd
iwm 8265: stsp, Matthias Schmidt
iwm 9260: phessler
iwx ax200: stsp, jmc, gnezdo

sys/dev/pci/if_iwm.c
sys/dev/pci/if_iwmvar.h
sys/dev/pci/if_iwn.c
sys/dev/pci/if_iwx.c
sys/dev/pci/if_iwxvar.h
sys/net80211/ieee80211_input.c
sys/net80211/ieee80211_node.c
sys/net80211/ieee80211_var.h

index 1d7c376..78294ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwm.c,v 1.319 2021/04/25 15:32:21 stsp Exp $       */
+/*     $OpenBSD: if_iwm.c,v 1.320 2021/04/29 21:43:47 stsp Exp $       */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -328,8 +328,10 @@ void       iwm_init_channel_map(struct iwm_softc *, const uint16_t * const,
            const uint8_t *nvm_channels, int nchan);
 int    iwm_mimo_enabled(struct iwm_softc *);
 void   iwm_setup_ht_rates(struct iwm_softc *);
-void   iwm_htprot_task(void *);
-void   iwm_update_htprot(struct ieee80211com *, struct ieee80211_node *);
+void   iwm_mac_ctxt_task(void *);
+void   iwm_updateprot(struct ieee80211com *);
+void   iwm_updateslot(struct ieee80211com *);
+void   iwm_updateedca(struct ieee80211com *);
 void   iwm_init_reorder_buffer(struct iwm_reorder_buffer *, uint16_t,
            uint16_t);
 void   iwm_clear_reorder_buffer(struct iwm_softc *, struct iwm_rxba_data *);
@@ -3170,7 +3172,7 @@ iwm_sta_rx_agg(struct iwm_softc *sc, struct ieee80211_node *ni, uint8_t tid,
 }
 
 void
-iwm_htprot_task(void *arg)
+iwm_mac_ctxt_task(void *arg)
 {
        struct iwm_softc *sc = arg;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -3183,27 +3185,39 @@ iwm_htprot_task(void *arg)
                return;
        }
 
-       /* This call updates HT protection based on in->in_ni.ni_htop1. */
        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);
+               printf("%s: failed to update MAC\n", DEVNAME(sc));
 
        refcnt_rele_wake(&sc->task_refs);
        splx(s);
 }
 
-/*
- * This function is called by upper layer when HT protection settings in
- * beacons have changed.
- */
 void
-iwm_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni)
+iwm_updateprot(struct ieee80211com *ic)
+{
+       struct iwm_softc *sc = ic->ic_softc;
+
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwm_add_task(sc, systq, &sc->mac_ctxt_task);
+}
+
+void
+iwm_updateslot(struct ieee80211com *ic)
+{
+       struct iwm_softc *sc = ic->ic_softc;
+
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwm_add_task(sc, systq, &sc->mac_ctxt_task);
+}
+
+void
+iwm_updateedca(struct ieee80211com *ic)
 {
        struct iwm_softc *sc = ic->ic_softc;
 
-       /* assumes that ni == ic->ic_bss */
-       iwm_add_task(sc, systq, &sc->htprot_task);
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwm_add_task(sc, systq, &sc->mac_ctxt_task);
 }
 
 void
@@ -8026,7 +8040,7 @@ iwm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        if (ic->ic_state == IEEE80211_S_RUN) {
                timeout_del(&sc->sc_calib_to);
                iwm_del_task(sc, systq, &sc->ba_task);
-               iwm_del_task(sc, systq, &sc->htprot_task);
+               iwm_del_task(sc, systq, &sc->mac_ctxt_task);
                for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
                        struct iwm_rxba_data *rxba = &sc->sc_rxba_data[i];
                        iwm_clear_reorder_buffer(sc, rxba);
@@ -8808,7 +8822,7 @@ iwm_stop(struct ifnet *ifp)
        task_del(systq, &sc->init_task);
        iwm_del_task(sc, sc->sc_nswq, &sc->newstate_task);
        iwm_del_task(sc, systq, &sc->ba_task);
-       iwm_del_task(sc, systq, &sc->htprot_task);
+       iwm_del_task(sc, systq, &sc->mac_ctxt_task);
        KASSERT(sc->task_refs.refs >= 1);
        refcnt_finalize(&sc->task_refs, "iwmstop");
 
@@ -10250,7 +10264,7 @@ iwm_attach(struct device *parent, struct device *self, void *aux)
        task_set(&sc->init_task, iwm_init_task, sc);
        task_set(&sc->newstate_task, iwm_newstate_task, sc);
        task_set(&sc->ba_task, iwm_ba_task, sc);
-       task_set(&sc->htprot_task, iwm_htprot_task, sc);
+       task_set(&sc->mac_ctxt_task, iwm_mac_ctxt_task, sc);
 
        ic->ic_node_alloc = iwm_node_alloc;
        ic->ic_bgscan_start = iwm_bgscan;
@@ -10260,7 +10274,9 @@ iwm_attach(struct device *parent, struct device *self, void *aux)
        /* Override 802.11 state transition machine. */
        sc->sc_newstate = ic->ic_newstate;
        ic->ic_newstate = iwm_newstate;
-       ic->ic_update_htprot = iwm_update_htprot;
+       ic->ic_updateprot = iwm_updateprot;
+       ic->ic_updateslot = iwm_updateslot;
+       ic->ic_updateedca = iwm_updateedca;
        ic->ic_ampdu_rx_start = iwm_ampdu_rx_start;
        ic->ic_ampdu_rx_stop = iwm_ampdu_rx_stop;
 #ifdef notyet
index f404247..05a6258 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwmvar.h,v 1.59 2021/04/25 15:32:21 stsp Exp $     */
+/*     $OpenBSD: if_iwmvar.h,v 1.60 2021/04/29 21:43:47 stsp Exp $     */
 
 /*
  * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -478,8 +478,8 @@ struct iwm_softc {
        uint16_t                ba_winsize[IWM_MAX_TID_COUNT];
        int                     ba_timeout_val[IWM_MAX_TID_COUNT];
 
-       /* Task for HT protection updates. */
-       struct task             htprot_task;
+       /* Task for ERP/HT prot/slot-time/EDCA updates. */
+       struct task             mac_ctxt_task;
 
        bus_space_tag_t sc_st;
        bus_space_handle_t sc_sh;
index 241fff3..a5a78bf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwn.c,v 1.247 2021/03/22 09:52:49 stsp Exp $       */
+/*     $OpenBSD: if_iwn.c,v 1.248 2021/04/29 21:43:47 stsp Exp $       */
 
 /*-
  * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -247,8 +247,9 @@ int         iwn_set_key(struct ieee80211com *, struct ieee80211_node *,
                    struct ieee80211_key *);
 void           iwn_delete_key(struct ieee80211com *, struct ieee80211_node *,
                    struct ieee80211_key *);
-void           iwn_update_htprot(struct ieee80211com *,
-                   struct ieee80211_node *);
+void           iwn_updateprot(struct ieee80211com *);
+void           iwn_updateslot(struct ieee80211com *);
+void           iwn_update_rxon(struct iwn_softc *);
 int            iwn_ampdu_rx_start(struct ieee80211com *,
                    struct ieee80211_node *, uint8_t);
 void           iwn_ampdu_rx_stop(struct ieee80211com *,
@@ -540,7 +541,8 @@ iwn_attach(struct device *parent, struct device *self, void *aux)
        ic->ic_updateedca = iwn_updateedca;
        ic->ic_set_key = iwn_set_key;
        ic->ic_delete_key = iwn_delete_key;
-       ic->ic_update_htprot = iwn_update_htprot;
+       ic->ic_updateprot = iwn_updateprot;
+       ic->ic_updateslot = iwn_updateslot;
        ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
        ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
        ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;
@@ -5652,25 +5654,58 @@ iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
        (void)ops->add_node(sc, &node, 1);
 }
 
-/*
- * This function is called by upper layer when HT protection settings in
- * beacons have changed.
- */
 void
-iwn_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni)
+iwn_updateprot(struct ieee80211com *ic)
 {
        struct iwn_softc *sc = ic->ic_softc;
-       struct iwn_ops *ops = &sc->ops;
        enum ieee80211_htprot htprot;
-       struct iwn_rxon_assoc rxon_assoc;
-       int s, error;
+
+       if (ic->ic_state != IEEE80211_S_RUN)
+               return;
+
+       /* Update ERP protection setting. */
+       if (ic->ic_flags & IEEE80211_F_USEPROT)
+               sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT);
+       else
+               sc->rxon.flags &= ~htole32(IWN_RXON_TGG_PROT);
 
        /* Update HT protection mode setting. */
-       htprot = (ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
+       htprot = (ic->ic_bss->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));
 
+       iwn_update_rxon(sc);
+}
+
+void
+iwn_updateslot(struct ieee80211com *ic)
+{
+       struct iwn_softc *sc = ic->ic_softc;
+
+       if (ic->ic_state != IEEE80211_S_RUN)
+               return;
+
+       if (ic->ic_flags & IEEE80211_F_SHSLOT)
+               sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);
+       else
+               sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT);
+
+       if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+               sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);
+       else
+               sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE);
+
+       iwn_update_rxon(sc);
+}
+void
+iwn_update_rxon(struct iwn_softc *sc)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct iwn_ops *ops = &sc->ops;
+       struct iwn_rxon_assoc rxon_assoc;
+       int s, error;
+
        /* Update RXON config. */
        memset(&rxon_assoc, 0, sizeof(rxon_assoc));
        rxon_assoc.flags = sc->rxon.flags;
index 724ab67..2775f72 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.53 2021/04/25 15:32:21 stsp Exp $        */
+/*     $OpenBSD: if_iwx.c,v 1.54 2021/04/29 21:43:47 stsp Exp $        */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -300,8 +300,10 @@ void       iwx_unprotect_session(struct iwx_softc *, struct iwx_node *);
 void   iwx_init_channel_map(struct iwx_softc *, uint16_t *, uint32_t *, int);
 void   iwx_setup_ht_rates(struct iwx_softc *);
 int    iwx_mimo_enabled(struct iwx_softc *);
-void   iwx_htprot_task(void *);
-void   iwx_update_htprot(struct ieee80211com *, struct ieee80211_node *);
+void   iwx_mac_ctxt_task(void *);
+void   iwx_updateprot(struct ieee80211com *);
+void   iwx_updateslot(struct ieee80211com *);
+void   iwx_updateedca(struct ieee80211com *);
 void   iwx_init_reorder_buffer(struct iwx_reorder_buffer *, uint16_t,
            uint16_t);
 void   iwx_clear_reorder_buffer(struct iwx_softc *, struct iwx_rxba_data *);
@@ -2940,7 +2942,7 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid,
 }
 
 void
-iwx_htprot_task(void *arg)
+iwx_mac_ctxt_task(void *arg)
 {
        struct iwx_softc *sc = arg;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -2953,27 +2955,39 @@ iwx_htprot_task(void *arg)
                return;
        }
 
-       /* This call updates HT protection based on in->in_ni.ni_htop1. */
        err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 1);
        if (err)
-               printf("%s: could not change HT protection: error %d\n",
-                   DEVNAME(sc), err);
+               printf("%s: failed to update MAC\n", DEVNAME(sc));
 
        refcnt_rele_wake(&sc->task_refs);
        splx(s);
 }
 
-/*
- * This function is called by upper layer when HT protection settings in
- * beacons have changed.
- */
 void
-iwx_update_htprot(struct ieee80211com *ic, struct ieee80211_node *ni)
+iwx_updateprot(struct ieee80211com *ic)
+{
+       struct iwx_softc *sc = ic->ic_softc;
+
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwx_add_task(sc, systq, &sc->mac_ctxt_task);
+}
+
+void
+iwx_updateslot(struct ieee80211com *ic)
+{
+       struct iwx_softc *sc = ic->ic_softc;
+
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwx_add_task(sc, systq, &sc->mac_ctxt_task);
+}
+
+void
+iwx_updateedca(struct ieee80211com *ic)
 {
        struct iwx_softc *sc = ic->ic_softc;
 
-       /* assumes that ni == ic->ic_bss */
-       iwx_add_task(sc, systq, &sc->htprot_task);
+       if (ic->ic_state == IEEE80211_S_RUN)
+               iwx_add_task(sc, systq, &sc->mac_ctxt_task);
 }
 
 void
@@ -6854,7 +6868,7 @@ iwx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 
        if (ic->ic_state == IEEE80211_S_RUN) {
                iwx_del_task(sc, systq, &sc->ba_task);
-               iwx_del_task(sc, systq, &sc->htprot_task);
+               iwx_del_task(sc, systq, &sc->mac_ctxt_task);
                for (i = 0; i < nitems(sc->sc_rxba_data); i++) {
                        struct iwx_rxba_data *rxba = &sc->sc_rxba_data[i];
                        iwx_clear_reorder_buffer(sc, rxba);
@@ -7426,7 +7440,7 @@ iwx_stop(struct ifnet *ifp)
        task_del(systq, &sc->init_task);
        iwx_del_task(sc, sc->sc_nswq, &sc->newstate_task);
        iwx_del_task(sc, systq, &sc->ba_task);
-       iwx_del_task(sc, systq, &sc->htprot_task);
+       iwx_del_task(sc, systq, &sc->mac_ctxt_task);
        KASSERT(sc->task_refs.refs >= 1);
        refcnt_finalize(&sc->task_refs, "iwxstop");
 
@@ -8823,7 +8837,7 @@ iwx_attach(struct device *parent, struct device *self, void *aux)
        task_set(&sc->init_task, iwx_init_task, sc);
        task_set(&sc->newstate_task, iwx_newstate_task, sc);
        task_set(&sc->ba_task, iwx_ba_task, sc);
-       task_set(&sc->htprot_task, iwx_htprot_task, sc);
+       task_set(&sc->mac_ctxt_task, iwx_mac_ctxt_task, sc);
 
        ic->ic_node_alloc = iwx_node_alloc;
        ic->ic_bgscan_start = iwx_bgscan;
@@ -8833,7 +8847,9 @@ iwx_attach(struct device *parent, struct device *self, void *aux)
        /* Override 802.11 state transition machine. */
        sc->sc_newstate = ic->ic_newstate;
        ic->ic_newstate = iwx_newstate;
-       ic->ic_update_htprot = iwx_update_htprot;
+       ic->ic_updateprot = iwx_updateprot;
+       ic->ic_updateslot = iwx_updateslot;
+       ic->ic_updateedca = iwx_updateedca;
        ic->ic_ampdu_rx_start = iwx_ampdu_rx_start;
        ic->ic_ampdu_rx_stop = iwx_ampdu_rx_stop;
 #ifdef notyet
index 732a1a4..9935287 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxvar.h,v 1.14 2021/04/25 15:32:21 stsp Exp $     */
+/*     $OpenBSD: if_iwxvar.h,v 1.15 2021/04/29 21:43:47 stsp Exp $     */
 
 /*
  * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -458,8 +458,8 @@ struct iwx_softc {
        uint16_t                ba_winsize[IWX_MAX_TID_COUNT];
        int                     ba_timeout_val[IWX_MAX_TID_COUNT];
 
-       /* Task for HT protection updates. */
-       struct task             htprot_task;
+       /* Task for ERP/HT prot/slot-time/EDCA updates. */
+       struct task             mac_ctxt_task;
 
        bus_space_tag_t sc_st;
        bus_space_handle_t sc_sh;
index 4a9c33e..633161c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_input.c,v 1.233 2021/04/25 15:32:21 stsp Exp $      */
+/*     $OpenBSD: ieee80211_input.c,v 1.234 2021/04/29 21:43:46 stsp Exp $      */
 
 /*-
  * Copyright (c) 2001 Atsushi Onoe
@@ -1744,6 +1744,7 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
        if (ic->ic_opmode == IEEE80211_M_STA &&
            ic->ic_state == IEEE80211_S_RUN &&
            ni->ni_state == IEEE80211_STA_BSS) {
+               int updateprot = 0;
                /*
                 * Check if protection mode has changed since last beacon.
                 */
@@ -1759,6 +1760,7 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
                        else
                                ic->ic_flags &= ~IEEE80211_F_USEPROT;
                        ic->ic_bss->ni_erp = erp;
+                       updateprot = 1;
                }
                if (htop && (ic->ic_bss->ni_flags & IEEE80211_NODE_HT)) {
                        enum ieee80211_htprot htprot_last, htprot;
@@ -1773,10 +1775,11 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
                                    htprot_last, htprot));
                                ic->ic_stats.is_ht_prot_change++;
                                ic->ic_bss->ni_htop1 = ni->ni_htop1;
-                               if (ic->ic_update_htprot)
-                                       ic->ic_update_htprot(ic, ic->ic_bss);
+                               updateprot = 1;
                        }
                }
+               if (updateprot && ic->ic_updateprot != NULL)
+                       ic->ic_updateprot(ic);
 
                /*
                 * Check if AP short slot time setting has changed
index 6365c1e..213ef3f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_node.c,v 1.184 2021/04/15 18:05:05 stsp Exp $       */
+/*     $OpenBSD: ieee80211_node.c,v 1.185 2021/04/29 21:43:47 stsp Exp $       */
 /*     $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $       */
 
 /*-
@@ -962,8 +962,8 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
                ni->ni_htop1 = IEEE80211_HTPROT_NONE;
                /* Disallow Greenfield mode. None of our drivers support it. */
                ni->ni_htop1 |= IEEE80211_HTOP1_NONGF_STA;
-               if (ic->ic_update_htprot)
-                       ic->ic_update_htprot(ic, ni);
+               if (ic->ic_updateprot)
+                       ic->ic_updateprot(ic);
 
                /* Configure QoS EDCA parameters. */
                for (aci = 0; aci < EDCA_NUM_AC; aci++) {
@@ -2214,8 +2214,8 @@ ieee80211_clean_nodes(struct ieee80211com *ic, int cache_timeout)
                        htop1 |= htprot;
                        ic->ic_bss->ni_htop1 = htop1;
                        ic->ic_protmode = protmode;
-                       if (ic->ic_update_htprot)
-                               ic->ic_update_htprot(ic, ic->ic_bss);
+                       if (ic->ic_updateprot)
+                               ic->ic_updateprot(ic);
                }
        }
 
@@ -2489,8 +2489,8 @@ ieee80211_node_join_ht(struct ieee80211com *ic, struct ieee80211_node *ni)
                htop1 &= ~IEEE80211_HTOP1_PROT_MASK;
                htop1 |= IEEE80211_HTPROT_NONHT_MIXED;
                ic->ic_bss->ni_htop1 = htop1;
-               if (ic->ic_update_htprot)
-                       ic->ic_update_htprot(ic, ic->ic_bss);
+               if (ic->ic_updateprot)
+                       ic->ic_updateprot(ic);
        }
 }
 
index ba71162..06cf737 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_var.h,v 1.102 2020/07/15 22:49:08 cheloha Exp $     */
+/*     $OpenBSD: ieee80211_var.h,v 1.103 2021/04/29 21:43:47 stsp Exp $        */
 /*     $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
 
 /*-
@@ -244,8 +244,7 @@ struct ieee80211com {
                                    struct ieee80211_node *, u_int8_t);
        void                    (*ic_ampdu_rx_stop)(struct ieee80211com *,
                                    struct ieee80211_node *, u_int8_t);
-       void                    (*ic_update_htprot)(struct ieee80211com *,
-                                       struct ieee80211_node *);
+       void                    (*ic_updateprot)(struct ieee80211com *);
        int                     (*ic_bgscan_start)(struct ieee80211com *);
        struct timeout          ic_bgscan_timeout;
        uint32_t                ic_bgscan_fail;