summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_iwm.c
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2021-07-07 08:21:32 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2021-07-07 08:21:32 +0000
commit216dddbeb2e2a738c6c824f9cb26d2ca433580b0 (patch)
tree807263b948eabe511e3938138d141725e35e4c66 /sys/dev/pci/if_iwm.c
parentff1233aecc535e9bf64ee51400c84d5ed4733d5b (diff)
Support the larger phy context command required by newer iwm(4) firmware.
Diffstat (limited to 'sys/dev/pci/if_iwm.c')
-rw-r--r--sys/dev/pci/if_iwm.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index ed8f3c7ae91..ac4d3526290 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwm.c,v 1.335 2021/07/07 08:13:37 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.336 2021/07/07 08:21:31 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -402,6 +402,8 @@ void iwm_rx_compressed_ba(struct iwm_softc *, struct iwm_rx_packet *,
void iwm_rx_bmiss(struct iwm_softc *, struct iwm_rx_packet *,
struct iwm_rx_data *);
int iwm_binding_cmd(struct iwm_softc *, struct iwm_node *, uint32_t);
+int iwm_phy_ctxt_cmd_uhb(struct iwm_softc *, struct iwm_phy_ctxt *, uint8_t,
+ uint8_t, uint32_t, uint32_t);
void iwm_phy_ctxt_cmd_hdr(struct iwm_softc *, struct iwm_phy_ctxt *,
struct iwm_phy_context_cmd *, uint32_t, uint32_t);
void iwm_phy_ctxt_cmd_data(struct iwm_softc *, struct iwm_phy_context_cmd *,
@@ -5743,12 +5745,57 @@ iwm_phy_ctxt_cmd_data(struct iwm_softc *sc, struct iwm_phy_context_cmd *cmd,
}
int
+iwm_phy_ctxt_cmd_uhb(struct iwm_softc *sc, struct iwm_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 iwm_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(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,
+ ctxt->color));
+ cmd.action = htole32(action);
+ cmd.apply_time = htole32(apply_time);
+
+ cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
+ IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
+ cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));
+ cmd.ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
+ cmd.ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+
+ idle_cnt = chains_static;
+ active_cnt = chains_dynamic;
+ cmd.rxchain_info = htole32(iwm_fw_valid_rx_ant(sc) <<
+ IWM_PHY_RX_CHAIN_VALID_POS);
+ cmd.rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
+ cmd.rxchain_info |= htole32(active_cnt <<
+ IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
+ cmd.txchain_info = htole32(iwm_fw_valid_tx_ant(sc));
+
+ return iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
+}
+
+int
iwm_phy_ctxt_cmd(struct iwm_softc *sc, struct iwm_phy_ctxt *ctxt,
uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
uint32_t apply_time)
{
struct iwm_phy_context_cmd cmd;
+ /*
+ * Intel increased the size of the fw_channel_info struct and neglected
+ * to bump the phy_context_cmd struct, which contains an fw_channel_info
+ * member in the middle.
+ * To keep things simple we use a separate function to handle the larger
+ * variant of the phy context command.
+ */
+ if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS))
+ return iwm_phy_ctxt_cmd_uhb(sc, ctxt, chains_static,
+ chains_dynamic, action, apply_time);
+
iwm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
iwm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,