From: stsp Date: Mon, 6 Mar 2023 10:48:05 +0000 (+0000) Subject: support iwx rate_n_flags API version 2 and delete fixed Tx rate support X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=08bf42d3d07486ca8fbb3b2b9eec11d8d5e4477a;p=openbsd support iwx rate_n_flags API version 2 and delete fixed Tx rate support As of this commit iwx will ignore 'ifconfig media' commands where the user-specified Tx rate resolves to something other than 'autoselect'. The existing support for forcing a Tx rate was already only partially working in 11n and 11ac modes. I doubt anyone had a serious use case for this. If you really need to force a specific Tx rate for data frames sent by iwx then hack the driver instead of using 'ifconfig media'. The firmware interface was designed for Tx rate selection in firmware. Maintaining support for overriding the Tx rate with ifconfig in face of complicated firmware interface changes such as this rate_n_flags change is just not worth it. While trying to keep forced Tx rates working on top of the new rate_n_flags format I accidentally broke the Tx rate used for managment frames during regular operation, which caused much frustration. --- diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index c0130b9c044..90e45ec0080 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.157 2023/03/06 10:31:58 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.158 2023/03/06 10:48:05 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -235,7 +235,6 @@ const int iwx_mcs2ridx[] = { uint8_t iwx_lookup_cmd_ver(struct iwx_softc *, uint8_t, uint8_t); uint8_t iwx_lookup_notif_ver(struct iwx_softc *, uint8_t, uint8_t); int iwx_is_mimo_ht_plcp(uint8_t); -int iwx_is_mimo_mcs(int); int iwx_store_cscheme(struct iwx_softc *, uint8_t *, size_t); int iwx_alloc_fw_monitor_block(struct iwx_softc *, uint8_t, uint8_t); int iwx_alloc_fw_monitor(struct iwx_softc *, uint8_t); @@ -395,6 +394,8 @@ int iwx_send_cmd_pdu_status(struct iwx_softc *, uint32_t, uint16_t, const void *, uint32_t *); void iwx_free_resp(struct iwx_softc *, struct iwx_host_cmd *); void iwx_cmd_done(struct iwx_softc *, int, int, int); +uint32_t iwx_fw_rateidx_ofdm(uint8_t); +uint32_t iwx_fw_rateidx_cck(uint8_t); const struct iwx_rate *iwx_tx_fill_cmd(struct iwx_softc *, struct iwx_node *, struct ieee80211_frame *, uint16_t *, uint32_t *); void iwx_tx_update_byte_tbl(struct iwx_softc *, struct iwx_tx_ring *, int, @@ -553,16 +554,21 @@ iwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd) int iwx_is_mimo_ht_plcp(uint8_t ht_plcp) { - return (ht_plcp != IWX_RATE_HT_SISO_MCS_INV_PLCP && - (ht_plcp & IWX_RATE_HT_MCS_NSS_MSK_V1)); -} + switch (ht_plcp) { + case IWX_RATE_HT_MIMO2_MCS_8_PLCP: + case IWX_RATE_HT_MIMO2_MCS_9_PLCP: + case IWX_RATE_HT_MIMO2_MCS_10_PLCP: + case IWX_RATE_HT_MIMO2_MCS_11_PLCP: + case IWX_RATE_HT_MIMO2_MCS_12_PLCP: + case IWX_RATE_HT_MIMO2_MCS_13_PLCP: + case IWX_RATE_HT_MIMO2_MCS_14_PLCP: + case IWX_RATE_HT_MIMO2_MCS_15_PLCP: + return 1; + default: + break; + } -int -iwx_is_mimo_mcs(int mcs) -{ - int ridx = iwx_mcs2ridx[mcs]; - return iwx_is_mimo_ht_plcp(iwx_rates[ridx].ht_plcp); - + return 0; } int @@ -2922,7 +2928,17 @@ out: void iwx_post_alive(struct iwx_softc *sc) { + int txcmd_ver; + iwx_ict_reset(sc); + + txcmd_ver = iwx_lookup_notif_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD) ; + if (txcmd_ver != IWX_FW_CMD_VER_UNKNOWN && txcmd_ver > 6) + sc->sc_rate_n_flags_version = 2; + else + sc->sc_rate_n_flags_version = 1; + + txcmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD); } int @@ -4538,6 +4554,8 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx, if (sc->sc_drvbpf != NULL) { struct iwx_rx_radiotap_header *tap = &sc->sc_rxtap; uint16_t chan_flags; + int have_legacy_rate = 1; + uint8_t mcs, rate; tap->wr_flags = 0; if (is_shortpre) @@ -4556,14 +4574,36 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx, tap->wr_dbm_antsignal = (int8_t)rxi->rxi_rssi; tap->wr_dbm_antnoise = (int8_t)sc->sc_noise; tap->wr_tsft = device_timestamp; - if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) { - uint8_t mcs = (rate_n_flags & + if (sc->sc_rate_n_flags_version >= 2) { + uint32_t mod_type = (rate_n_flags & + IWX_RATE_MCS_MOD_TYPE_MSK); + const struct ieee80211_rateset *rs = NULL; + uint32_t ridx; + have_legacy_rate = (mod_type == IWX_RATE_MCS_CCK_MSK || + mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK); + mcs = (rate_n_flags & IWX_RATE_HT_MCS_CODE_MSK); + ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK); + if (mod_type == IWX_RATE_MCS_CCK_MSK) + rs = &ieee80211_std_rateset_11b; + else if (mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK) + rs = &ieee80211_std_rateset_11a; + if (rs && ridx < rs->rs_nrates) { + rate = (rs->rs_rates[ridx] & + IEEE80211_RATE_VAL); + } else + rate = 0; + } else { + have_legacy_rate = ((rate_n_flags & + (IWX_RATE_MCS_HT_MSK_V1 | + IWX_RATE_MCS_VHT_MSK_V1)) == 0); + mcs = (rate_n_flags & (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 | IWX_RATE_HT_MCS_NSS_MSK_V1)); + rate = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1); + } + if (!have_legacy_rate) { tap->wr_rate = (0x80 | mcs); } else { - uint8_t rate = (rate_n_flags & - IWX_RATE_LEGACY_RATE_MSK_V1); switch (rate) { /* CCK rates. */ case 10: tap->wr_rate = 2; break; @@ -5827,6 +5867,36 @@ iwx_cmd_done(struct iwx_softc *sc, int qid, int idx, int code) ring->queued--; } +uint32_t +iwx_fw_rateidx_ofdm(uint8_t rval) +{ + /* Firmware expects indices which match our 11a rate set. */ + const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11a; + int i; + + for (i = 0; i < rs->rs_nrates; i++) { + if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval) + return i; + } + + return 0; +} + +uint32_t +iwx_fw_rateidx_cck(uint8_t rval) +{ + /* Firmware expects indices which match our 11b rate set. */ + const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11b; + int i; + + for (i = 0; i < rs->rs_nrates; i++) { + if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval) + return i; + } + + return 0; +} + /* * Determine the Tx command flags and Tx rate+flags to use. * Return the selected Tx rate. @@ -5842,6 +5912,7 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; int min_ridx = iwx_rval2ridx(ieee80211_min_basic_rate(ic)); int ridx, rate_flags; + uint8_t rval; *flags = 0; @@ -5850,16 +5921,9 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, /* for non-data, use the lowest supported rate */ ridx = min_ridx; *flags |= IWX_TX_FLAGS_CMD_RATE; - } else if (ic->ic_fixed_mcs != -1) { - ridx = sc->sc_fixed_ridx; - *flags |= IWX_TX_FLAGS_CMD_RATE; - } else if (ic->ic_fixed_rate != -1) { - ridx = sc->sc_fixed_ridx; - *flags |= IWX_TX_FLAGS_CMD_RATE; } else if (ni->ni_flags & IEEE80211_NODE_HT) { ridx = iwx_mcs2ridx[ni->ni_txmcs]; } else { - uint8_t rval; rval = (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL); ridx = iwx_rval2ridx(rval); if (ridx < min_ridx) @@ -5871,45 +5935,42 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, *flags |= IWX_TX_FLAGS_HIGH_PRI; rinfo = &iwx_rates[ridx]; - if (iwx_is_mimo_ht_plcp(rinfo->ht_plcp)) - rate_flags = IWX_RATE_MCS_ANT_AB_MSK; - else - rate_flags = IWX_RATE_MCS_ANT_A_MSK; - if (IWX_RIDX_IS_CCK(ridx)) - rate_flags |= IWX_RATE_MCS_CCK_MSK_V1; - if ((ni->ni_flags & IEEE80211_NODE_HT) && - type == IEEE80211_FC0_TYPE_DATA && - rinfo->ht_plcp != IWX_RATE_HT_SISO_MCS_INV_PLCP) { - uint8_t sco = IEEE80211_HTOP0_SCO_SCN; - uint8_t vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_HT; - if ((ni->ni_flags & IEEE80211_NODE_VHT) && - IEEE80211_CHAN_80MHZ_ALLOWED(ni->ni_chan) && - ieee80211_node_supports_vht_chan80(ni)) - vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_80; - else if (IEEE80211_CHAN_40MHZ_ALLOWED(ni->ni_chan) && - ieee80211_node_supports_ht_chan40(ni)) - sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK); - if (ni->ni_flags & IEEE80211_NODE_VHT) - rate_flags |= IWX_RATE_MCS_VHT_MSK_V1; + + /* + * Do not fill rate_n_flags if firmware controls the Tx rate. + * For data frames we rely on Tx rate scaling in firmware by default. + */ + if ((*flags & IWX_TX_FLAGS_CMD_RATE) == 0) { + *rate_n_flags = 0; + return rinfo; + } + + /* + * Forcing a CCK/OFDM legacy rate is important for management frames. + * Association will only succeed if we do this correctly. + */ + rate_flags = IWX_RATE_MCS_ANT_A_MSK; + if (IWX_RIDX_IS_CCK(ridx)) { + if (sc->sc_rate_n_flags_version >= 2) + rate_flags |= IWX_RATE_MCS_CCK_MSK; else - rate_flags |= IWX_RATE_MCS_HT_MSK_V1; - if (vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80 && - in->in_phyctxt != NULL && - in->in_phyctxt->vht_chan_width == vht_chan_width) { - rate_flags |= IWX_RATE_MCS_CHAN_WIDTH_80_V1; - if (ieee80211_node_supports_vht_sgi80(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK_V1; - } else if ((sco == IEEE80211_HTOP0_SCO_SCA || - sco == IEEE80211_HTOP0_SCO_SCB) && - in->in_phyctxt != NULL && in->in_phyctxt->sco == sco) { - rate_flags |= IWX_RATE_MCS_CHAN_WIDTH_40_V1; - if (ieee80211_node_supports_ht_sgi40(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK_V1; - } else if (ieee80211_node_supports_ht_sgi20(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK_V1; - *rate_n_flags = rate_flags | rinfo->ht_plcp; + rate_flags |= IWX_RATE_MCS_CCK_MSK_V1; + } else if (sc->sc_rate_n_flags_version >= 2) + rate_flags |= IWX_RATE_MCS_LEGACY_OFDM_MSK; + + rval = (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL); + if (sc->sc_rate_n_flags_version >= 2) { + if (rate_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK) { + rate_flags |= (iwx_fw_rateidx_ofdm(rval) & + IWX_RATE_LEGACY_RATE_MSK); + } else { + rate_flags |= (iwx_fw_rateidx_cck(rval) & + IWX_RATE_LEGACY_RATE_MSK); + } } else - *rate_n_flags = rate_flags | rinfo->plcp; + rate_flags |= rinfo->plcp; + + *rate_n_flags = rate_flags; return rinfo; } @@ -7718,39 +7779,78 @@ iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif) struct ieee80211_node *ni = ic->ic_bss; struct ieee80211_rateset *rs = &ni->ni_rates; uint32_t rate_n_flags; - int i; + uint8_t plcp, rval; + int i, cmd_ver, rate_n_flags_ver2 = 0; if (notif->sta_id != IWX_STATION_ID || (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0) return; rate_n_flags = le32toh(notif->rate); - if (rate_n_flags & IWX_RATE_MCS_VHT_MSK_V1) { - ni->ni_txmcs = (rate_n_flags & - IWX_RATE_VHT_MCS_RATE_CODE_MSK); - ni->ni_vht_ss = ((rate_n_flags & IWX_RATE_VHT_MCS_NSS_MSK) >> - IWX_RATE_VHT_MCS_NSS_POS) + 1; - } else if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) { - ni->ni_txmcs = (rate_n_flags & - (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 | - IWX_RATE_HT_MCS_NSS_MSK_V1)); + + cmd_ver = iwx_lookup_notif_ver(sc, IWX_DATA_PATH_GROUP, + IWX_TLC_MNG_UPDATE_NOTIF); + if (cmd_ver != IWX_FW_CMD_VER_UNKNOWN && cmd_ver >= 3) + rate_n_flags_ver2 = 1; + if (rate_n_flags_ver2) { + uint32_t mod_type = (rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK); + if (mod_type == IWX_RATE_MCS_VHT_MSK) { + ni->ni_txmcs = (rate_n_flags & + IWX_RATE_HT_MCS_CODE_MSK); + ni->ni_vht_ss = ((rate_n_flags & + IWX_RATE_MCS_NSS_MSK) >> + IWX_RATE_MCS_NSS_POS) + 1; + return; + } else if (mod_type == IWX_RATE_MCS_HT_MSK) { + ni->ni_txmcs = IWX_RATE_HT_MCS_INDEX(rate_n_flags); + return; + } } else { - uint8_t plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1); - uint8_t rval = 0; + if (rate_n_flags & IWX_RATE_MCS_VHT_MSK_V1) { + ni->ni_txmcs = (rate_n_flags & + IWX_RATE_VHT_MCS_RATE_CODE_MSK); + ni->ni_vht_ss = ((rate_n_flags & + IWX_RATE_VHT_MCS_NSS_MSK) >> + IWX_RATE_VHT_MCS_NSS_POS) + 1; + return; + } else if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) { + ni->ni_txmcs = (rate_n_flags & + (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 | + IWX_RATE_HT_MCS_NSS_MSK_V1)); + return; + } + } + + if (rate_n_flags_ver2) { + const struct ieee80211_rateset *rs; + uint32_t ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK); + if (rate_n_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK) + rs = &ieee80211_std_rateset_11a; + else + rs = &ieee80211_std_rateset_11b; + if (ridx < rs->rs_nrates) + rval = (rs->rs_rates[ridx] & IEEE80211_RATE_VAL); + else + rval = 0; + } else { + plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1); + + rval = 0; for (i = IWX_RATE_1M_INDEX; i < nitems(iwx_rates); i++) { if (iwx_rates[i].plcp == plcp) { rval = iwx_rates[i].rate; break; } } - if (rval) { - uint8_t rv; - for (i = 0; i < rs->rs_nrates; i++) { - rv = rs->rs_rates[i] & IEEE80211_RATE_VAL; - if (rv == rval) { - ni->ni_txrate = i; - break; - } + } + + if (rval) { + uint8_t rv; + for (i = 0; i < rs->rs_nrates; i++) { + rv = rs->rs_rates[i] & IEEE80211_RATE_VAL; + if (rv == rval) { + ni->ni_txrate = i; + break; } } } @@ -8290,27 +8390,12 @@ iwx_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, int iwx_media_change(struct ifnet *ifp) { - struct iwx_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - uint8_t rate, ridx; int err; err = ieee80211_media_change(ifp); if (err != ENETRESET) return err; - if (ic->ic_fixed_mcs != -1) - sc->sc_fixed_ridx = iwx_mcs2ridx[ic->ic_fixed_mcs]; - else if (ic->ic_fixed_rate != -1) { - rate = ic->ic_sup_rates[ic->ic_curmode]. - rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; - /* Map 802.11 rate to HW rate index. */ - for (ridx = 0; ridx <= IWX_RIDX_MAX; ridx++) - if (iwx_rates[ridx].rate == rate) - break; - sc->sc_fixed_ridx = ridx; - } - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) { iwx_stop(ifp); diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index 64e4a1655ca..daa6489811d 100644 --- a/sys/dev/pci/if_iwxreg.h +++ b/sys/dev/pci/if_iwxreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwxreg.h,v 1.45 2023/03/06 10:31:58 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.46 2023/03/06 10:48:05 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -5093,6 +5093,154 @@ enum { #define IWX_RATE_MCS_CTS_REQUIRED_POS (31) #define IWX_RATE_MCS_CTS_REQUIRED_MSK (1 << IWX_RATE_MCS_CTS_REQUIRED_POS) + +/* rate_n_flags bit field version 2 + * + * The 32-bit value has different layouts in the low 8 bits depending on the + * format. There are three formats, HT, VHT and legacy (11abg, with subformats + * for CCK and OFDM). + * + */ + +/* Bits 10-8: rate format + * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT) + * (3) Very High-throughput (VHT) (4) High-efficiency (HE) + * (5) Extremely High-throughput (EHT) + */ +#define IWX_RATE_MCS_MOD_TYPE_POS 8 +#define IWX_RATE_MCS_MOD_TYPE_MSK (0x7 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_CCK_MSK (0 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_LEGACY_OFDM_MSK (1 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_HT_MSK (2 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_VHT_MSK (3 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_HE_MSK (4 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_EHT_MSK (5 << IWX_RATE_MCS_MOD_TYPE_POS) + +/* + * Legacy CCK rate format for bits 0:3: + * + * (0) 0xa - 1 Mbps + * (1) 0x14 - 2 Mbps + * (2) 0x37 - 5.5 Mbps + * (3) 0x6e - 11 nbps + * + * Legacy OFDM rate format for bits 0:3: + * + * (0) 6 Mbps + * (1) 9 Mbps + * (2) 12 Mbps + * (3) 18 Mbps + * (4) 24 Mbps + * (5) 36 Mbps + * (6) 48 Mbps + * (7) 54 Mbps + * + */ +#define IWX_RATE_LEGACY_RATE_MSK 0x7 + +/* + * HT, VHT, HE, EHT rate format for bits 3:0 + * 3-0: MCS + * + */ +#define IWX_RATE_HT_MCS_CODE_MSK 0x7 +#define IWX_RATE_MCS_NSS_POS 4 +#define IWX_RATE_MCS_NSS_MSK (1 << IWX_RATE_MCS_NSS_POS) +#define IWX_RATE_MCS_CODE_MSK 0xf +#define IWX_RATE_HT_MCS_INDEX(r) ((((r) & IWX_RATE_MCS_NSS_MSK) >> 1) | \ + ((r) & IWX_RATE_HT_MCS_CODE_MSK)) + +/* Bits 7-5: reserved */ + +/* + * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz + */ +#define IWX_RATE_MCS_CHAN_WIDTH_MSK (0x7 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_20 (0 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_40 (1 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_80 (2 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_160 (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_320 (4 << IWX_RATE_MCS_CHAN_WIDTH_POS) + +/* Bit 15-14: Antenna selection: + * Bit 14: Ant A active + * Bit 15: Ant B active + * + * All relevant definitions are same as in v1 + */ + +/* Bit 16 (1) LDPC enables, (0) LDPC disabled */ +#define IWX_RATE_MCS_LDPC_POS 16 +#define IWX_RATE_MCS_LDPC_MSK (1 << IWX_RATE_MCS_LDPC_POS) + +/* Bit 17: (0) SS, (1) SS*2 (same as v1) */ + +/* Bit 18: OFDM-HE dual carrier mode (same as v1) */ + +/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */ + +/* + * Bit 22-20: HE LTF type and guard interval + * CCK: + * 0 long preamble + * 1 short preamble + * HT/VHT: + * 0 0.8us + * 1 0.4us + * HE (ext) SU: + * 0 1xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * 4 4xLTF+0.8us + * HE MU: + * 0 4xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * HE TRIG: + * 0 1xLTF+1.6us + * 1 2xLTF+1.6us + * 2 4xLTF+3.2us + * */ +#define IWX_RATE_MCS_HE_GI_LTF_MSK (0x7 << IWX_RATE_MCS_HE_GI_LTF_POS) +#define IWX_RATE_MCS_SGI_POS IWX_RATE_MCS_HE_GI_LTF_POS +#define IWX_RATE_MCS_SGI_MSK (1 << IWX_RATE_MCS_SGI_POS) +#define IWX_RATE_MCS_HE_SU_4_LTF 3 +#define IWX_RATE_MCS_HE_SU_4_LTF_08_GI 4 + +/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define IWX_RATE_MCS_HE_TYPE_POS 23 +#define IWX_RATE_MCS_HE_TYPE_SU (0 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_EXT_SU (1 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_MU (2 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_TRIG (3 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_MSK (3 << IWX_RATE_MCS_HE_TYPE_POS) + +/* Bit 25: duplicate channel enabled + * + * if this bit is set, duplicate is according to BW (bits 11-13): + * + * CCK: 2x 20MHz + * OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16) + * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160) + * */ +#define IWX_RATE_MCS_DUP_POS 25 +#define IWX_RATE_MCS_DUP_MSK (1 << IWX_RATE_MCS_DUP_POS) + +/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define IWX_RATE_MCS_HE_106T_POS 26 +#define IWX_RATE_MCS_HE_106T_MSK (1 << IWX_RATE_MCS_HE_106T_POS) + +/* Bit 27: EHT extra LTF: + * instead of 1 LTF for SISO use 2 LTFs, + * instead of 2 LTFs for NSTS=2 use 4 LTFs*/ +#define IWX_RATE_MCS_EHT_EXTRA_LTF_POS 27 +#define IWX_RATE_MCS_EHT_EXTRA_LTF_MSK (1 << IWX_RATE_MCS_EHT_EXTRA_LTF_POS) + +/* Bit 31-28: reserved */ + + /* Link Quality definitions */ /* # entries in rate scale table to support Tx retries */ @@ -5447,10 +5595,14 @@ struct iwx_dram_sec_info { * @IWX_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate * selection, retry limits and BT kill */ +/* Valid for TX_FLAGS_BITS_API_S_VER_3: */ #define IWX_TX_FLAGS_CMD_RATE (1 << 0) #define IWX_TX_FLAGS_ENCRYPT_DIS (1 << 1) #define IWX_TX_FLAGS_HIGH_PRI (1 << 2) -/* TX_FLAGS_BITS_API_S_VER_3 */ +/* Valid for TX_FLAGS_BITS_API_S_VER_4 and above: */ +#define IWX_TX_FLAGS_RTS (1 << 3) +#define IWX_TX_FLAGS_CTS (1 << 4) +/* TX_FLAGS_BITS_API_S_VER_4 */ /** * struct iwx_tx_cmd_gen2 - TX command struct to FW for 22000 devices diff --git a/sys/dev/pci/if_iwxvar.h b/sys/dev/pci/if_iwxvar.h index 13dc72e83b0..76489aa52eb 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.38 2023/03/06 10:16:17 stsp Exp $ */ +/* $OpenBSD: if_iwxvar.h,v 1.39 2023/03/06 10:48:05 stsp Exp $ */ /* * Copyright (c) 2014 genua mbh @@ -712,6 +712,7 @@ struct iwx_softc { #define IWX_MAX_FW_CMD_VERSIONS 704 struct iwx_fw_cmd_version cmd_versions[IWX_MAX_FW_CMD_VERSIONS]; int n_cmd_versions; + int sc_rate_n_flags_version; int sc_intmask; int sc_flags; @@ -746,8 +747,6 @@ struct iwx_softc { int sc_scan_last_antenna; - int sc_fixed_ridx; - int sc_staid; int sc_nodecolor;