2012-03-10 12:59:40 +00:00
|
|
|
--- a/net/mac80211/ieee80211_i.h
|
|
|
|
+++ b/net/mac80211/ieee80211_i.h
|
2012-04-16 21:08:41 +00:00
|
|
|
@@ -726,6 +726,8 @@ struct ieee80211_sub_if_data {
|
2012-03-10 12:59:40 +00:00
|
|
|
|
|
|
|
/* bitmap of allowed (non-MCS) rate indexes for rate control */
|
|
|
|
u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
|
|
|
|
+
|
|
|
|
+ bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
|
|
|
|
u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
|
|
|
|
|
|
|
|
union {
|
|
|
|
--- a/net/mac80211/cfg.c
|
|
|
|
+++ b/net/mac80211/cfg.c
|
2012-04-16 21:08:41 +00:00
|
|
|
@@ -1914,9 +1914,20 @@ static int ieee80211_set_bitrate_mask(st
|
2012-03-10 12:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
|
|
|
+ struct ieee80211_supported_band *sband = wiphy->bands[i];
|
|
|
|
+
|
|
|
|
sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
|
|
|
|
memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
|
|
|
|
sizeof(mask->control[i].mcs));
|
|
|
|
+
|
|
|
|
+ sdata->rc_has_mcs_mask[i] = false;
|
|
|
|
+ if (!sband)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (memcmp(sdata->rc_rateidx_mcs_mask[i],
|
|
|
|
+ sband->ht_cap.mcs.rx_mask,
|
|
|
|
+ sizeof(sband->ht_cap.mcs.rx_mask)) != 0)
|
|
|
|
+ sdata->rc_has_mcs_mask[i] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
--- a/include/net/mac80211.h
|
|
|
|
+++ b/include/net/mac80211.h
|
2012-04-16 21:08:41 +00:00
|
|
|
@@ -3645,7 +3645,7 @@ void ieee80211_send_bar(struct ieee80211
|
2012-03-10 12:59:40 +00:00
|
|
|
* (deprecated; this will be removed once drivers get updated to use
|
|
|
|
* rate_idx_mask)
|
2012-04-16 21:08:41 +00:00
|
|
|
* @rate_idx_mask: user-requested (legacy) rate mask
|
|
|
|
- * @rate_idx_mcs_mask: user-requested MCS rate mask
|
2012-03-10 12:59:40 +00:00
|
|
|
+ * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use)
|
|
|
|
* @bss: whether this frame is sent out in AP or IBSS mode
|
2012-04-16 21:08:41 +00:00
|
|
|
*/
|
|
|
|
struct ieee80211_tx_rate_control {
|
|
|
|
@@ -3657,7 +3657,7 @@ struct ieee80211_tx_rate_control {
|
2012-03-10 12:59:40 +00:00
|
|
|
bool rts, short_preamble;
|
|
|
|
u8 max_rate_idx;
|
|
|
|
u32 rate_idx_mask;
|
|
|
|
- u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
|
|
|
|
+ u8 *rate_idx_mcs_mask;
|
|
|
|
bool bss;
|
|
|
|
};
|
|
|
|
|
|
|
|
--- a/net/mac80211/tx.c
|
|
|
|
+++ b/net/mac80211/tx.c
|
2012-04-16 21:08:41 +00:00
|
|
|
@@ -642,9 +642,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
|
2012-03-10 12:59:40 +00:00
|
|
|
txrc.max_rate_idx = -1;
|
|
|
|
else
|
|
|
|
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
|
|
|
|
- memcpy(txrc.rate_idx_mcs_mask,
|
|
|
|
- tx->sdata->rc_rateidx_mcs_mask[tx->channel->band],
|
|
|
|
- sizeof(txrc.rate_idx_mcs_mask));
|
|
|
|
+
|
|
|
|
+ if (tx->sdata->rc_has_mcs_mask[tx->channel->band])
|
|
|
|
+ txrc.rate_idx_mcs_mask =
|
|
|
|
+ tx->sdata->rc_rateidx_mcs_mask[tx->channel->band];
|
|
|
|
+
|
|
|
|
txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
|
|
tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
|
|
|
|
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
|
2012-04-16 21:08:41 +00:00
|
|
|
@@ -2479,8 +2481,6 @@ struct sk_buff *ieee80211_beacon_get_tim
|
2012-03-10 12:59:40 +00:00
|
|
|
txrc.max_rate_idx = -1;
|
|
|
|
else
|
|
|
|
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
|
|
|
|
- memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
|
|
|
|
- sizeof(txrc.rate_idx_mcs_mask));
|
|
|
|
txrc.bss = true;
|
|
|
|
rate_control_get_rate(sdata, NULL, &txrc);
|
|
|
|
|
|
|
|
--- a/net/mac80211/rate.c
|
|
|
|
+++ b/net/mac80211/rate.c
|
|
|
|
@@ -461,9 +461,12 @@ void rate_control_get_rate(struct ieee80
|
|
|
|
* the common case.
|
|
|
|
*/
|
|
|
|
mask = sdata->rc_rateidx_mask[info->band];
|
|
|
|
- memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
|
|
|
|
- sizeof(mcs_mask));
|
|
|
|
- if (mask != (1 << txrc->sband->n_bitrates) - 1) {
|
|
|
|
+ if (mask != (1 << txrc->sband->n_bitrates) - 1 || txrc->rate_idx_mcs_mask) {
|
|
|
|
+ if (txrc->rate_idx_mcs_mask)
|
|
|
|
+ memcpy(mcs_mask, txrc->rate_idx_mcs_mask, sizeof(mcs_mask));
|
|
|
|
+ else
|
|
|
|
+ memset(mcs_mask, 0xff, sizeof(mcs_mask));
|
|
|
|
+
|
|
|
|
if (sta) {
|
|
|
|
/* Filter out rates that the STA does not support */
|
|
|
|
mask &= sta->sta.supp_rates[info->band];
|