From: stsp Date: Mon, 6 Mar 2023 10:28:04 +0000 (+0000) Subject: add support for iwx TLC config command v4 X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=69c5ca4e6fe59fa6a46104b045a3f348425f3949;p=openbsd add support for iwx TLC config command v4 --- diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 6491f113aaa..4c92ab3041b 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.155 2023/03/06 10:24:15 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.156 2023/03/06 10:28:04 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -449,6 +449,8 @@ int iwx_enable_mgmt_queue(struct iwx_softc *); int iwx_rs_rval2idx(uint8_t); uint16_t iwx_rs_ht_rates(struct iwx_softc *, struct ieee80211_node *, int); uint16_t iwx_rs_vht_rates(struct iwx_softc *, struct ieee80211_node *, int); +int iwx_rs_init_v3(struct iwx_softc *, struct iwx_node *); +int iwx_rs_init_v4(struct iwx_softc *, struct iwx_node *); int iwx_rs_init(struct iwx_softc *, struct iwx_node *); int iwx_enable_data_tx_queues(struct iwx_softc *); int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *, @@ -7562,11 +7564,11 @@ iwx_rs_vht_rates(struct iwx_softc *sc, struct ieee80211_node *ni, int num_ss) } int -iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) +iwx_rs_init_v3(struct iwx_softc *sc, struct iwx_node *in) { struct ieee80211_node *ni = &in->in_ni; struct ieee80211_rateset *rs = &ni->ni_rates; - struct iwx_tlc_config_cmd cfg_cmd; + struct iwx_tlc_config_cmd_v3 cfg_cmd; uint32_t cmd_id; int i; size_t cmd_size = sizeof(cfg_cmd); @@ -7583,16 +7585,16 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) if (ni->ni_flags & IEEE80211_NODE_VHT) { cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT; - cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_vht_rates(sc, ni, 1)); - cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_vht_rates(sc, ni, 2)); } else if (ni->ni_flags & IEEE80211_NODE_HT) { cfg_cmd.mode = IWX_TLC_MNG_MODE_HT; - cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, IEEE80211_HT_RATESET_SISO)); - cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, IEEE80211_HT_RATESET_MIMO2)); } else @@ -7629,6 +7631,86 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd); } +int +iwx_rs_init_v4(struct iwx_softc *sc, struct iwx_node *in) +{ + struct ieee80211_node *ni = &in->in_ni; + struct ieee80211_rateset *rs = &ni->ni_rates; + struct iwx_tlc_config_cmd_v4 cfg_cmd; + uint32_t cmd_id; + int i; + size_t cmd_size = sizeof(cfg_cmd); + + memset(&cfg_cmd, 0, sizeof(cfg_cmd)); + + for (i = 0; i < rs->rs_nrates; i++) { + uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL; + int idx = iwx_rs_rval2idx(rval); + if (idx == -1) + return EINVAL; + cfg_cmd.non_ht_rates |= (1 << idx); + } + + if (ni->ni_flags & IEEE80211_NODE_VHT) { + cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT; + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_vht_rates(sc, ni, 1)); + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_vht_rates(sc, ni, 2)); + } else if (ni->ni_flags & IEEE80211_NODE_HT) { + cfg_cmd.mode = IWX_TLC_MNG_MODE_HT; + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_ht_rates(sc, ni, + IEEE80211_HT_RATESET_SISO)); + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_ht_rates(sc, ni, + IEEE80211_HT_RATESET_MIMO2)); + } else + cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT; + + cfg_cmd.sta_id = IWX_STATION_ID; + if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80) + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ; + else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA || + in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB) + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ; + else + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ; + cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK; + if (ni->ni_flags & IEEE80211_NODE_VHT) + cfg_cmd.max_mpdu_len = htole16(3895); + else + cfg_cmd.max_mpdu_len = htole16(3839); + if (ni->ni_flags & IEEE80211_NODE_HT) { + if (ieee80211_node_supports_ht_sgi20(ni)) { + cfg_cmd.sgi_ch_width_supp |= (1 << + IWX_TLC_MNG_CH_WIDTH_20MHZ); + } + if (ieee80211_node_supports_ht_sgi40(ni)) { + cfg_cmd.sgi_ch_width_supp |= (1 << + IWX_TLC_MNG_CH_WIDTH_40MHZ); + } + } + if ((ni->ni_flags & IEEE80211_NODE_VHT) && + ieee80211_node_supports_vht_sgi80(ni)) + cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_80MHZ); + + cmd_id = iwx_cmd_id(IWX_TLC_MNG_CONFIG_CMD, IWX_DATA_PATH_GROUP, 0); + return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd); +} + +int +iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) +{ + int cmd_ver; + + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_TLC_MNG_CONFIG_CMD); + if (cmd_ver == 4) + return iwx_rs_init_v4(sc, in); + return iwx_rs_init_v3(sc, in); +} + void iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif) { diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index 3d0f5d9309b..e3ad7178e32 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.43 2023/03/06 10:24:15 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.44 2023/03/06 10:28:04 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -5109,14 +5109,14 @@ enum { * @IWX_TLC_MNG_CH_WIDTH_40MHZ: 40MHZ channel * @IWX_TLC_MNG_CH_WIDTH_80MHZ: 80MHZ channel * @IWX_TLC_MNG_CH_WIDTH_160MHZ: 160MHZ channel - * @IWX_TLC_MNG_CH_WIDTH_LAST: maximum value + * @IWX_TLC_MNG_CH_WIDTH_320MHZ: 320MHZ channel */ enum iwx_tlc_mng_cfg_cw { IWX_TLC_MNG_CH_WIDTH_20MHZ, IWX_TLC_MNG_CH_WIDTH_40MHZ, IWX_TLC_MNG_CH_WIDTH_80MHZ, IWX_TLC_MNG_CH_WIDTH_160MHZ, - IWX_TLC_MNG_CH_WIDTH_LAST = IWX_TLC_MNG_CH_WIDTH_160MHZ, + IWX_TLC_MNG_CH_WIDTH_320MHZ, }; /** @@ -5134,8 +5134,7 @@ enum iwx_tlc_mng_cfg_cw { * @IWX_TLC_MNG_MODE_HT: enable HT * @IWX_TLC_MNG_MODE_VHT: enable VHT * @IWX_TLC_MNG_MODE_HE: enable HE - * @IWX_TLC_MNG_MODE_INVALID: invalid value - * @IWX_TLC_MNG_MODE_NUM: a count of possible modes + * @IWX_TLC_MNG_MODE_EHT: enable EHT */ enum iwx_tlc_mng_cfg_mode { IWX_TLC_MNG_MODE_CCK = 0, @@ -5144,8 +5143,7 @@ enum iwx_tlc_mng_cfg_mode { IWX_TLC_MNG_MODE_HT, IWX_TLC_MNG_MODE_VHT, IWX_TLC_MNG_MODE_HE, - IWX_TLC_MNG_MODE_INVALID, - IWX_TLC_MNG_MODE_NUM = IWX_TLC_MNG_MODE_INVALID, + IWX_TLC_MNG_MODE_EHT, }; /** @@ -5183,11 +5181,23 @@ enum iwx_tlc_mng_ht_rates { #define IWX_TLC_NSS_2 1 #define IWX_TLC_NSS_MAX 2 -#define IWX_TLC_HT_BW_NONE_160 0 -#define IWX_TLC_HT_BW_160 1 /** - * struct iwx_tlc_config_cmd - TLC configuration + * IWX_TLC_MCS_PER_BW - mcs index per BW + * @IWX_TLC_MCS_PER_BW_80: mcs for bw - 20Hhz, 40Hhz, 80Hhz + * @IWX_TLC_MCS_PER_BW_160: mcs for bw - 160Mhz + * @IWX_TLC_MCS_PER_BW_320: mcs for bw - 320Mhz + * @IWX_TLC_MCS_PER_BW_NUM_V3: number of entries up to version 3 + * @IWX_TLC_MCS_PER_BW_NUM_V4: number of entries from version 4 + */ +#define IWX_TLC_MCS_PER_BW_80 0 +#define IWX_TLC_MCS_PER_BW_160 1 +#define IWX_TLC_MCS_PER_BW_320 2 +#define IWX_TLC_MCS_PER_BW_NUM_V3 (IWX_TLC_MCS_PER_BW_160 + 1) +#define IWX_TLC_MCS_PER_BW_NUM_V4 (IWX_TLC_MCS_PER_BW_320 + 1) + +/** + * struct iwx_tlc_config_cmd_v3 - TLC configuration version 3 * @sta_id: station id * @reserved1: reserved * @max_ch_width: max supported channel width from @enum iwx_tlc_mng_cfg_cw @@ -5196,16 +5206,16 @@ enum iwx_tlc_mng_ht_rates { * @amsdu: 1 = TX amsdu is supported, 0 = not supported * @flags: bitmask of IWX_TLC_MNG_CFG_* * @non_ht_rates: bitmap of supported legacy rates - * @ht_rates: bitmap of &enum iwx_tlc_mng_ht_rates, per + * @ht_rates: MCS index 0 - 11, per * pair (0 - 80mhz width and below, 1 - 160mhz). * @max_mpdu_len: max MPDU length, in bytes * @sgi_ch_width_supp: bitmap of SGI support per channel width - * use (1 << @enum iwx_tlc_mng_cfg_cw) + * use (1 << IWX_TLC_MNG_CFG_CW_*) * @reserved2: reserved * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI), * set zero for no limit. */ -struct iwx_tlc_config_cmd { +struct iwx_tlc_config_cmd_v3 { uint8_t sta_id; uint8_t reserved1[3]; uint8_t max_ch_width; @@ -5214,13 +5224,44 @@ struct iwx_tlc_config_cmd { uint8_t amsdu; uint16_t flags; uint16_t non_ht_rates; - uint16_t ht_rates[IWX_TLC_NSS_MAX][2]; + uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V3]; uint16_t max_mpdu_len; uint8_t sgi_ch_width_supp; uint8_t reserved2; uint32_t max_tx_op; } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */ +/** + * struct iwx_tlc_config_cmd_v4 - TLC configuration + * @sta_id: station id + * @reserved1: reserved + * @max_ch_width: max supported channel width from @enum iwx_tlc_mng_cfg_cw + * @mode: &enum iwx_tlc_mng_cfg_mode + * @chains: bitmask of IWX_TLC_MNG_CHAIN_*_MSK + * @sgi_ch_width_supp: bitmap of SGI support per channel width + * use (1 << IWX_TLC_MNG_CFG_CW_*) + * @flags: bitmask of IWX_TLC_MNG_CFG_* + * @non_ht_rates: bitmap of supported legacy rates + * @ht_rates: MCS index 0 - 11, per + * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz). + * @max_mpdu_len: max MPDU length, in bytes + * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI), + * set zero for no limit. + */ +struct iwx_tlc_config_cmd_v4 { + uint8_t sta_id; + uint8_t reserved1[3]; + uint8_t max_ch_width; + uint8_t mode; + uint8_t chains; + uint8_t sgi_ch_width_supp; + uint16_t flags; + uint16_t non_ht_rates; + uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V4]; + uint16_t max_mpdu_len; + uint16_t max_tx_op; +} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */ + /** * @IWX_TLC_NOTIF_FLAG_RATE: last initial rate update * @IWX_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update @@ -5233,7 +5274,8 @@ struct iwx_tlc_config_cmd { * @sta_id: station id * @reserved: reserved * @flags: bitmap of notifications reported - * @rate: current initial rate + * @rate: current initial rate; using rate_n_flags version 1 if notification + * version is < 3 at run-time, else rate_n_flags version 2 * @amsdu_size: Max AMSDU size, in bytes * @amsdu_enabled: bitmap for per-TID AMSDU enablement */