dev->open = ieee80211_mgmt_open;
dev->stop = ieee80211_mgmt_stop;
dev->type = ARPHRD_IEEE80211_PRISM;
- dev->uninit = ieee80211_if_reinit;
dev->destructor = ieee80211_if_free;
}
dev->change_mtu = ieee80211_change_mtu;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
- dev->uninit = ieee80211_if_reinit;
dev->destructor = ieee80211_if_free;
}
goto fail_dev;
ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+ ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
result = ieee80211_init_rate_ctrl_alg(local, NULL);
if (result < 0) {
* because the driver cannot be handing us frames any
* more and the tasklet is killed.
*/
- list_for_each_entry_safe(sdata, tmp, &local->interfaces, list)
+
+ /*
+ * First, we remove all non-master interfaces. Do this because they
+ * may have bss pointer dependency on the master, and when we free
+ * the master these would be freed as well, breaking our list
+ * iteration completely.
+ */
+ list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+ if (sdata->dev == local->mdev)
+ continue;
+ list_del(&sdata->list);
__ieee80211_if_del(local, sdata);
+ }
+
+ /* then, finally, remove the master interface */
+ __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
rtnl_unlock();
if (ret)
goto fail;
+ /*
+ * Called even when register_netdevice fails, it would
+ * oops if assigned before initialising the rest.
+ */
+ ndev->uninit = ieee80211_if_reinit;
+
ieee80211_debugfs_add_netdev(nsdata);
if (local->open_count > 0)
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int oldtype = sdata->type;
- dev->hard_start_xmit = ieee80211_subif_start_xmit;
-
+ /*
+ * We need to call this function on the master interface
+ * which already has a hard_start_xmit routine assigned
+ * which must not be changed.
+ */
+ if (!dev->hard_start_xmit)
+ dev->hard_start_xmit = ieee80211_subif_start_xmit;
+
+ /*
+ * Called even when register_netdevice fails, it would
+ * oops if assigned before initialising the rest.
+ */
+ dev->uninit = ieee80211_if_reinit;
+
+ /* most have no BSS pointer */
+ sdata->bss = NULL;
sdata->type = type;
+
switch (type) {
case IEEE80211_IF_TYPE_WDS:
- sdata->bss = NULL;
+ /* nothing special */
break;
case IEEE80211_IF_TYPE_VLAN:
sdata->u.vlan.ap = NULL;
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;
ASSERT_RTNL();
kfree(sdata->u.ap.beacon_tail);
kfree(sdata->u.ap.generic_elem);
- if (dev != local->mdev) {
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
- local->total_ps_buffered--;
- dev_kfree_skb(skb);
- }
+ while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+ local->total_ps_buffered--;
+ dev_kfree_skb(skb);
}
break;