]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/mac80211/ibss.c
mac80211: Add netif state checking to ieee80211_ifa_changed
[mv-sheeva.git] / net / mac80211 / ibss.c
index e2976da4e0d9c7e86b21557c1571e2dd7e449db6..d7a96ced2c83ef255cef5ca22a9a99025a7e66a7 100644 (file)
@@ -92,12 +92,18 @@ 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;
 
        local->oper_channel = chan;
-       local->oper_channel_type = NL80211_CHAN_NO_HT;
+       WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
        sband = local->hw.wiphy->bands[chan->band];
@@ -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;
 
@@ -787,6 +798,15 @@ static void ieee80211_ibss_work(struct work_struct *work)
        }
 }
 
+static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+       struct ieee80211_local *local = sdata->local;
+
+       set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
+       ieee80211_queue_work(&local->hw, &ifibss->work);
+}
+
 static void ieee80211_ibss_timer(unsigned long data)
 {
        struct ieee80211_sub_if_data *sdata =
@@ -799,8 +819,7 @@ static void ieee80211_ibss_timer(unsigned long data)
                return;
        }
 
-       set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
-       ieee80211_queue_work(&local->hw, &ifibss->work);
+       ieee80211_queue_ibss_work(sdata);
 }
 
 #ifdef CONFIG_PM
@@ -848,7 +867,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
                if (!sdata->u.ibss.ssid_len)
                        continue;
                sdata->u.ibss.last_scan_completed = jiffies;
-               mod_timer(&sdata->u.ibss.timer, 0);
+               ieee80211_queue_ibss_work(sdata);
        }
        mutex_unlock(&local->iflist_mtx);
 }
@@ -897,6 +916,13 @@ 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;
+               WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
+                                                   NL80211_CHAN_NO_HT));
+       }
+
        if (params->ie) {
                sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
                                           GFP_KERNEL);
@@ -951,7 +977,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);