diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2023-03-06 10:52:17 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2023-03-06 10:52:17 +0000 |
commit | 1a84000f4f3ad0b9ea49a6b8f46f802269b24ddf (patch) | |
tree | 009b8668381988ad4cb6b5785fcb9ffbb0dae4fe /sys/dev/pci | |
parent | 1a6e99be598fbbd27a554a4157055f5b33fbc04e (diff) |
add support for the iwx RLC config command
New firmware wants to be told about MIMO antenna configuration via
a separate command, rather than via the good old PHY context command.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_iwx.c | 82 | ||||
-rw-r--r-- | sys/dev/pci/if_iwxreg.h | 57 |
2 files changed, 123 insertions, 16 deletions
diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 90e45ec0080..5b98d32c504 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.158 2023/03/06 10:48:05 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.159 2023/03/06 10:52:16 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -454,6 +454,8 @@ 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_send_rlc(struct iwx_softc *, struct iwx_phy_ctxt *, + uint8_t, uint8_t); int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *, struct ieee80211_channel *, uint8_t, uint8_t, uint32_t, uint8_t, uint8_t); @@ -5505,13 +5507,17 @@ iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, 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); + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) != 2) { + 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); } @@ -5561,13 +5567,17 @@ iwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, 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); + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) != 2) { + 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); } @@ -7857,6 +7867,30 @@ iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif) } int +iwx_phy_send_rlc(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, + uint8_t chains_static, uint8_t chains_dynamic) +{ + struct iwx_rlc_config_cmd cmd; + uint32_t cmd_id; + uint8_t active_cnt, idle_cnt; + + memset(&cmd, 0, sizeof(cmd)); + + idle_cnt = chains_static; + active_cnt = chains_dynamic; + + cmd.phy_id = htole32(phyctxt->id), + cmd.rlc.rx_chain_info = htole32(iwx_fw_valid_rx_ant(sc) << + IWX_PHY_RX_CHAIN_VALID_POS); + cmd.rlc.rx_chain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS); + cmd.rlc.rx_chain_info |= htole32(active_cnt << + IWX_PHY_RX_CHAIN_MIMO_CNT_POS); + + cmd_id = iwx_cmd_id(IWX_RLC_CONFIG_CMD, IWX_DATA_PATH_GROUP, 2); + return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd); +} + +int iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, struct ieee80211_channel *chan, uint8_t chains_static, uint8_t chains_dynamic, uint32_t apply_time, uint8_t sco, @@ -7900,6 +7934,12 @@ iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, phyctxt->sco = sco; phyctxt->vht_chan_width = vht_chan_width; + + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) == 2) + return iwx_phy_send_rlc(sc, phyctxt, + chains_static, chains_dynamic); + return 0; } @@ -8865,6 +8905,15 @@ iwx_init_hw(struct iwx_softc *sc) DEVNAME(sc), i, err); goto err; } + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) == 2) { + err = iwx_phy_send_rlc(sc, &sc->sc_phyctxt[i], 1, 1); + if (err) { + printf("%s: could not configure RLC for PHY " + "%d (error %d)\n", DEVNAME(sc), i, err); + goto err; + } + } } err = iwx_config_ltr(sc); @@ -9907,6 +9956,9 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) break; } + case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RLC_CONFIG_CMD): + break; + case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP, IWX_PNVM_INIT_COMPLETE): sc->sc_init_complete |= IWX_PNVM_COMPLETE; diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index daa6489811d..fc8ef4436b3 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.46 2023/03/06 10:48:05 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.47 2023/03/06 10:52:16 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -2004,6 +2004,7 @@ struct iwx_tx_queue_cfg_rsp { /* DATA_PATH group subcommand IDs */ #define IWX_DQA_ENABLE_CMD 0x00 +#define IWX_RLC_CONFIG_CMD 0x08 #define IWX_TLC_MNG_CONFIG_CMD 0x0f #define IWX_RX_NO_DATA_NOTIF 0xf5 #define IWX_TLC_MNG_UPDATE_NOTIF 0xf7 @@ -5272,6 +5273,60 @@ enum { #define IWX_LQ_FLAG_DYNAMIC_BW_POS 6 #define IWX_LQ_FLAG_DYNAMIC_BW_MSK (1 << IWX_LQ_FLAG_DYNAMIC_BW_POS) +#define IWX_RLC_CHAIN_INFO_DRIVER_FORCE (1 << 0) +#define IWL_RLC_CHAIN_INFO_VALID 0x000e +#define IWL_RLC_CHAIN_INFO_FORCE 0x0070 +#define IWL_RLC_CHAIN_INFO_FORCE_MIMO 0x0380 +#define IWL_RLC_CHAIN_INFO_COUNT 0x0c00 +#define IWL_RLC_CHAIN_INFO_MIMO_COUNT 0x3000 + +/** + * struct iwx_rlc_properties - RLC properties + * @rx_chain_info: RX chain info, IWX_RLC_CHAIN_INFO_* + * @reserved: reserved + */ +struct iwx_rlc_properties { + uint32_t rx_chain_info; + uint32_t reserved; +} __packed; /* RLC_PROPERTIES_S_VER_1 */ + +#define IWX_SAD_MODE_ENABLED (1 << 0) +#define IWX_SAD_MODE_DEFAULT_ANT_MSK 0x6 +#define IWX_SAD_MODE_DEFAULT_ANT_FW 0x0 +#define IWX_SAD_MODE_DEFAULT_ANT_A 0x2 +#define IWX_SAD_MODE_DEFAULT_ANT_B 0x4 + +/** + * struct iwx_sad_properties - SAD properties + * @chain_a_sad_mode: chain A SAD mode, IWX_SAD_MODE_* + * @chain_b_sad_mode: chain B SAD mode, IWX_SAD_MODE_* + * @mac_id: MAC index + * @reserved: reserved + */ +struct iwx_sad_properties { + uint32_t chain_a_sad_mode; + uint32_t chain_b_sad_mode; + uint32_t mac_id; + uint32_t reserved; +} __packed; + +/** + * struct iwx_rlc_config_cmd - RLC configuration + * @phy_id: PHY index + * @rlc: RLC properties, &struct iwx_rlc_properties + * @sad: SAD (single antenna diversity) options, &struct iwx_sad_properties + * @flags: flags, IWX_RLC_FLAGS_* + * @reserved: reserved + */ +struct iwx_rlc_config_cmd { + uint32_t phy_id; + struct iwx_rlc_properties rlc; + struct iwx_sad_properties sad; + uint8_t flags; + uint8_t reserved[3]; +} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */ + + /** * Options for TLC config flags * @IWX_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for |