aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211.c19
-rw-r--r--net/mac80211/ieee80211_iface.c37
2 files changed, 44 insertions, 12 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index ccf84634f156..52638194e45f 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -265,7 +265,6 @@ void ieee80211_if_mgmt_setup(struct net_device *dev)
265 dev->open = ieee80211_mgmt_open; 265 dev->open = ieee80211_mgmt_open;
266 dev->stop = ieee80211_mgmt_stop; 266 dev->stop = ieee80211_mgmt_stop;
267 dev->type = ARPHRD_IEEE80211_PRISM; 267 dev->type = ARPHRD_IEEE80211_PRISM;
268 dev->uninit = ieee80211_if_reinit;
269 dev->destructor = ieee80211_if_free; 268 dev->destructor = ieee80211_if_free;
270} 269}
271 270
@@ -551,7 +550,6 @@ void ieee80211_if_setup(struct net_device *dev)
551 dev->change_mtu = ieee80211_change_mtu; 550 dev->change_mtu = ieee80211_change_mtu;
552 dev->open = ieee80211_open; 551 dev->open = ieee80211_open;
553 dev->stop = ieee80211_stop; 552 dev->stop = ieee80211_stop;
554 dev->uninit = ieee80211_if_reinit;
555 dev->destructor = ieee80211_if_free; 553 dev->destructor = ieee80211_if_free;
556} 554}
557 555
@@ -1242,6 +1240,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
1242 goto fail_dev; 1240 goto fail_dev;
1243 1241
1244 ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); 1242 ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
1243 ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
1245 1244
1246 result = ieee80211_init_rate_ctrl_alg(local, NULL); 1245 result = ieee80211_init_rate_ctrl_alg(local, NULL);
1247 if (result < 0) { 1246 if (result < 0) {
@@ -1346,8 +1345,22 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1346 * because the driver cannot be handing us frames any 1345 * because the driver cannot be handing us frames any
1347 * more and the tasklet is killed. 1346 * more and the tasklet is killed.
1348 */ 1347 */
1349 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) 1348
1349 /*
1350 * First, we remove all non-master interfaces. Do this because they
1351 * may have bss pointer dependency on the master, and when we free
1352 * the master these would be freed as well, breaking our list
1353 * iteration completely.
1354 */
1355 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
1356 if (sdata->dev == local->mdev)
1357 continue;
1358 list_del(&sdata->list);
1350 __ieee80211_if_del(local, sdata); 1359 __ieee80211_if_del(local, sdata);
1360 }
1361
1362 /* then, finally, remove the master interface */
1363 __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
1351 1364
1352 rtnl_unlock(); 1365 rtnl_unlock();
1353 1366
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index 2ba24ef319da..369ee4f52a29 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -127,6 +127,12 @@ int ieee80211_if_add_mgmt(struct ieee80211_local *local)
127 if (ret) 127 if (ret)
128 goto fail; 128 goto fail;
129 129
130 /*
131 * Called even when register_netdevice fails, it would
132 * oops if assigned before initialising the rest.
133 */
134 ndev->uninit = ieee80211_if_reinit;
135
130 ieee80211_debugfs_add_netdev(nsdata); 136 ieee80211_debugfs_add_netdev(nsdata);
131 137
132 if (local->open_count > 0) 138 if (local->open_count > 0)
@@ -155,12 +161,27 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
155 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 161 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
156 int oldtype = sdata->type; 162 int oldtype = sdata->type;
157 163
158 dev->hard_start_xmit = ieee80211_subif_start_xmit; 164 /*
159 165 * We need to call this function on the master interface
166 * which already has a hard_start_xmit routine assigned
167 * which must not be changed.
168 */
169 if (!dev->hard_start_xmit)
170 dev->hard_start_xmit = ieee80211_subif_start_xmit;
171
172 /*
173 * Called even when register_netdevice fails, it would
174 * oops if assigned before initialising the rest.
175 */
176 dev->uninit = ieee80211_if_reinit;
177
178 /* most have no BSS pointer */
179 sdata->bss = NULL;
160 sdata->type = type; 180 sdata->type = type;
181
161 switch (type) { 182 switch (type) {
162 case IEEE80211_IF_TYPE_WDS: 183 case IEEE80211_IF_TYPE_WDS:
163 sdata->bss = NULL; 184 /* nothing special */
164 break; 185 break;
165 case IEEE80211_IF_TYPE_VLAN: 186 case IEEE80211_IF_TYPE_VLAN:
166 sdata->u.vlan.ap = NULL; 187 sdata->u.vlan.ap = NULL;
@@ -213,6 +234,7 @@ void ieee80211_if_reinit(struct net_device *dev)
213 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 234 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
214 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 235 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
215 struct sta_info *sta; 236 struct sta_info *sta;
237 struct sk_buff *skb;
216 238
217 ASSERT_RTNL(); 239 ASSERT_RTNL();
218 240
@@ -246,12 +268,9 @@ void ieee80211_if_reinit(struct net_device *dev)
246 kfree(sdata->u.ap.beacon_tail); 268 kfree(sdata->u.ap.beacon_tail);
247 kfree(sdata->u.ap.generic_elem); 269 kfree(sdata->u.ap.generic_elem);
248 270
249 if (dev != local->mdev) { 271 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
250 struct sk_buff *skb; 272 local->total_ps_buffered--;
251 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { 273 dev_kfree_skb(skb);
252 local->total_ps_buffered--;
253 dev_kfree_skb(skb);
254 }
255 } 274 }
256 275
257 break; 276 break;