iwlwifi: mvm: reserve sta_id 0 to station
authorEliad Peller <eliad@wizery.com>
Thu, 23 Jan 2014 15:58:23 +0000 (17:58 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 6 Feb 2014 19:11:21 +0000 (21:11 +0200)
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 <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.h

index e3a9cec45566f94b7cda7b43231283320157d803..b956e2f0b631c4d3a50a3b89bd25dea6ac7351e1 100644 (file)
@@ -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,
@@ -1066,16 +1063,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
@@ -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:
index b9b6bfb5b25b4bfa9c8352a001e94c09293d90c3..ba4dcabf7c4a508924a239c5db4aaa35bfb62b9b 100644 (file)
@@ -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;
index fb416c5d4a632d9fb0af57593357f89531741394..d1da93b79cc6fb3e575278884f2241f2965a294c 100644 (file)
@@ -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;
 
index 5ecabddc1dbf9f7211a51674a82af99d95b18d36..2ed84c421481c79dfa1e847b1940ac78da8a9d9c 100644 (file)
@@ -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,