Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / net / mac80211 / ibss.c
index e2976da..b72ee64 100644 (file)
@@ -92,6 +92,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
                sta_info_flush(sdata->local, sdata);
 
+       /* if merging, indicate to driver that we leave the old IBSS */
+       if (sdata->vif.bss_conf.ibss_joined) {
+               sdata->vif.bss_conf.ibss_joined = false;
+               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
+       }
+
        memcpy(ifibss->bssid, bssid, ETH_ALEN);
 
        sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
@@ -171,6 +177,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        bss_change |= BSS_CHANGED_BSSID;
        bss_change |= BSS_CHANGED_BEACON;
        bss_change |= BSS_CHANGED_BEACON_ENABLED;
+       bss_change |= BSS_CHANGED_IBSS;
+       sdata->vif.bss_conf.ibss_joined = true;
        ieee80211_bss_info_change_notify(sdata, bss_change);
 
        ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
@@ -265,17 +273,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                        sta->sta.supp_rates[band] = supp_rates |
                                ieee80211_mandatory_rates(local, band);
 
+                       if (sta->sta.supp_rates[band] != prev_rates) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-                       if (sta->sta.supp_rates[band] != prev_rates)
                                printk(KERN_DEBUG "%s: updated supp_rates set "
-                                   "for %pM based on beacon info (0x%llx | "
-                                   "0x%llx -> 0x%llx)\n",
-                                   sdata->name,
-                                   sta->sta.addr,
-                                   (unsigned long long) prev_rates,
-                                   (unsigned long long) supp_rates,
-                                   (unsigned long long) sta->sta.supp_rates[band]);
+                                   "for %pM based on beacon/probe_response "
+                                   "(0x%x -> 0x%x)\n",
+                                   sdata->name, sta->sta.addr,
+                                   prev_rates, sta->sta.supp_rates[band]);
 #endif
+                               rate_control_rate_init(sta);
+                       }
                        rcu_read_unlock();
                } else {
                        rcu_read_unlock();
@@ -371,6 +378,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                       sdata->name, mgmt->bssid);
 #endif
                ieee80211_sta_join_ibss(sdata, bss);
+               supp_rates = ieee80211_sta_get_rates(local, elems, band);
                ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
                                       supp_rates, GFP_KERNEL);
        }
@@ -481,7 +489,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
        printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
               "IBSS networks with same SSID (merge)\n", sdata->name);
 
-       ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len);
+       ieee80211_request_internal_scan(sdata,
+                       ifibss->ssid, ifibss->ssid_len,
+                       ifibss->fixed_channel ? ifibss->channel : NULL);
 }
 
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -588,8 +598,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
                       "join\n", sdata->name);
 
-               ieee80211_request_internal_scan(sdata, ifibss->ssid,
-                                               ifibss->ssid_len);
+               ieee80211_request_internal_scan(sdata,
+                               ifibss->ssid, ifibss->ssid_len,
+                               ifibss->fixed_channel ? ifibss->channel : NULL);
        } else {
                int interval = IEEE80211_SCAN_INTERVAL;
 
@@ -897,6 +908,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.channel = params->channel;
        sdata->u.ibss.fixed_channel = params->channel_fixed;
 
+       /* fix ourselves to that channel now already */
+       if (params->channel_fixed) {
+               sdata->local->oper_channel = params->channel;
+               sdata->local->oper_channel_type = NL80211_CHAN_NO_HT;
+       }
+
        if (params->ie) {
                sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
                                           GFP_KERNEL);
@@ -951,7 +968,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        kfree(sdata->u.ibss.ie);
        skb = sdata->u.ibss.presp;
        rcu_assign_pointer(sdata->u.ibss.presp, NULL);
-       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+       sdata->vif.bss_conf.ibss_joined = false;
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
+                                               BSS_CHANGED_IBSS);
        synchronize_rcu();
        kfree_skb(skb);