summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c79
1 files changed, 53 insertions, 26 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5918c1f2b10c..6fc5b3f22746 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -279,6 +279,30 @@ int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
+int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ /* This has been tested on those devices only */
+ if (mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
+ mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22000)
+ return -ENOTSUPP;
+
+ if (!mvm->nvm_data)
+ return -EBUSY;
+
+ /* mac80211 ensures the device is not started,
+ * so the firmware cannot be running
+ */
+
+ mvm->set_tx_ant = tx_ant;
+ mvm->set_rx_ant = rx_ant;
+
+ iwl_reinit_cab(mvm->trans, mvm->nvm_data, tx_ant, rx_ant, mvm->fw);
+
+ return 0;
+}
+
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
{
struct ieee80211_hw *hw = mvm->hw;
@@ -498,7 +522,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ARRAY_SIZE(iwl_mvm_iface_combinations);
hw->wiphy->max_remain_on_channel_duration = 10000;
- hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
+ hw->max_listen_interval = IWL_MVM_CONN_LISTEN_INTERVAL;
/* Extract MAC address */
memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
@@ -1033,6 +1057,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
spin_unlock_bh(&mvm->time_event_lock);
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
+ mvmvif->ap_sta = NULL;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
@@ -1169,19 +1194,9 @@ int iwl_mvm_mac_start(struct ieee80211_hw *hw)
for (retry = 0; retry <= max_retry; retry++) {
ret = __iwl_mvm_mac_start(mvm);
- if (!ret)
+ if (!ret || mvm->pldr_sync)
break;
- /*
- * In PLDR sync PCI re-enumeration is needed. no point to retry
- * mac start before that.
- */
- if (mvm->pldr_sync) {
- iwl_mei_alive_notif(false);
- iwl_trans_pcie_remove(mvm->trans, true);
- break;
- }
-
IWL_ERR(mvm, "mac start retry %d\n", retry);
}
clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
@@ -1370,7 +1385,8 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -1380,10 +1396,11 @@ int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_STATION) {
struct iwl_mvm_sta *mvmsta;
+ unsigned int link_id = link_conf->link_id;
+ u8 ap_sta_id = mvmvif->link[link_id]->ap_sta_id;
mvmvif->csa_bcn_pending = false;
- mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
- mvmvif->deflink.ap_sta_id);
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
if (WARN_ON(!mvmsta)) {
ret = -EIO;
@@ -1452,7 +1469,8 @@ void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
mvmvif->csa_failed = true;
mutex_unlock(&mvm->mutex);
- iwl_mvm_post_channel_switch(hw, vif);
+ /* If we're here, we can't support MLD */
+ iwl_mvm_post_channel_switch(hw, vif, &vif->bss_conf);
}
void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
@@ -1464,7 +1482,7 @@ void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
/* Trigger disconnect (should clear the CSA state) */
- ieee80211_chswitch_done(vif, false);
+ ieee80211_chswitch_done(vif, false, 0);
}
static u8
@@ -3878,9 +3896,14 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
- /* this would be a mac80211 bug ... but don't crash */
+ /* this would be a mac80211 bug ... but don't crash, unless we had a
+ * firmware crash while we were activating a link, in which case it is
+ * legit to have phy_ctxt = NULL. Don't bother not to WARN if we are in
+ * recovery flow since we spit tons of error messages anyway.
+ */
for_each_sta_active_link(vif, sta, link_sta, link_id) {
- if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
+ if (WARN_ON_ONCE(!mvmvif->link[link_id] ||
+ !mvmvif->link[link_id]->phy_ctxt)) {
mutex_unlock(&mvm->mutex);
return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status) ? 0 : -EINVAL;
@@ -4742,8 +4765,9 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt;
- bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
- struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
+ bool use_def = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx) ||
+ iwl_mvm_enable_fils(mvm, ctx);
+ struct cfg80211_chan_def *def = use_def ? &ctx->def : &ctx->min_def;
int ret;
lockdep_assert_held(&mvm->mutex);
@@ -4810,8 +4834,9 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
- bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx);
- struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def;
+ bool use_def = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx) ||
+ iwl_mvm_enable_fils(mvm, ctx);
+ struct cfg80211_chan_def *def = use_def ? &ctx->def : &ctx->min_def;
if (WARN_ONCE((phy_ctxt->ref > 1) &&
(changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
@@ -4950,7 +4975,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
- u32 duration = 3 * vif->bss_conf.beacon_int;
+ u32 duration = 5 * vif->bss_conf.beacon_int;
/* Protect the session to make sure we hear the first
* beacon on the new channel.
@@ -5456,7 +5481,8 @@ int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
goto out_unlock;
}
- if (chsw->delay > IWL_MAX_CSA_BLOCK_TX)
+ if (chsw->delay > IWL_MAX_CSA_BLOCK_TX &&
+ hweight16(vif->valid_links) <= 1)
schedule_delayed_work(&mvmvif->csa_work, 0);
if (chsw->block_tx) {
@@ -5535,7 +5561,7 @@ void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
if (mvmvif->csa_misbehave) {
/* Second time, give up on this AP*/
iwl_mvm_abort_channel_switch(hw, vif);
- ieee80211_chswitch_done(vif, false);
+ ieee80211_chswitch_done(vif, false, 0);
mvmvif->csa_misbehave = false;
return;
}
@@ -6200,6 +6226,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
.ampdu_action = iwl_mvm_mac_ampdu_action,
.get_antenna = iwl_mvm_op_get_antenna,
+ .set_antenna = iwl_mvm_op_set_antenna,
.start = iwl_mvm_mac_start,
.reconfig_complete = iwl_mvm_mac_reconfig_complete,
.stop = iwl_mvm_mac_stop,