-/* $OpenBSD: if_iwx.c,v 1.63 2021/07/06 15:53:33 stsp Exp $ */
+/* $OpenBSD: if_iwx.c,v 1.64 2021/07/18 11:40:31 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
uint16_t iwx_rs_ht_rates(struct iwx_softc *, struct ieee80211_node *, int);
int iwx_rs_init(struct iwx_softc *, struct iwx_node *);
int iwx_enable_data_tx_queues(struct iwx_softc *);
+int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *,
+ struct ieee80211_channel *, uint8_t, uint8_t, uint32_t);
int iwx_auth(struct iwx_softc *);
int iwx_deauth(struct iwx_softc *);
int iwx_assoc(struct iwx_softc *);
}
}
+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)
+{
+ uint16_t band_flags = (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
+ int err;
+
+ if (isset(sc->sc_enabled_capa,
+ IWX_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
+ (phyctxt->channel->ic_flags & band_flags) !=
+ (chan->ic_flags & band_flags)) {
+ err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
+ chains_dynamic, IWX_FW_CTXT_ACTION_REMOVE, apply_time);
+ if (err) {
+ printf("%s: could not remove PHY context "
+ "(error %d)\n", DEVNAME(sc), err);
+ return err;
+ }
+ phyctxt->channel = chan;
+ err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
+ chains_dynamic, IWX_FW_CTXT_ACTION_ADD, apply_time);
+ if (err) {
+ printf("%s: could not remove PHY context "
+ "(error %d)\n", DEVNAME(sc), err);
+ return err;
+ }
+ } else {
+ phyctxt->channel = chan;
+ err = iwx_phy_ctxt_cmd(sc, phyctxt, chains_static,
+ chains_dynamic, IWX_FW_CTXT_ACTION_MODIFY, apply_time);
+ if (err) {
+ printf("%s: could not update PHY context (error %d)\n",
+ DEVNAME(sc), err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
int
iwx_auth(struct iwx_softc *sc)
{
splassert(IPL_NET);
- if (ic->ic_opmode == IEEE80211_M_MONITOR)
- sc->sc_phyctxt[0].channel = ic->ic_ibss_chan;
- else
- sc->sc_phyctxt[0].channel = in->in_ni.ni_chan;
- err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 1, 1,
- IWX_FW_CTXT_ACTION_MODIFY, 0);
- if (err) {
- printf("%s: could not update PHY context (error %d)\n",
- DEVNAME(sc), err);
- return err;
+ if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
+ ic->ic_ibss_chan, 1, 1, 0);
+ if (err)
+ return err;
+ } else {
+ err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
+ in->in_ni.ni_chan, 1, 1, 0);
+ if (err)
+ return err;
}
in->in_phyctxt = &sc->sc_phyctxt[0];
sc->sc_flags &= ~IWX_FLAG_MAC_ACTIVE;
}
+ /* Move unused PHY context to a default channel. */
+ err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
+ &ic->ic_channels[1], 1, 1, 0);
+ if (err)
+ return err;
+
return 0;
}
if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
(in->in_ni.ni_flags & IEEE80211_NODE_HT)) &&
iwx_mimo_enabled(sc)) {
- err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0],
- 2, 2, IWX_FW_CTXT_ACTION_MODIFY, 0);
+ err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
+ in->in_ni.ni_chan, 2, 2, 0);
if (err) {
- printf("%s: failed to update PHY\n",
- DEVNAME(sc));
+ printf("%s: failed to update PHY\n", DEVNAME(sc));
return err;
}
}
/* Reset Tx chains in case MIMO was enabled. */
if ((in->in_ni.ni_flags & IEEE80211_NODE_HT) &&
iwx_mimo_enabled(sc)) {
- err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[0], 1, 1,
- IWX_FW_CTXT_ACTION_MODIFY, 0);
+ err = iwx_phy_ctxt_update(sc, &sc->sc_phyctxt[0],
+ in->in_ni.ni_chan, 1, 1, 0);
if (err) {
printf("%s: failed to update PHY\n", DEVNAME(sc));
return err;
goto err;
}
- for (i = 0; i < 1; i++) {
+ for (i = 0; i < IWX_NUM_PHY_CTX; i++) {
/*
* The channel used here isn't relevant as it's
* going to be overwritten in the other flows.
* For now use the first channel we have.
*/
+ sc->sc_phyctxt[i].id = i;
sc->sc_phyctxt[i].channel = &ic->ic_channels[1];
err = iwx_phy_ctxt_cmd(sc, &sc->sc_phyctxt[i], 1, 1,
IWX_FW_CTXT_ACTION_ADD, 0);