From 09268e1f27d8f5f2f53b7cc87ce46ea555fcc4f8 Mon Sep 17 00:00:00 2001 From: stsp Date: Thu, 29 Apr 2021 21:43:46 +0000 Subject: [PATCH] Make iwn, iwm, and iwx keep track of beacon parameters at run-time. - 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 | 52 +++++++++++++++++++---------- sys/dev/pci/if_iwmvar.h | 6 ++-- sys/dev/pci/if_iwn.c | 61 ++++++++++++++++++++++++++-------- sys/dev/pci/if_iwx.c | 52 +++++++++++++++++++---------- sys/dev/pci/if_iwxvar.h | 6 ++-- sys/net80211/ieee80211_input.c | 9 +++-- sys/net80211/ieee80211_node.c | 14 ++++---- sys/net80211/ieee80211_var.h | 5 ++- 8 files changed, 137 insertions(+), 68 deletions(-) diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 1d7c376ff8c..78294baa6fd 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -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 @@ -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 diff --git a/sys/dev/pci/if_iwmvar.h b/sys/dev/pci/if_iwmvar.h index f40424718a5..05a62582e8a 100644 --- a/sys/dev/pci/if_iwmvar.h +++ b/sys/dev/pci/if_iwmvar.h @@ -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 @@ -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; diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 241fff3d280..a5a78bfcf86 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -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 @@ -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; diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 724ab6796ce..2775f725d63 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -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 @@ -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 diff --git a/sys/dev/pci/if_iwxvar.h b/sys/dev/pci/if_iwxvar.h index 732a1a4f4ef..993528772f7 100644 --- a/sys/dev/pci/if_iwxvar.h +++ b/sys/dev/pci/if_iwxvar.h @@ -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 @@ -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; diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 4a9c33e9694..633161c60bc 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -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 diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 6365c1e2dfe..213ef3fc1c9 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -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); } } diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index ba711629a0b..06cf7375f70 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -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; -- 2.20.1