|
@@ -90,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;
|
|
@@ -104,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
|
|
@@ -111,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;
|
|
@@ -135,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;
|
|
@@ -161,29 +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 if the station we're setting up is the AP that
|
|
|
- * we advertised a restricted capability set to.
|
|
|
- */
|
|
|
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
|
|
- !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
|
|
- 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));
|