From b92e661b401897928040d89b3a9d0cd74ce6e9a1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 23 Jan 2014 17:58:23 +0200 Subject: [PATCH] iwlwifi: mvm: reserve sta_id 0 to station The d3/d0i3 fw code requires the sta_id to be 0 (this is used to determine the rates and keys to use in arp offloading). Reserve sta_id 0 to station interface in order to comply with this requirement. Change some functions prototypes in order to make the allocation function know about the interface type. Signed-off-by: Eliad Peller Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/d3.c | 27 --------------------------- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 ++- drivers/net/wireless/iwlwifi/mvm/sta.c | 28 +++++++++++++++++++++------- drivers/net/wireless/iwlwifi/mvm/sta.h | 2 +- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index e3a9cec45566..b956e2f0b631 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -963,7 +963,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, }; int ret, i; int len __maybe_unused; - u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; if (!wowlan) { /* @@ -980,8 +979,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); - old_aux_sta_id = mvm->aux_sta.sta_id; - /* see if there's only a single BSS vif and it's associated */ ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, @@ -1067,16 +1064,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, iwl_trans_stop_device(mvm->trans); /* - * The D3 firmware still hardcodes the AP station ID for the - * BSS we're associated with as 0. Store the real STA ID here - * and assign 0. When we leave this function, we'll restore - * the original value for the resume code. - */ - old_ap_sta_id = mvm_ap_sta->sta_id; - mvm_ap_sta->sta_id = 0; - mvmvif->ap_sta_id = 0; - - /* * Set the HW restart bit -- this is mostly true as we're * going to load new firmware and reprogram that, though * the reprogramming is going to be manual to avoid adding @@ -1096,16 +1083,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, mvm->ptk_ivlen = 0; mvm->ptk_icvlen = 0; - /* - * The D3 firmware still hardcodes the AP station ID for the - * BSS we're associated with as 0. As a result, we have to move - * the auxiliary station to ID 1 so the ID 0 remains free for - * the AP station for later. - * We set the sta_id to 1 here, and reset it to its previous - * value (that we stored above) later. - */ - mvm->aux_sta.sta_id = 1; - ret = iwl_mvm_load_d3_fw(mvm); if (ret) goto out; @@ -1222,10 +1199,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, iwl_trans_d3_suspend(mvm->trans, test); out: - mvm->aux_sta.sta_id = old_aux_sta_id; - mvm_ap_sta->sta_id = old_ap_sta_id; - mvmvif->ap_sta_id = old_ap_sta_id; - if (ret < 0) ieee80211_restart_hw(mvm->hw); out_noreset: diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b9b6bfb5b25b..ba4dcabf7c4a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -703,7 +703,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, vif->type == NL80211_IFTYPE_ADHOC) { u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, - qmask); + qmask, + ieee80211_vif_type_p2p(vif)); if (ret) { IWL_ERR(mvm, "Failed to allocate bcast sta\n"); goto out_release; diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index fb416c5d4a63..d1da93b79cc6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -175,19 +175,30 @@ static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm, &sta_cmd); } -static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) +static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, + enum nl80211_iftype iftype) { int sta_id; + u32 reserved_ids = 0; + BUILD_BUG_ON(IWL_MVM_STATION_COUNT > 32); WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)); lockdep_assert_held(&mvm->mutex); + /* d0i3/d3 assumes the AP's sta_id (of sta vif) is 0. reserve it. */ + if (iftype != NL80211_IFTYPE_STATION) + reserved_ids = BIT(0); + /* Don't take rcu_read_lock() since we are protected by mvm->mutex */ - for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) + for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) { + if (BIT(sta_id) & reserved_ids) + continue; + if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], lockdep_is_held(&mvm->mutex))) return sta_id; + } return IWL_MVM_STATION_COUNT; } @@ -312,7 +323,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) - sta_id = iwl_mvm_find_free_sta_id(mvm); + sta_id = iwl_mvm_find_free_sta_id(mvm, + ieee80211_vif_type_p2p(vif)); else sta_id = mvm_sta->sta_id; @@ -564,10 +576,10 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm, } int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, - u32 qmask) + u32 qmask, enum nl80211_iftype iftype) { if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { - sta->sta_id = iwl_mvm_find_free_sta_id(mvm); + sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype); if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT)) return -ENOSPC; } @@ -631,7 +643,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); /* Add the aux station, but without any queues */ - ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0); + ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0, + NL80211_IFTYPE_UNSPECIFIED); if (ret) return ret; @@ -703,7 +716,8 @@ int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); - ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask); + ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask, + ieee80211_vif_type_p2p(vif)); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 5ecabddc1dbf..2ed84c421481 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h @@ -384,7 +384,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm); int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, - u32 qmask); + u32 qmask, enum nl80211_iftype iftype); void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta); int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, -- 2.11.0