| 1 | --- a/net/mac80211/ieee80211_i.h |
| 2 | +++ b/net/mac80211/ieee80211_i.h |
| 3 | @@ -761,6 +761,8 @@ struct ieee80211_sub_if_data { |
| 4 | |
| 5 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ |
| 6 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; |
| 7 | + |
| 8 | + bool rc_has_mcs_mask[IEEE80211_NUM_BANDS]; |
| 9 | u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN]; |
| 10 | |
| 11 | union { |
| 12 | --- a/net/mac80211/cfg.c |
| 13 | +++ b/net/mac80211/cfg.c |
| 14 | @@ -2300,9 +2300,20 @@ static int ieee80211_set_bitrate_mask(st |
| 15 | } |
| 16 | |
| 17 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
| 18 | + struct ieee80211_supported_band *sband = wiphy->bands[i]; |
| 19 | + |
| 20 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
| 21 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, |
| 22 | sizeof(mask->control[i].mcs)); |
| 23 | + |
| 24 | + sdata->rc_has_mcs_mask[i] = false; |
| 25 | + if (!sband) |
| 26 | + continue; |
| 27 | + |
| 28 | + if (memcmp(sdata->rc_rateidx_mcs_mask[i], |
| 29 | + sband->ht_cap.mcs.rx_mask, |
| 30 | + sizeof(sband->ht_cap.mcs.rx_mask)) != 0) |
| 31 | + sdata->rc_has_mcs_mask[i] = true; |
| 32 | } |
| 33 | |
| 34 | return 0; |
| 35 | --- a/include/net/mac80211.h |
| 36 | +++ b/include/net/mac80211.h |
| 37 | @@ -3968,7 +3968,7 @@ void ieee80211_send_bar(struct ieee80211 |
| 38 | * (deprecated; this will be removed once drivers get updated to use |
| 39 | * rate_idx_mask) |
| 40 | * @rate_idx_mask: user-requested (legacy) rate mask |
| 41 | - * @rate_idx_mcs_mask: user-requested MCS rate mask |
| 42 | + * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use) |
| 43 | * @bss: whether this frame is sent out in AP or IBSS mode |
| 44 | */ |
| 45 | struct ieee80211_tx_rate_control { |
| 46 | @@ -3980,7 +3980,7 @@ struct ieee80211_tx_rate_control { |
| 47 | bool rts, short_preamble; |
| 48 | u8 max_rate_idx; |
| 49 | u32 rate_idx_mask; |
| 50 | - u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
| 51 | + u8 *rate_idx_mcs_mask; |
| 52 | bool bss; |
| 53 | }; |
| 54 | |
| 55 | --- a/net/mac80211/tx.c |
| 56 | +++ b/net/mac80211/tx.c |
| 57 | @@ -636,9 +636,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 |
| 58 | txrc.max_rate_idx = -1; |
| 59 | else |
| 60 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
| 61 | - memcpy(txrc.rate_idx_mcs_mask, |
| 62 | - tx->sdata->rc_rateidx_mcs_mask[info->band], |
| 63 | - sizeof(txrc.rate_idx_mcs_mask)); |
| 64 | + |
| 65 | + if (tx->sdata->rc_has_mcs_mask[info->band]) |
| 66 | + txrc.rate_idx_mcs_mask = |
| 67 | + tx->sdata->rc_rateidx_mcs_mask[info->band]; |
| 68 | + |
| 69 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
| 70 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || |
| 71 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); |
| 72 | @@ -2502,8 +2504,6 @@ struct sk_buff *ieee80211_beacon_get_tim |
| 73 | txrc.max_rate_idx = -1; |
| 74 | else |
| 75 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
| 76 | - memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band], |
| 77 | - sizeof(txrc.rate_idx_mcs_mask)); |
| 78 | txrc.bss = true; |
| 79 | rate_control_get_rate(sdata, NULL, &txrc); |
| 80 | |
| 81 | --- a/net/mac80211/rate.c |
| 82 | +++ b/net/mac80211/rate.c |
| 83 | @@ -460,9 +460,12 @@ void rate_control_get_rate(struct ieee80 |
| 84 | * the common case. |
| 85 | */ |
| 86 | mask = sdata->rc_rateidx_mask[info->band]; |
| 87 | - memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band], |
| 88 | - sizeof(mcs_mask)); |
| 89 | - if (mask != (1 << txrc->sband->n_bitrates) - 1) { |
| 90 | + if (mask != (1 << txrc->sband->n_bitrates) - 1 || txrc->rate_idx_mcs_mask) { |
| 91 | + if (txrc->rate_idx_mcs_mask) |
| 92 | + memcpy(mcs_mask, txrc->rate_idx_mcs_mask, sizeof(mcs_mask)); |
| 93 | + else |
| 94 | + memset(mcs_mask, 0xff, sizeof(mcs_mask)); |
| 95 | + |
| 96 | if (sta) { |
| 97 | /* Filter out rates that the STA does not support */ |
| 98 | mask &= sta->sta.supp_rates[info->band]; |
| 99 | |