diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index fd7d4abfb454..bcce3c1c5feb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1602,6 +1602,18 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, RCU_INIT_POINTER(mvm->csa_vif, NULL); return; case NL80211_IFTYPE_STATION: + /* + * if we don't know about an ongoing channel switch, + * make sure FW cancels it + */ + if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, + CHANNEL_SWITCH_ERROR_NOTIF, + 0) && !vif->csa_active) { + IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n"); + iwl_mvm_cancel_channel_switch(mvm, vif, mac_id); + break; + } + iwl_mvm_csa_client_absent(mvm, vif); cancel_delayed_work(&mvmvif->csa_work); ieee80211_chswitch_done(vif, true); @@ -1615,6 +1627,31 @@ out_unlock: rcu_read_unlock(); } +void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_channel_switch_error_notif *notif = (void *)pkt->data; + struct ieee80211_vif *vif; + u32 id = le32_to_cpu(notif->mac_id); + u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask); + + rcu_read_lock(); + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + if (!vif) { + rcu_read_unlock(); + return; + } + + IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n", + id, csa_err_mask); + if (csa_err_mask & (CS_ERR_COUNT_ERROR | + CS_ERR_LONG_DELAY_AFTER_CS | + CS_ERR_TX_BLOCK_TIMER_EXPIRED)) + ieee80211_channel_switch_disconnect(vif, true); + rcu_read_unlock(); +} + void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { |