mac80211: inform driver of basic rateset
Johannes Berg [Wed, 10 Sep 2008 22:01:57 +0000 (00:01 +0200)]
Drivers need to know the basic rateset to be able to configure
the ACK/CTS programming in hardware correctly.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/util.c

index d67882d..c81e579 100644 (file)
@@ -160,6 +160,7 @@ struct ieee80211_low_level_stats {
  * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
  * @BSS_CHANGED_ERP_SLOT: slot timing changed
  * @BSS_CHANGED_HT: 802.11n parameters changed
+ * @BSS_CHANGED_BASIC_RATES: Basic rateset changed
  */
 enum ieee80211_bss_change {
        BSS_CHANGED_ASSOC               = 1<<0,
@@ -167,6 +168,7 @@ enum ieee80211_bss_change {
        BSS_CHANGED_ERP_PREAMBLE        = 1<<2,
        BSS_CHANGED_ERP_SLOT            = 1<<3,
        BSS_CHANGED_HT                  = 1<<4,
+       BSS_CHANGED_BASIC_RATES         = 1<<5,
 };
 
 /**
@@ -187,6 +189,9 @@ enum ieee80211_bss_change {
  * @assoc_ht: association in HT mode
  * @ht_conf: ht capabilities
  * @ht_bss_conf: ht extended capabilities
+ * @basic_rates: bitmap of basic rates, each bit stands for an
+ *     index into the rate table configured by the driver in
+ *     the current band.
  */
 struct ieee80211_bss_conf {
        /* association related data */
@@ -200,6 +205,7 @@ struct ieee80211_bss_conf {
        u16 beacon_int;
        u16 assoc_capability;
        u64 timestamp;
+       u64 basic_rates;
        /* ht related data */
        bool assoc_ht;
        struct ieee80211_ht_info *ht_conf;
index 1f9336a..21cc6d0 100644 (file)
@@ -433,11 +433,6 @@ struct ieee80211_sub_if_data {
 
        int drop_unencrypted;
 
-       /*
-        * basic rates of this AP or the AP we're associated to
-        */
-       u64 basic_rates;
-
        /* Fragment table for host-based reassembly */
        struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
        unsigned int fragment_next;
@@ -1017,6 +1012,8 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
 void ieee802_11_parse_elems(u8 *start, size_t len,
                            struct ieee802_11_elems *elems);
 int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
+u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
+                             enum ieee80211_band band);
 
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
index 61b1934..dab8eba 100644 (file)
@@ -144,7 +144,9 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
        ieee80211_setup_sdata(sdata, type);
 
        /* reset some values that shouldn't be kept across type changes */
-       sdata->basic_rates = 0;
+       sdata->bss_conf.basic_rates =
+               ieee80211_mandatory_rates(sdata->local,
+                       sdata->local->hw.conf.channel->band);
        sdata->drop_unencrypted = 0;
 
        return 0;
index 5b74844..55bc607 100644 (file)
@@ -710,6 +710,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        ieee80211_led_assoc(local, 1);
 
        sdata->bss_conf.assoc = 1;
+       /*
+        * For now just always ask the driver to update the basic rateset
+        * when we have associated, we aren't checking whether it actually
+        * changed or not.
+        */
+       changed |= BSS_CHANGED_BASIC_RATES;
        ieee80211_bss_info_change_notify(sdata, changed);
 
        netif_tx_start_all_queues(sdata->dev);
@@ -1296,7 +1302,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        }
 
        sta->supp_rates[local->hw.conf.channel->band] = rates;
-       sdata->basic_rates = basic_rates;
+       sdata->bss_conf.basic_rates = basic_rates;
 
        /* cf. IEEE 802.11 9.2.12 */
        if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
@@ -1453,34 +1459,6 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        return res;
 }
 
-static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local,
-                                       enum ieee80211_band band)
-{
-       struct ieee80211_supported_band *sband;
-       struct ieee80211_rate *bitrates;
-       u64 mandatory_rates;
-       enum ieee80211_rate_flags mandatory_flag;
-       int i;
-
-       sband = local->hw.wiphy->bands[band];
-       if (!sband) {
-               WARN_ON(1);
-               sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-       }
-
-       if (band == IEEE80211_BAND_2GHZ)
-               mandatory_flag = IEEE80211_RATE_MANDATORY_B;
-       else
-               mandatory_flag = IEEE80211_RATE_MANDATORY_A;
-
-       bitrates = sband->bitrates;
-       mandatory_rates = 0;
-       for (i = 0; i < sband->n_bitrates; i++)
-               if (bitrates[i].flags & mandatory_flag)
-                       mandatory_rates |= BIT(i);
-       return mandatory_rates;
-}
-
 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                                  struct ieee80211_mgmt *mgmt,
                                  size_t len,
@@ -1522,7 +1500,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                        prev_rates = sta->supp_rates[band];
                        /* make sure mandatory rates are always added */
                        sta->supp_rates[band] = supp_rates |
-                               ieee80211_sta_get_mandatory_rates(local, band);
+                               ieee80211_mandatory_rates(local, band);
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
                        if (sta->supp_rates[band] != prev_rates)
@@ -2361,7 +2339,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
 
        /* make sure mandatory rates are always added */
        sta->supp_rates[band] = supp_rates |
-                       ieee80211_sta_get_mandatory_rates(local, band);
+                       ieee80211_mandatory_rates(local, band);
 
        rate_control_rate_init(sta, local);
 
index 1bed3be..a523189 100644 (file)
@@ -153,7 +153,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
                if (r->bitrate > txrate->bitrate)
                        break;
 
-               if (tx->sdata->basic_rates & BIT(i))
+               if (tx->sdata->bss_conf.basic_rates & BIT(i))
                        rate = r->bitrate;
 
                switch (sband->band) {
@@ -594,7 +594,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
                for (idx = 0; idx < sband->n_bitrates; idx++) {
                        if (sband->bitrates[idx].bitrate > rate->bitrate)
                                continue;
-                       if (tx->sdata->basic_rates & BIT(idx) &&
+                       if (tx->sdata->bss_conf.basic_rates & BIT(idx) &&
                            (baserate < 0 ||
                             (sband->bitrates[baserate].bitrate
                              < sband->bitrates[idx].bitrate)))
index a7968df..d6aca91 100644 (file)
@@ -640,3 +640,31 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
 
        return ret;
 }
+
+u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
+                             enum ieee80211_band band)
+{
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_rate *bitrates;
+       u64 mandatory_rates;
+       enum ieee80211_rate_flags mandatory_flag;
+       int i;
+
+       sband = local->hw.wiphy->bands[band];
+       if (!sband) {
+               WARN_ON(1);
+               sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+       }
+
+       if (band == IEEE80211_BAND_2GHZ)
+               mandatory_flag = IEEE80211_RATE_MANDATORY_B;
+       else
+               mandatory_flag = IEEE80211_RATE_MANDATORY_A;
+
+       bitrates = sband->bitrates;
+       mandatory_rates = 0;
+       for (i = 0; i < sband->n_bitrates; i++)
+               if (bitrates[i].flags & mandatory_flag)
+                       mandatory_rates |= BIT(i);
+       return mandatory_rates;
+}