Page MenuHomeFreeBSD

D60082.diff
No OneTemporary

D60082.diff

diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -5023,8 +5023,11 @@
* going to be overwritten in the other flows.
* For now use the first channel we have.
*/
- if ((error = iwm_phy_ctxt_add(sc,
- &sc->sc_phyctxt[i], &ic->ic_channels[1], 1, 1)) != 0)
+ sc->sc_phyctxt[i].id = i;
+ sc->sc_phyctxt[i].channel = &ic->ic_channels[1];
+ error = iwm_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,
+ IWM_FW_CTXT_ACTION_ADD, 0, IEEE80211_HTINFO_2NDCHAN_NONE);
+ if (error)
goto error;
}
@@ -6456,6 +6459,7 @@
ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
for (i = 0; i < nitems(sc->sc_phyctxt); i++) {
sc->sc_phyctxt[i].id = i;
+ sc->sc_phyctxt[i].sco = IEEE80211_HTINFO_2NDCHAN_NONE;
sc->sc_phyctxt[i].color = 0;
sc->sc_phyctxt[i].ref = 0;
sc->sc_phyctxt[i].channel = NULL;
diff --git a/sys/dev/iwm/if_iwm_phy_ctxt.h b/sys/dev/iwm/if_iwm_phy_ctxt.h
--- a/sys/dev/iwm/if_iwm_phy_ctxt.h
+++ b/sys/dev/iwm/if_iwm_phy_ctxt.h
@@ -113,4 +113,9 @@
struct iwm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic);
+extern 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, uint8_t sco);
+
#endif /* __IF_IWM_PHY_CTXT_H__ */
diff --git a/sys/dev/iwm/if_iwm_phy_ctxt.c b/sys/dev/iwm/if_iwm_phy_ctxt.c
--- a/sys/dev/iwm/if_iwm_phy_ctxt.c
+++ b/sys/dev/iwm/if_iwm_phy_ctxt.c
@@ -188,7 +188,7 @@
static void
iwm_phy_ctxt_cmd_data(struct iwm_softc *sc,
struct iwm_phy_context_cmd *cmd, struct ieee80211_channel *chan,
- uint8_t chains_static, uint8_t chains_dynamic)
+ uint8_t chains_static, uint8_t chains_dynamic, uint8_t sco)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t active_cnt, idle_cnt;
@@ -209,11 +209,23 @@
IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
cmd->ci.channel = ieee80211_chan2ieee(ic, chan);
-
- /* TODO: HT40 */
- /* TODO: VHT40/VHT80 */
- cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
- cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ if (IEEE80211_IS_CHAN_HT40(chan)) {
+ if (sco == IEEE80211_HTINFO_2NDCHAN_ABOVE) {
+ /* secondary chan above -> control chan below */
+ cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE40;
+ } else if (sco == IEEE80211_HTINFO_2NDCHAN_BELOW) {
+ /* secondary chan below -> control chan above */
+ cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_ABOVE;
+ cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE40;
+ } else {
+ cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
+ cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ }
+ } else {
+ cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
+ cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ }
/* Set rx the chains */
idle_cnt = chains_static;
@@ -240,17 +252,60 @@
cmd->txchain_info = htole32(iwm_get_valid_tx_ant(sc));
}
-/*
- * Send a command
- * only if something in the configuration changed: in case that this is the
- * first time that the phy configuration is applied or in case that the phy
- * configuration changed from the previous apply.
- */
static int
-iwm_phy_ctxt_apply(struct iwm_softc *sc,
+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, uint8_t sco)
+{
+ 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));
+ if (IEEE80211_IS_CHAN_HT40(chan)) {
+ if (sco == IEEE80211_HTINFO_2NDCHAN_ABOVE) {
+ /* secondary chan above -> control chan below */
+ cmd.ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ cmd.ci.width = IWM_PHY_VHT_CHANNEL_MODE40;
+ } else if (sco == IEEE80211_HTINFO_2NDCHAN_BELOW) {
+ /* secondary chan below -> control chan above */
+ cmd.ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_ABOVE;
+ cmd.ci.width = IWM_PHY_VHT_CHANNEL_MODE40;
+ } else {
+ cmd.ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
+ cmd.ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
+ }
+ } else {
+ 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_get_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_get_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)
+ uint32_t action, uint32_t apply_time, uint8_t sco)
{
struct iwm_phy_context_cmd cmd;
int ret;
@@ -260,12 +315,23 @@
__func__,
ctxt->channel);
+ /*
+ * 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 (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS))
+ return iwm_phy_ctxt_cmd_uhb(sc, ctxt, chains_static,
+ chains_dynamic, action, apply_time, sco);
+
/* Set the command header fields */
iwm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
/* Set the command data */
iwm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,
- chains_static, chains_dynamic);
+ chains_static, chains_dynamic, sco);
ret = iwm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, IWM_CMD_SYNC,
sizeof(struct iwm_phy_context_cmd), &cmd);
@@ -285,14 +351,22 @@
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
+ int sco, ret;
+
+ sco = iwm_get_phy_sco(sc, chan);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(&sc->sc_ic, chan));
- return iwm_phy_ctxt_apply(sc, ctxt,
- chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0);
+ ret = iwm_phy_ctxt_cmd(sc, ctxt,
+ chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0, sco);
+ if (ret != 0)
+ return (ret);
+
+ ctxt->sco = sco;
+ return (0);
}
/*
@@ -306,14 +380,22 @@
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
+ int sco, ret;
+
+ sco = iwm_get_phy_sco(sc, chan);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(&sc->sc_ic, chan));
- return iwm_phy_ctxt_apply(sc, ctxt,
- chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0);
+ ret = iwm_phy_ctxt_cmd(sc, ctxt,
+ chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0, sco);
+ if (ret != 0)
+ return (ret);
+
+ ctxt->sco = sco;
+ return (0);
}
/*
diff --git a/sys/dev/iwm/if_iwm_util.h b/sys/dev/iwm/if_iwm_util.h
--- a/sys/dev/iwm/if_iwm_util.h
+++ b/sys/dev/iwm/if_iwm_util.h
@@ -159,4 +159,22 @@
return sc->sc_fw.phy_config & phy_config;
}
+/**
+ * @brief Return the HT above/below field for the given channel width
+ *
+ * @param sc driver softc
+ * @param c channel
+ * @return IEEE80211_HTINFO_2NDCHAN_* value
+ */
+static inline uint8_t
+iwm_get_phy_sco(struct iwm_softc *sc, const struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_HT40U(c))
+ return (IEEE80211_HTINFO_2NDCHAN_ABOVE);
+ else if (IEEE80211_IS_CHAN_HT40D(c))
+ return (IEEE80211_HTINFO_2NDCHAN_BELOW);
+ else
+ return (IEEE80211_HTINFO_2NDCHAN_NONE);
+}
+
#endif /* __IF_IWM_UTIL_H__ */
diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h
--- a/sys/dev/iwm/if_iwmvar.h
+++ b/sys/dev/iwm/if_iwmvar.h
@@ -349,6 +349,7 @@
uint16_t color;
uint32_t ref;
struct ieee80211_channel *channel;
+ uint8_t sco; /* 40MHz secondary channel offset */
};
struct iwm_bf_data {

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 29, 3:33 AM (1 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39839355
Default Alt Text
D60082.diff (8 KB)

Event Timeline