Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173752944
D60082.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D60082.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60082: iwm: update phy context routines; add HT channel width parameter
Attached
Detach File
Event Timeline
Log In to Comment