diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-07-29 11:56:54 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2021-07-29 11:56:54 +0000 |
commit | 7fba5538266a3d08fbea2c38469b9012ec123dff (patch) | |
tree | 2b2260b01a8ec95686621bdd6a225be60963992d | |
parent | d648c3626c78c3e67f53694d560968637c6c07c4 (diff) |
Handle iwx(4) PHY context command version 3.
ok kevlo@
-rw-r--r-- | sys/dev/pci/if_iwx.c | 96 | ||||
-rw-r--r-- | sys/dev/pci/if_iwxreg.h | 40 |
2 files changed, 130 insertions, 6 deletions
diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index fa02c31ef57..81627b46d19 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.78 2021/07/29 11:56:21 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.79 2021/07/29 11:56:53 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -357,6 +357,10 @@ void iwx_rx_tx_cmd(struct iwx_softc *, struct iwx_rx_packet *, void iwx_rx_bmiss(struct iwx_softc *, struct iwx_rx_packet *, struct iwx_rx_data *); int iwx_binding_cmd(struct iwx_softc *, struct iwx_node *, uint32_t); +int iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, + uint8_t, uint32_t); +int iwx_phy_ctxt_cmd_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, + uint8_t, uint32_t); int iwx_phy_ctxt_cmd_uhb(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, uint8_t, uint32_t, uint32_t); int iwx_phy_ctxt_cmd(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, @@ -4441,12 +4445,86 @@ iwx_binding_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action) } int +iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, + uint8_t chains_static, uint8_t chains_dynamic, uint32_t action) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct iwx_phy_context_cmd_uhb cmd; + uint8_t active_cnt, idle_cnt; + struct ieee80211_channel *chan = ctxt->channel; + + memset(&cmd, 0, sizeof(cmd)); + cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id, + ctxt->color)); + cmd.action = htole32(action); + + if (IEEE80211_IS_CHAN_2GHZ(ctxt->channel) || + !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT)) + cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX); + else + cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX); + + cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ? + IWX_PHY_BAND_24 : IWX_PHY_BAND_5; + cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan)); + cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20; + cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW; + + idle_cnt = chains_static; + active_cnt = chains_dynamic; + cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) << + IWX_PHY_RX_CHAIN_VALID_POS); + cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS); + cmd.rxchain_info |= htole32(active_cnt << + IWX_PHY_RX_CHAIN_MIMO_CNT_POS); + + return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd); +} + +int +iwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, + uint8_t chains_static, uint8_t chains_dynamic, uint32_t action) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct iwx_phy_context_cmd cmd; + uint8_t active_cnt, idle_cnt; + struct ieee80211_channel *chan = ctxt->channel; + + memset(&cmd, 0, sizeof(cmd)); + cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id, + ctxt->color)); + cmd.action = htole32(action); + + if (IEEE80211_IS_CHAN_2GHZ(ctxt->channel) || + !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT)) + cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX); + else + cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX); + + cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ? + IWX_PHY_BAND_24 : IWX_PHY_BAND_5; + cmd.ci.channel = ieee80211_chan2ieee(ic, chan); + cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20; + cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW; + + idle_cnt = chains_static; + active_cnt = chains_dynamic; + cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) << + IWX_PHY_RX_CHAIN_VALID_POS); + cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS); + cmd.rxchain_info |= htole32(active_cnt << + IWX_PHY_RX_CHAIN_MIMO_CNT_POS); + + return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd); +} + +int iwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, uint8_t chains_static, uint8_t chains_dynamic, uint32_t action, uint32_t apply_time) { struct ieee80211com *ic = &sc->sc_ic; - struct iwx_phy_context_cmd_uhb cmd; + struct iwx_phy_context_cmd_uhb_v1 cmd; uint8_t active_cnt, idle_cnt; struct ieee80211_channel *chan = ctxt->channel; @@ -4480,9 +4558,10 @@ iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, uint32_t apply_time) { struct ieee80211com *ic = &sc->sc_ic; - struct iwx_phy_context_cmd cmd; + struct iwx_phy_context_cmd_v1 cmd; uint8_t active_cnt, idle_cnt; struct ieee80211_channel *chan = ctxt->channel; + int cmdver; /* * Intel increased the size of the fw_channel_info struct and neglected @@ -4491,6 +4570,17 @@ iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, * To keep things simple we use a separate function to handle the larger * variant of the phy context command. */ + cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONTEXT_CMD); + if (cmdver == 3) { + /* Version 3 differs in the "data" portion of the command. */ + if (isset(sc->sc_enabled_capa, + IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS)) { + return iwx_phy_ctxt_cmd_uhb_v3(sc, ctxt, chains_static, + chains_dynamic, action); + } + return iwx_phy_ctxt_cmd_v3(sc, ctxt, chains_static, + chains_dynamic, action); + } if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS)) return iwx_phy_ctxt_cmd_uhb(sc, ctxt, chains_static, chains_dynamic, action, apply_time); diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index fc05171a70e..26231b92db5 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.23 2021/07/29 11:53:46 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.24 2021/07/29 11:56:53 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -2924,6 +2924,40 @@ struct iwx_fw_channel_info { /* TODO: fix the value, make it depend on firmware at runtime? */ #define IWX_NUM_PHY_CTX 3 +/** + * struct iwl_phy_context_cmd - config of the PHY context + * ( IWX_PHY_CONTEXT_CMD = 0x8 ) + * @id_and_color: ID and color of the relevant Binding + * @action: action to perform, one of IWX_FW_CTXT_ACTION_* + * @lmac_id: the lmac id the phy context belongs to + * @ci: channel info + * @rxchain_info: ??? + * @dsp_cfg_flags: set to 0 + * @reserved: reserved to align to 64 bit + */ +struct iwx_phy_context_cmd_uhb { + /* COMMON_INDEX_HDR_API_S_VER_1 */ + uint32_t id_and_color; + uint32_t action; + /* PHY_CONTEXT_DATA_API_S_VER_3 */ + struct iwx_fw_channel_info ci; + uint32_t lmac_id; + uint32_t rxchain_info; + uint32_t dsp_cfg_flags; + uint32_t reserved; +} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */ +struct iwx_phy_context_cmd { + /* COMMON_INDEX_HDR_API_S_VER_1 */ + uint32_t id_and_color; + uint32_t action; + /* PHY_CONTEXT_DATA_API_S_VER_3 */ + struct iwx_fw_channel_info_v1 ci; + uint32_t lmac_id; + uint32_t rxchain_info; + uint32_t dsp_cfg_flags; + uint32_t reserved; +} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */ + /* TODO: complete missing documentation */ /** * struct iwx_phy_context_cmd - config of the PHY context @@ -2947,7 +2981,7 @@ struct iwx_fw_channel_info { * magic with pointers to struct members instead.) */ /* This version must be used if IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS is set: */ -struct iwx_phy_context_cmd_uhb { +struct iwx_phy_context_cmd_uhb_v1 { /* COMMON_INDEX_HDR_API_S_VER_1 */ uint32_t id_and_color; uint32_t action; @@ -2961,7 +2995,7 @@ struct iwx_phy_context_cmd_uhb { uint32_t dsp_cfg_flags; } __packed; /* IWX_PHY_CONTEXT_CMD_API_VER_1 */ /* This version must be used otherwise: */ -struct iwx_phy_context_cmd { +struct iwx_phy_context_cmd_v1 { /* COMMON_INDEX_HDR_API_S_VER_1 */ uint32_t id_and_color; uint32_t action; |