diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 79 |
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, |