aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--net/mac80211/iface.c (renamed from net/mac80211/ieee80211_iface.c)48
1 files changed, 32 insertions, 16 deletions
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/iface.c
index 92f1eb2da311..80954a512185 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/iface.c
@@ -15,6 +15,7 @@
#include "ieee80211_i.h"
#include "sta_info.h"
#include "debugfs_netdev.h"
+#include "mesh.h"
void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
{
@@ -39,7 +40,8 @@ static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
/* Must be called with rtnl lock held. */
int ieee80211_if_add(struct net_device *dev, const char *name,
- struct net_device **new_dev, int type)
+ struct net_device **new_dev, int type,
+ struct vif_params *params)
{
struct net_device *ndev;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
@@ -78,6 +80,12 @@ int ieee80211_if_add(struct net_device *dev, const char *name,
ieee80211_debugfs_add_netdev(sdata);
ieee80211_if_set_type(ndev, type);
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
+ params && params->mesh_id_len)
+ ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
+ params->mesh_id_len,
+ params->mesh_id);
+
/* we're under RTNL so all this is fine */
if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
__ieee80211_if_del(local, sdata);
@@ -118,6 +126,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
sdata->bss = NULL;
sdata->vif.type = type;
+ sdata->basic_rates = 0;
+
switch (type) {
case IEEE80211_IF_TYPE_WDS:
/* nothing special */
@@ -132,6 +142,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
sdata->bss = &sdata->u.ap;
INIT_LIST_HEAD(&sdata->u.ap.vlans);
break;
+ case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS: {
struct ieee80211_sub_if_data *msdata;
@@ -153,15 +164,20 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
sdata->bss = &msdata->u.ap;
+
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ ieee80211_mesh_init_sdata(sdata);
break;
}
case IEEE80211_IF_TYPE_MNTR:
dev->type = ARPHRD_IEEE80211_RADIOTAP;
dev->hard_start_xmit = ieee80211_monitor_start_xmit;
+ sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
+ MONITOR_FLAG_OTHER_BSS;
break;
default:
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
- dev->name, __FUNCTION__, type);
+ dev->name, __func__, type);
}
ieee80211_debugfs_change_if_type(sdata, oldtype);
}
@@ -171,8 +187,8 @@ void ieee80211_if_reinit(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sta_info *sta;
struct sk_buff *skb;
+ int flushed;
ASSERT_RTNL();
@@ -180,6 +196,10 @@ void ieee80211_if_reinit(struct net_device *dev)
ieee80211_if_sdata_deinit(sdata);
+ /* Need to handle mesh specially to allow eliding the function call */
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ mesh_rmc_free(dev);
+
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_INVALID:
/* cannot happen */
@@ -189,6 +209,7 @@ void ieee80211_if_reinit(struct net_device *dev)
/* Remove all virtual interfaces that use this BSS
* as their sdata->bss */
struct ieee80211_sub_if_data *tsdata, *n;
+ struct beacon_data *beacon;
list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
@@ -206,7 +227,10 @@ void ieee80211_if_reinit(struct net_device *dev)
}
}
- kfree(sdata->u.ap.beacon);
+ beacon = sdata->u.ap.beacon;
+ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+ synchronize_rcu();
+ kfree(beacon);
while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
local->total_ps_buffered--;
@@ -216,17 +240,9 @@ void ieee80211_if_reinit(struct net_device *dev)
break;
}
case IEEE80211_IF_TYPE_WDS:
- sta = sta_info_get(local, sdata->u.wds.remote_addr);
- if (sta) {
- sta_info_free(sta);
- sta_info_put(sta);
- } else {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Someone had deleted my STA "
- "entry for the WDS link\n", dev->name);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- }
+ /* nothing to do */
break;
+ case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
kfree(sdata->u.sta.extra_ie);
@@ -249,8 +265,8 @@ void ieee80211_if_reinit(struct net_device *dev)
break;
}
- /* remove all STAs that are bound to this virtual interface */
- sta_info_flush(local, dev);
+ flushed = sta_info_flush(local, sdata);
+ WARN_ON(flushed);
memset(&sdata->u, 0, sizeof(sdata->u));
ieee80211_if_sdata_init(sdata);