mac80211: fix a memory leak on sta rate selection table
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / mac80211 / ht.c
index 0db25d4bb223156a5420e900620c154bf7a92726..af8cee06e4f37475ed17c764e55cf75c070ef9f2 100644 (file)
@@ -40,13 +40,6 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
        if (!ht_cap->ht_supported)
                return;
 
-       if (sdata->vif.type != NL80211_IFTYPE_STATION) {
-               /* AP interfaces call this code when adding new stations,
-                * so just silently ignore non station interfaces.
-                */
-               return;
-       }
-
        /* NOTE:  If you add more over-rides here, update register_hw
         * ht_capa_mod_msk logic in main.c as well.
         * And, if this method can ever change ht_cap.ht_supported, fix
@@ -97,7 +90,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
                                       const struct ieee80211_ht_cap *ht_cap_ie,
                                       struct sta_info *sta)
 {
-       struct ieee80211_sta_ht_cap ht_cap;
+       struct ieee80211_sta_ht_cap ht_cap, own_cap;
        u8 ampdu_info, tx_mcs_set_cap;
        int i, max_tx_streams;
        bool changed;
@@ -111,6 +104,18 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 
        ht_cap.ht_supported = true;
 
+       own_cap = sband->ht_cap;
+
+       /*
+        * If user has specified capability over-rides, take care
+        * of that if the station we're setting up is the AP that
+        * we advertised a restricted capability set to. Override
+        * our own capabilities and then use those below.
+        */
+       if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+           !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+               ieee80211_apply_htcap_overrides(sdata, &own_cap);
+
        /*
         * The bits listed in this expression should be
         * the same for the peer and us, if the station
@@ -118,21 +123,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
         * we mask them out.
         */
        ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) &
-               (sband->ht_cap.cap |
-                ~(IEEE80211_HT_CAP_LDPC_CODING |
-                  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-                  IEEE80211_HT_CAP_GRN_FLD |
-                  IEEE80211_HT_CAP_SGI_20 |
-                  IEEE80211_HT_CAP_SGI_40 |
-                  IEEE80211_HT_CAP_DSSSCCK40));
+               (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING |
+                                IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                                IEEE80211_HT_CAP_GRN_FLD |
+                                IEEE80211_HT_CAP_SGI_20 |
+                                IEEE80211_HT_CAP_SGI_40 |
+                                IEEE80211_HT_CAP_DSSSCCK40));
 
        /*
         * The STBC bits are asymmetric -- if we don't have
         * TX then mask out the peer's RX and vice versa.
         */
-       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+       if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC))
                ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC;
-       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))
+       if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC))
                ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC;
 
        ampdu_info = ht_cap_ie->ampdu_params_info;
@@ -142,7 +146,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
                (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
 
        /* own MCS TX capabilities */
-       tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
+       tx_mcs_set_cap = own_cap.mcs.tx_params;
 
        /* Copy peer MCS TX capabilities, the driver might need them. */
        ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params;
@@ -168,26 +172,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
         */
        for (i = 0; i < max_tx_streams; i++)
                ht_cap.mcs.rx_mask[i] =
-                       sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
+                       own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
 
        if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
                for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
                     i < IEEE80211_HT_MCS_MASK_LEN; i++)
                        ht_cap.mcs.rx_mask[i] =
-                               sband->ht_cap.mcs.rx_mask[i] &
+                               own_cap.mcs.rx_mask[i] &
                                        ht_cap_ie->mcs.rx_mask[i];
 
        /* handle MCS rate 32 too */
-       if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
+       if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
                ht_cap.mcs.rx_mask[32/8] |= 1;
 
  apply:
-       /*
-        * If user has specified capability over-rides, take care
-        * of that here.
-        */
-       ieee80211_apply_htcap_overrides(sdata, &ht_cap);
-
        changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
 
        memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));