]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/iface.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / net / mac80211 / iface.c
index a0757913046eab8eee0c99104d8900db4e338c3e..3dfd20a453aba250fff726d1733f0dac6c763b3c 100644 (file)
@@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
                 wiphy_name(local->hw.wiphy));
 
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+
        ieee80211_set_default_queues(sdata);
 
        ret = drv_add_interface(local, sdata);
@@ -416,8 +418,10 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                return ret;
        }
 
+       mutex_lock(&local->mtx);
        ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
                                        IEEE80211_CHANCTX_EXCLUSIVE);
+       mutex_unlock(&local->mtx);
        if (ret) {
                drv_remove_interface(local, sdata);
                kfree(sdata);
@@ -454,7 +458,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 
        synchronize_net();
 
+       mutex_lock(&local->mtx);
        ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&local->mtx);
 
        drv_remove_interface(local, sdata);
 
@@ -749,6 +755,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        u32 hw_reconf_flags = 0;
        int i, flushed;
        struct ps_data *ps;
+       struct cfg80211_chan_def chandef;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
@@ -783,10 +790,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
         * This is relevant only in WDS mode, in all other modes we've
         * already removed all stations when disconnecting or similar,
         * so warn otherwise.
-        *
-        * We call sta_info_flush_cleanup() later, to combine RCU waits.
         */
-       flushed = sta_info_flush_defer(sdata);
+       flushed = sta_info_flush(sdata);
        WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
                     (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
 
@@ -823,11 +828,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
 
        if (sdata->wdev.cac_started) {
+               chandef = sdata->vif.bss_conf.chandef;
                WARN_ON(local->suspended);
-               mutex_lock(&local->iflist_mtx);
+               mutex_lock(&local->mtx);
                ieee80211_vif_release_channel(sdata);
-               mutex_unlock(&local->iflist_mtx);
-               cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
+               mutex_unlock(&local->mtx);
+               cfg80211_cac_event(sdata->dev, &chandef,
+                                  NL80211_RADAR_CAC_ABORTED,
                                   GFP_KERNEL);
        }
 
@@ -886,23 +893,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                cancel_work_sync(&sdata->work);
                /*
                 * When we get here, the interface is marked down.
+                * Free the remaining keys, if there are any
+                * (shouldn't be, except maybe in WDS mode?)
                 *
-                * sta_info_flush_cleanup() requires rcu_barrier()
-                * first to wait for the station call_rcu() calls
-                * to complete, and we also need synchronize_rcu()
-                * to wait for the RX path in case it is using the
-                * interface and enqueuing frames at this very time on
+                * Force the key freeing to always synchronize_net()
+                * to wait for the RX path in case it is using this
+                * interface enqueuing frames * at this very time on
                 * another CPU.
                 */
-               synchronize_rcu();
-               rcu_barrier();
-               sta_info_flush_cleanup(sdata);
-
-               /*
-                * Free all remaining keys, there shouldn't be any,
-                * except maybe in WDS mode?
-                */
-               ieee80211_free_keys(sdata);
+               ieee80211_free_keys(sdata, true);
 
                /* fall through */
        case NL80211_IFTYPE_AP:
@@ -1013,17 +1012,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
                        atomic_dec(&local->iff_promiscs);
                sdata->flags ^= IEEE80211_SDATA_PROMISC;
        }
-
-       /*
-        * TODO: If somebody needs this on AP interfaces,
-        *       it can be enabled easily but multicast
-        *       addresses from VLANs need to be synced.
-        */
-       if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-           sdata->vif.type != NL80211_IFTYPE_AP)
-               drv_set_multicast_list(local, sdata, &dev->mc);
-
        spin_lock_bh(&local->filter_lock);
        __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
        spin_unlock_bh(&local->filter_lock);
@@ -1036,11 +1024,10 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
  */
 static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 {
-       int flushed;
        int i;
 
        /* free extra data */
-       ieee80211_free_keys(sdata);
+       ieee80211_free_keys(sdata, false);
 
        ieee80211_debugfs_remove_netdev(sdata);
 
@@ -1050,9 +1037,6 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 
        if (ieee80211_vif_is_mesh(&sdata->vif))
                mesh_rmc_free(sdata);
-
-       flushed = sta_info_flush(sdata);
-       WARN_ON(flushed);
 }
 
 static void ieee80211_uninit(struct net_device *dev)
@@ -1272,6 +1256,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 
        sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
        sdata->control_port_no_encrypt = false;
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 
        sdata->noack_map = 0;
 
@@ -1497,8 +1482,8 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                        bool used = false;
 
                        list_for_each_entry(sdata, &local->interfaces, list) {
-                               if (memcmp(local->hw.wiphy->addresses[i].addr,
-                                          sdata->vif.addr, ETH_ALEN) == 0) {
+                               if (ether_addr_equal(local->hw.wiphy->addresses[i].addr,
+                                                    sdata->vif.addr)) {
                                        used = true;
                                        break;
                                }
@@ -1558,8 +1543,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                        val += inc;
 
                        list_for_each_entry(sdata, &local->interfaces, list) {
-                               if (memcmp(tmp_addr, sdata->vif.addr,
-                                                       ETH_ALEN) == 0) {
+                               if (ether_addr_equal(tmp_addr, sdata->vif.addr)) {
                                        used = true;
                                        break;
                                }
@@ -1579,15 +1563,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
        mutex_unlock(&local->iflist_mtx);
 }
 
-static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
-
-       ieee80211_cleanup_sdata_stas(sdata);
-}
-
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                     struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params)
@@ -1660,9 +1635,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        INIT_LIST_HEAD(&sdata->key_list);
 
-       spin_lock_init(&sdata->cleanup_stations_lock);
-       INIT_LIST_HEAD(&sdata->cleanup_stations);
-       INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
        INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
                          ieee80211_dfs_cac_timer_work);
        INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
@@ -1687,6 +1659,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
        sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
        sdata->user_power_level = local->user_power_level;
 
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+
        /* setup type-dependent data */
        ieee80211_setup_sdata(sdata, type);