aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211_iface.c')
-rw-r--r--net/mac80211/ieee80211_iface.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index 92f1eb2da311..80954a512185 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -15,6 +15,7 @@
15#include "ieee80211_i.h" 15#include "ieee80211_i.h"
16#include "sta_info.h" 16#include "sta_info.h"
17#include "debugfs_netdev.h" 17#include "debugfs_netdev.h"
18#include "mesh.h"
18 19
19void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) 20void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
20{ 21{
@@ -39,7 +40,8 @@ static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
39 40
40/* Must be called with rtnl lock held. */ 41/* Must be called with rtnl lock held. */
41int ieee80211_if_add(struct net_device *dev, const char *name, 42int ieee80211_if_add(struct net_device *dev, const char *name,
42 struct net_device **new_dev, int type) 43 struct net_device **new_dev, int type,
44 struct vif_params *params)
43{ 45{
44 struct net_device *ndev; 46 struct net_device *ndev;
45 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 47 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
@@ -78,6 +80,12 @@ int ieee80211_if_add(struct net_device *dev, const char *name,
78 ieee80211_debugfs_add_netdev(sdata); 80 ieee80211_debugfs_add_netdev(sdata);
79 ieee80211_if_set_type(ndev, type); 81 ieee80211_if_set_type(ndev, type);
80 82
83 if (ieee80211_vif_is_mesh(&sdata->vif) &&
84 params && params->mesh_id_len)
85 ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
86 params->mesh_id_len,
87 params->mesh_id);
88
81 /* we're under RTNL so all this is fine */ 89 /* we're under RTNL so all this is fine */
82 if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) { 90 if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
83 __ieee80211_if_del(local, sdata); 91 __ieee80211_if_del(local, sdata);
@@ -118,6 +126,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
118 sdata->bss = NULL; 126 sdata->bss = NULL;
119 sdata->vif.type = type; 127 sdata->vif.type = type;
120 128
129 sdata->basic_rates = 0;
130
121 switch (type) { 131 switch (type) {
122 case IEEE80211_IF_TYPE_WDS: 132 case IEEE80211_IF_TYPE_WDS:
123 /* nothing special */ 133 /* nothing special */
@@ -132,6 +142,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
132 sdata->bss = &sdata->u.ap; 142 sdata->bss = &sdata->u.ap;
133 INIT_LIST_HEAD(&sdata->u.ap.vlans); 143 INIT_LIST_HEAD(&sdata->u.ap.vlans);
134 break; 144 break;
145 case IEEE80211_IF_TYPE_MESH_POINT:
135 case IEEE80211_IF_TYPE_STA: 146 case IEEE80211_IF_TYPE_STA:
136 case IEEE80211_IF_TYPE_IBSS: { 147 case IEEE80211_IF_TYPE_IBSS: {
137 struct ieee80211_sub_if_data *msdata; 148 struct ieee80211_sub_if_data *msdata;
@@ -153,15 +164,20 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
153 164
154 msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); 165 msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
155 sdata->bss = &msdata->u.ap; 166 sdata->bss = &msdata->u.ap;
167
168 if (ieee80211_vif_is_mesh(&sdata->vif))
169 ieee80211_mesh_init_sdata(sdata);
156 break; 170 break;
157 } 171 }
158 case IEEE80211_IF_TYPE_MNTR: 172 case IEEE80211_IF_TYPE_MNTR:
159 dev->type = ARPHRD_IEEE80211_RADIOTAP; 173 dev->type = ARPHRD_IEEE80211_RADIOTAP;
160 dev->hard_start_xmit = ieee80211_monitor_start_xmit; 174 dev->hard_start_xmit = ieee80211_monitor_start_xmit;
175 sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
176 MONITOR_FLAG_OTHER_BSS;
161 break; 177 break;
162 default: 178 default:
163 printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", 179 printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
164 dev->name, __FUNCTION__, type); 180 dev->name, __func__, type);
165 } 181 }
166 ieee80211_debugfs_change_if_type(sdata, oldtype); 182 ieee80211_debugfs_change_if_type(sdata, oldtype);
167} 183}
@@ -171,8 +187,8 @@ void ieee80211_if_reinit(struct net_device *dev)
171{ 187{
172 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 188 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
173 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 189 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
174 struct sta_info *sta;
175 struct sk_buff *skb; 190 struct sk_buff *skb;
191 int flushed;
176 192
177 ASSERT_RTNL(); 193 ASSERT_RTNL();
178 194
@@ -180,6 +196,10 @@ void ieee80211_if_reinit(struct net_device *dev)
180 196
181 ieee80211_if_sdata_deinit(sdata); 197 ieee80211_if_sdata_deinit(sdata);
182 198
199 /* Need to handle mesh specially to allow eliding the function call */
200 if (ieee80211_vif_is_mesh(&sdata->vif))
201 mesh_rmc_free(dev);
202
183 switch (sdata->vif.type) { 203 switch (sdata->vif.type) {
184 case IEEE80211_IF_TYPE_INVALID: 204 case IEEE80211_IF_TYPE_INVALID:
185 /* cannot happen */ 205 /* cannot happen */
@@ -189,6 +209,7 @@ void ieee80211_if_reinit(struct net_device *dev)
189 /* Remove all virtual interfaces that use this BSS 209 /* Remove all virtual interfaces that use this BSS
190 * as their sdata->bss */ 210 * as their sdata->bss */
191 struct ieee80211_sub_if_data *tsdata, *n; 211 struct ieee80211_sub_if_data *tsdata, *n;
212 struct beacon_data *beacon;
192 213
193 list_for_each_entry_safe(tsdata, n, &local->interfaces, list) { 214 list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
194 if (tsdata != sdata && tsdata->bss == &sdata->u.ap) { 215 if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
@@ -206,7 +227,10 @@ void ieee80211_if_reinit(struct net_device *dev)
206 } 227 }
207 } 228 }
208 229
209 kfree(sdata->u.ap.beacon); 230 beacon = sdata->u.ap.beacon;
231 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
232 synchronize_rcu();
233 kfree(beacon);
210 234
211 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { 235 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
212 local->total_ps_buffered--; 236 local->total_ps_buffered--;
@@ -216,17 +240,9 @@ void ieee80211_if_reinit(struct net_device *dev)
216 break; 240 break;
217 } 241 }
218 case IEEE80211_IF_TYPE_WDS: 242 case IEEE80211_IF_TYPE_WDS:
219 sta = sta_info_get(local, sdata->u.wds.remote_addr); 243 /* nothing to do */
220 if (sta) {
221 sta_info_free(sta);
222 sta_info_put(sta);
223 } else {
224#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
225 printk(KERN_DEBUG "%s: Someone had deleted my STA "
226 "entry for the WDS link\n", dev->name);
227#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
228 }
229 break; 244 break;
245 case IEEE80211_IF_TYPE_MESH_POINT:
230 case IEEE80211_IF_TYPE_STA: 246 case IEEE80211_IF_TYPE_STA:
231 case IEEE80211_IF_TYPE_IBSS: 247 case IEEE80211_IF_TYPE_IBSS:
232 kfree(sdata->u.sta.extra_ie); 248 kfree(sdata->u.sta.extra_ie);
@@ -249,8 +265,8 @@ void ieee80211_if_reinit(struct net_device *dev)
249 break; 265 break;
250 } 266 }
251 267
252 /* remove all STAs that are bound to this virtual interface */ 268 flushed = sta_info_flush(local, sdata);
253 sta_info_flush(local, dev); 269 WARN_ON(flushed);
254 270
255 memset(&sdata->u, 0, sizeof(sdata->u)); 271 memset(&sdata->u, 0, sizeof(sdata->u));
256 ieee80211_if_sdata_init(sdata); 272 ieee80211_if_sdata_init(sdata);