]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/ibss.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[~andy/linux] / net / mac80211 / ibss.c
index aa537681f87c03008ff2ce6dd655a45dfa17dfbe..0b30277eb3667bbc113cc89802609959f8d1faae 100644 (file)
@@ -63,19 +63,18 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
 static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                      const u8 *bssid, const int beacon_int,
                                      struct ieee80211_channel *chan,
-                                     const size_t supp_rates_len,
-                                     const u8 *supp_rates,
+                                     const u32 basic_rates,
                                      const u16 capability, u64 tsf)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
-       int rates, i, j;
+       int rates, i;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
        u8 *pos;
        struct ieee80211_supported_band *sband;
        u32 bss_change;
-
+       u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
 
        /* Reset own TSF to allow time synchronization work. */
        drv_reset_tsf(local);
@@ -101,6 +100,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
        sband = local->hw.wiphy->bands[chan->band];
 
+       /* build supported rates array */
+       pos = supp_rates;
+       for (i = 0; i < sband->n_bitrates; i++) {
+               int rate = sband->bitrates[i].bitrate;
+               u8 basic = 0;
+               if (basic_rates & BIT(i))
+                       basic = 0x80;
+               *pos++ = basic | (u8) (rate / 5);
+       }
+
        /* Build IBSS probe response */
        mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
        memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
@@ -118,7 +127,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        *pos++ = ifibss->ssid_len;
        memcpy(pos, ifibss->ssid, ifibss->ssid_len);
 
-       rates = supp_rates_len;
+       rates = sband->n_bitrates;
        if (rates > 8)
                rates = 8;
        pos = skb_put(skb, 2 + rates);
@@ -140,8 +149,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        *pos++ = 0;
        *pos++ = 0;
 
-       if (supp_rates_len > 8) {
-               rates = supp_rates_len - 8;
+       if (sband->n_bitrates > 8) {
+               rates = sband->n_bitrates - 8;
                pos = skb_put(skb, 2 + rates);
                *pos++ = WLAN_EID_EXT_SUPP_RATES;
                *pos++ = rates;
@@ -162,15 +171,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        bss_change |= BSS_CHANGED_BEACON_ENABLED;
        ieee80211_bss_info_change_notify(sdata, bss_change);
 
-       rates = 0;
-       for (i = 0; i < supp_rates_len; i++) {
-               int bitrate = (supp_rates[i] & 0x7f) * 5;
-               for (j = 0; j < sband->n_bitrates; j++)
-                       if (sband->bitrates[j].bitrate == bitrate)
-                               rates |= BIT(j);
-       }
-
-       ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates);
+       ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
 
        ifibss->state = IEEE80211_IBSS_MLME_JOINED;
        mod_timer(&ifibss->timer,
@@ -184,15 +185,35 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_bss *bss)
 {
+       struct ieee80211_supported_band *sband;
+       u32 basic_rates;
+       int i, j;
        u16 beacon_int = bss->cbss.beacon_interval;
 
        if (beacon_int < 10)
                beacon_int = 10;
 
+       sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band];
+
+       basic_rates = 0;
+
+       for (i = 0; i < bss->supp_rates_len; i++) {
+               int rate = (bss->supp_rates[i] & 0x7f) * 5;
+               bool is_basic = !!(bss->supp_rates[i] & 0x80);
+
+               for (j = 0; j < sband->n_bitrates; j++) {
+                       if (sband->bitrates[j].bitrate == rate) {
+                               if (is_basic)
+                                       basic_rates |= BIT(j);
+                               break;
+                       }
+               }
+       }
+
        __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
                                  beacon_int,
                                  bss->cbss.channel,
-                                 bss->supp_rates_len, bss->supp_rates,
+                                 basic_rates,
                                  bss->cbss.capability,
                                  bss->cbss.tsf);
 }
@@ -449,9 +470,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
-       u8 *pos;
        u8 bssid[ETH_ALEN];
-       u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
        u16 capability;
        int i;
 
@@ -480,15 +499,9 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
        else
                sdata->drop_unencrypted = 0;
 
-       pos = supp_rates;
-       for (i = 0; i < sband->n_bitrates; i++) {
-               int rate = sband->bitrates[i].bitrate;
-               *pos++ = (u8) (rate / 5);
-       }
-
        __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
-                                 ifibss->channel, sband->n_bitrates,
-                                 supp_rates, capability, 0);
+                                 ifibss->channel, 3, /* first two are basic */
+                                 capability, 0);
 }
 
 static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
@@ -499,6 +512,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_channel *chan = NULL;
        const u8 *bssid = NULL;
        int active_ibss;
+       u16 capability;
 
        active_ibss = ieee80211_sta_active_ibss(sdata);
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
@@ -509,6 +523,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
        if (active_ibss)
                return;
 
+       capability = WLAN_CAPABILITY_IBSS;
+       if (sdata->default_key)
+               capability |= WLAN_CAPABILITY_PRIVACY;
+
        if (ifibss->fixed_bssid)
                bssid = ifibss->bssid;
        if (ifibss->fixed_channel)
@@ -517,8 +535,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                bssid = ifibss->bssid;
        bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
                                       ifibss->ssid, ifibss->ssid_len,
-                                      WLAN_CAPABILITY_IBSS,
-                                      WLAN_CAPABILITY_IBSS);
+                                      WLAN_CAPABILITY_IBSS |
+                                      WLAN_CAPABILITY_PRIVACY,
+                                      capability);
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
        if (bss)
@@ -718,6 +737,9 @@ static void ieee80211_ibss_work(struct work_struct *work)
        struct ieee80211_if_ibss *ifibss;
        struct sk_buff *skb;
 
+       if (WARN_ON(local->suspended))
+               return;
+
        if (!netif_running(sdata->dev))
                return;
 
@@ -754,10 +776,36 @@ static void ieee80211_ibss_timer(unsigned long data)
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
 
+       if (local->quiescing) {
+               ifibss->timer_running = true;
+               return;
+       }
+
        set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
        queue_work(local->hw.workqueue, &ifibss->work);
 }
 
+#ifdef CONFIG_PM
+void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+       cancel_work_sync(&ifibss->work);
+       if (del_timer_sync(&ifibss->timer))
+               ifibss->timer_running = true;
+}
+
+void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+       if (ifibss->timer_running) {
+               add_timer(&ifibss->timer);
+               ifibss->timer_running = false;
+       }
+}
+#endif
+
 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;