]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/iface.c
Blackfin arch: move EXPORT_SYMBOL to the place where it is actually defined
[linux-2.6-omap-h63xx.git] / net / mac80211 / iface.c
index 8336fee68d3e05b717047e4d8a1ac5f3623542a8..5abbc3f07dd6eb4c035b697698c878450e444c1e 100644 (file)
@@ -65,7 +65,7 @@ static int ieee80211_open(struct net_device *dev)
        struct ieee80211_if_init_conf conf;
        u32 changed = 0;
        int res;
-       bool need_hw_reconfig = 0;
+       u32 hw_reconf_flags = 0;
        u8 null_addr[ETH_ALEN] = {0};
 
        /* fail early if user set an invalid address */
@@ -152,7 +152,8 @@ static int ieee80211_open(struct net_device *dev)
                        res = local->ops->start(local_to_hw(local));
                if (res)
                        goto err_del_bss;
-               need_hw_reconfig = 1;
+               /* we're brought up, everything changes */
+               hw_reconf_flags = ~0;
                ieee80211_led_radio(local, local->hw.conf.radio_enabled);
        }
 
@@ -198,8 +199,10 @@ static int ieee80211_open(struct net_device *dev)
 
                /* must be before the call to ieee80211_configure_filter */
                local->monitors++;
-               if (local->monitors == 1)
+               if (local->monitors == 1) {
                        local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+                       hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+               }
 
                if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
                        local->fif_fcsfail++;
@@ -226,8 +229,14 @@ static int ieee80211_open(struct net_device *dev)
                if (res)
                        goto err_stop;
 
-               if (ieee80211_vif_is_mesh(&sdata->vif))
+               if (ieee80211_vif_is_mesh(&sdata->vif)) {
+                       local->fif_other_bss++;
+                       netif_addr_lock_bh(local->mdev);
+                       ieee80211_configure_filter(local);
+                       netif_addr_unlock_bh(local->mdev);
+
                        ieee80211_start_mesh(sdata);
+               }
                changed |= ieee80211_reset_erp_info(sdata);
                ieee80211_bss_info_change_notify(sdata, changed);
                ieee80211_enable_keys(sdata);
@@ -279,8 +288,8 @@ static int ieee80211_open(struct net_device *dev)
                atomic_inc(&local->iff_promiscs);
 
        local->open_count++;
-       if (need_hw_reconfig) {
-               ieee80211_hw_config(local);
+       if (hw_reconf_flags) {
+               ieee80211_hw_config(local, hw_reconf_flags);
                /*
                 * set default queue parameters so drivers don't
                 * need to initialise the hardware if the hardware
@@ -322,6 +331,7 @@ static int ieee80211_stop(struct net_device *dev)
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_init_conf conf;
        struct sta_info *sta;
+       u32 hw_reconf_flags = 0;
 
        /*
         * Stop TX on this interface first.
@@ -405,8 +415,10 @@ static int ieee80211_stop(struct net_device *dev)
                }
 
                local->monitors--;
-               if (local->monitors == 0)
+               if (local->monitors == 0) {
                        local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+                       hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+               }
 
                if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
                        local->fif_fcsfail--;
@@ -423,7 +435,11 @@ static int ieee80211_stop(struct net_device *dev)
                break;
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_ADHOC:
-               sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED;
+               /* Announce that we are leaving the network. */
+               if (sdata->u.sta.state != IEEE80211_STA_MLME_DISABLED)
+                       ieee80211_sta_deauthenticate(sdata,
+                                               WLAN_REASON_DEAUTH_LEAVING);
+
                memset(sdata->u.sta.bssid, 0, ETH_ALEN);
                del_timer_sync(&sdata->u.sta.timer);
                /*
@@ -450,8 +466,15 @@ static int ieee80211_stop(struct net_device *dev)
                /* fall through */
        case NL80211_IFTYPE_MESH_POINT:
                if (ieee80211_vif_is_mesh(&sdata->vif)) {
-                       /* allmulti is always set on mesh ifaces */
+                       /* other_bss and allmulti are always set on mesh
+                        * ifaces */
+                       local->fif_other_bss--;
                        atomic_dec(&local->iff_allmultis);
+
+                       netif_addr_lock_bh(local->mdev);
+                       ieee80211_configure_filter(local);
+                       netif_addr_unlock_bh(local->mdev);
+
                        ieee80211_stop_mesh(sdata);
                }
                /* fall through */
@@ -504,8 +527,15 @@ static int ieee80211_stop(struct net_device *dev)
 
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
+
+               /* no reconfiguring after stop! */
+               hw_reconf_flags = 0;
        }
 
+       /* do after stop to avoid reconfiguring when we stop anyway */
+       if (hw_reconf_flags)
+               ieee80211_hw_config(local, hw_reconf_flags);
+
        return 0;
 }
 
@@ -668,6 +698,10 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
        if (type == sdata->vif.type)
                return 0;
 
+       /* Setting ad-hoc mode on non-IBSS channel is not supported. */
+       if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)
+               return -EOPNOTSUPP;
+
        /*
         * We could, here, on changes between IBSS/STA/MESH modes,
         * invoke an MLME function instead that disassociates etc.
@@ -682,7 +716,7 @@ 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->bss_conf.basic_rates =
+       sdata->vif.bss_conf.basic_rates =
                ieee80211_mandatory_rates(sdata->local,
                        sdata->local->hw.conf.channel->band);
        sdata->drop_unencrypted = 0;