-/* $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 <info@genua.de>
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);
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,
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
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
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)
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;
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.
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;
/* 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)
*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;
}
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;
}
}
}
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);
-/* $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,
#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 */
* @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