mac80211: fix and optimize MCS mask handling
authorFelix Fietkau <nbd@openwrt.org>
Tue, 16 Apr 2013 11:38:42 +0000 (13:38 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 16 Apr 2013 21:42:29 +0000 (23:42 +0200)
Currently the code always copies the configured MCS mask (even if it is
set to default), but only uses it if legacy rates were also masked out.
Fix this by adding a flag that tracks whether the configured MCS mask is
set to default or not.
Optimize the code further by storing a pointer to the configured rate
mask in txrc instead of using memcpy.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/rate.c
net/mac80211/tx.c

index bc5d8184c489118a6f8354cea1f2c5570478a0b1..05dbb97885043bc172f75c20739b9c53cf29d8dd 100644 (file)
@@ -4107,7 +4107,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
  *     (deprecated; this will be removed once drivers get updated to use
  *     rate_idx_mask)
  * @rate_idx_mask: user-requested (legacy) rate mask
- * @rate_idx_mcs_mask: user-requested MCS rate mask
+ * @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
  */
 struct ieee80211_tx_rate_control {
@@ -4119,7 +4119,7 @@ struct ieee80211_tx_rate_control {
        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;
 };
 
index fdd95bd751a158c6269266fb934c4194041a814b..72ab1c0e3ca72d3b4dab9a4b77fd4e4f1ea2cbf2 100644 (file)
@@ -2417,9 +2417,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
        }
 
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+               struct ieee80211_supported_band *sband = wiphy->bands[i];
+               int j;
+
                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;
+
+               for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++)
+                       if (~sdata->rc_rateidx_mcs_mask[i][j]) {
+                               sdata->rc_has_mcs_mask[i] = true;
+                               break;
+                       }
        }
 
        return 0;
index f4a65a340a521e969cd948e7c01198a0b2a9cb06..21c1720eee000c6861fe48ac255afd21068c0caf 100644 (file)
@@ -739,6 +739,8 @@ struct ieee80211_sub_if_data {
 
        /* 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 {
index dd88381c53b7780dcae3a3b7e47ca0ca56a54474..5d545dd2d050dadec414448dff79a6e78b70cbbe 100644 (file)
@@ -460,9 +460,12 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
         * 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];
index bb82c873f774b1d657462f4d223321c2e888bd28..15c1b286e280693399905c83f71b55581dd43f48 100644 (file)
@@ -642,9 +642,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                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[info->band],
-              sizeof(txrc.rate_idx_mcs_mask));
+
+       if (tx->sdata->rc_has_mcs_mask[info->band])
+               txrc.rate_idx_mcs_mask =
+                       tx->sdata->rc_rateidx_mcs_mask[info->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);
@@ -2508,8 +2510,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                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);