diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 91 |
1 files changed, 76 insertions, 15 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a50f4df..5ace468 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -550,18 +550,18 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else mvm->max_scans = IWL_MVM_MAX_LMAC_SCANS; - if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; - if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) { - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; + if (mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels) + hw->wiphy->bands[NL80211_BAND_2GHZ] = + &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; + if (mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels) { + hw->wiphy->bands[NL80211_BAND_5GHZ] = + &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BEAMFORMER) && fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_LQ_SS_PARAMS)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= + hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; } @@ -665,12 +665,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->netdev_features |= mvm->cfg->features; - if (!iwl_mvm_is_csum_supported(mvm)) - hw->netdev_features &= ~NETIF_F_RXCSUM; - - if (IWL_MVM_SW_TX_CSUM_OFFLOAD) - hw->netdev_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6; + if (!iwl_mvm_is_csum_supported(mvm)) { + hw->netdev_features &= ~(IWL_TX_CSUM_NETIF_FLAGS | + NETIF_F_RXCSUM); + /* We may support SW TX CSUM */ + if (IWL_MVM_SW_TX_CSUM_OFFLOAD) + hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS; + } ret = ieee80211_register_hw(mvm->hw); if (ret) @@ -992,6 +993,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) iwl_mvm_reset_phy_ctxts(mvm); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); + memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames)); memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained)); memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); @@ -1180,6 +1182,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) flush_work(&mvm->d0i3_exit_work); flush_work(&mvm->async_handlers_wk); + flush_work(&mvm->add_stream_wk); cancel_delayed_work_sync(&mvm->fw_dump_wk); iwl_mvm_free_fw_dump_desc(mvm); @@ -1823,6 +1826,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); + if (changes & BSS_CHANGED_ASSOC && !bss_conf->assoc && + mvmvif->lqm_active) + iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_STOP_MEASUREMENT, + 0, 0); + /* * If we're not associated yet, take the (new) BSSID before associating * so the firmware knows. If we're already associated, then use the old @@ -2342,7 +2350,8 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return; } - if (iwlwifi_mod_params.uapsd_disable) { + if (!vif->p2p && + (iwlwifi_mod_params.uapsd_disable & IWL_DISABLE_UAPSD_BSS)) { vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; return; } @@ -2378,6 +2387,22 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm, peer_addr, action); } +static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvm_sta) +{ + struct iwl_mvm_tid_data *tid_data; + struct sk_buff *skb; + int i; + + spin_lock_bh(&mvm_sta->lock); + for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { + tid_data = &mvm_sta->tid_data[i]; + while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) + ieee80211_free_txskb(mvm->hw, skb); + } + spin_unlock_bh(&mvm_sta->lock); +} + static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2398,6 +2423,33 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, /* if a STA is being removed, reuse its ID */ flush_work(&mvm->sta_drained_wk); + /* + * If we are in a STA removal flow and in DQA mode: + * + * This is after the sync_rcu part, so the queues have already been + * flushed. No more TXs on their way in mac80211's path, and no more in + * the queues. + * Also, we won't be getting any new TX frames for this station. + * What we might have are deferred TX frames that need to be taken care + * of. + * + * Drop any still-queued deferred-frame before removing the STA, and + * make sure the worker is no longer handling frames for this STA. + */ + if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST && + iwl_mvm_is_dqa_supported(mvm)) { + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); + + iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta); + flush_work(&mvm->add_stream_wk); + + /* + * No need to make sure deferred TX indication is off since the + * worker will already remove it if it was on + */ + } + mutex_lock(&mvm->mutex); if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { @@ -2861,7 +2913,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)), .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id), /* Set the channel info data */ - .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ? + .channel_info.band = (channel->band == NL80211_BAND_2GHZ) ? PHY_BAND_24 : PHY_BAND_5, .channel_info.channel = channel->hw_value, .channel_info.width = PHY_VHT_CHANNEL_MODE20, @@ -3630,6 +3682,11 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, break; case NL80211_IFTYPE_STATION: + if (mvmvif->lqm_active) + iwl_mvm_send_lqm_cmd(vif, + LQM_CMD_OPERATION_STOP_MEASUREMENT, + 0, 0); + /* Schedule the time event to a bit before beacon 1, * to make sure we're in the new channel when the * GO/AP arrives. @@ -3729,6 +3786,10 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, if (!vif || vif->type != NL80211_IFTYPE_STATION) return; + /* Make sure we're done with the deferred traffic before flushing */ + if (iwl_mvm_is_dqa_supported(mvm)) + flush_work(&mvm->add_stream_wk); + mutex_lock(&mvm->mutex); mvmvif = iwl_mvm_vif_from_mac80211(vif); |