|
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct net_device *dev)
|
|
|
|
|
|
/* we hold the RTNL here so can safely walk the list */
|
|
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
|
|
- if (sdata->dev != dev && netif_running(sdata->dev)) {
|
|
|
+ if (netif_running(sdata->dev)) {
|
|
|
res = 0;
|
|
|
break;
|
|
|
}
|
|
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct net_device *dev)
|
|
|
|
|
|
/* we hold the RTNL here so can safely walk the list */
|
|
|
list_for_each_entry(sdata, &local->interfaces, list)
|
|
|
- if (sdata->dev != dev && netif_running(sdata->dev))
|
|
|
+ if (netif_running(sdata->dev))
|
|
|
dev_close(sdata->dev);
|
|
|
|
|
|
return 0;
|
|
@@ -194,7 +194,7 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
list_for_each_entry(nsdata, &local->interfaces, list) {
|
|
|
struct net_device *ndev = nsdata->dev;
|
|
|
|
|
|
- if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
|
|
|
+ if (ndev != dev && netif_running(ndev)) {
|
|
|
/*
|
|
|
* Allow only a single IBSS interface to be up at any
|
|
|
* time. This is restricted because beacon distribution
|
|
@@ -209,30 +209,6 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
|
|
|
return -EBUSY;
|
|
|
|
|
|
- /*
|
|
|
- * Disallow multiple IBSS/STA mode interfaces.
|
|
|
- *
|
|
|
- * This is a technical restriction, it is possible although
|
|
|
- * most likely not IEEE 802.11 compliant to have multiple
|
|
|
- * STAs with just a single hardware (the TSF timer will not
|
|
|
- * be adjusted properly.)
|
|
|
- *
|
|
|
- * However, because mac80211 uses the master device's BSS
|
|
|
- * information for each STA/IBSS interface, doing this will
|
|
|
- * currently corrupt that BSS information completely, unless,
|
|
|
- * a not very useful case, both STAs are associated to the
|
|
|
- * same BSS.
|
|
|
- *
|
|
|
- * To remove this restriction, the BSS information needs to
|
|
|
- * be embedded in the STA/IBSS mode sdata instead of using
|
|
|
- * the master device's BSS structure.
|
|
|
- */
|
|
|
- if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
|
|
|
- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
|
|
|
- (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
|
|
|
- nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
/*
|
|
|
* The remaining checks are only performed for interfaces
|
|
|
* with the same MAC address.
|
|
@@ -252,7 +228,7 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
*/
|
|
|
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
|
|
|
nsdata->vif.type == IEEE80211_IF_TYPE_AP)
|
|
|
- sdata->u.vlan.ap = nsdata;
|
|
|
+ sdata->bss = &nsdata->u.ap;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -262,10 +238,13 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
return -ENOLINK;
|
|
|
break;
|
|
|
case IEEE80211_IF_TYPE_VLAN:
|
|
|
- if (!sdata->u.vlan.ap)
|
|
|
+ if (!sdata->bss)
|
|
|
return -ENOLINK;
|
|
|
+ list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
|
|
|
break;
|
|
|
case IEEE80211_IF_TYPE_AP:
|
|
|
+ sdata->bss = &sdata->u.ap;
|
|
|
+ break;
|
|
|
case IEEE80211_IF_TYPE_STA:
|
|
|
case IEEE80211_IF_TYPE_MNTR:
|
|
|
case IEEE80211_IF_TYPE_IBSS:
|
|
@@ -283,14 +262,13 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
if (local->ops->start)
|
|
|
res = local->ops->start(local_to_hw(local));
|
|
|
if (res)
|
|
|
- return res;
|
|
|
+ goto err_del_bss;
|
|
|
need_hw_reconfig = 1;
|
|
|
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
|
|
|
}
|
|
|
|
|
|
switch (sdata->vif.type) {
|
|
|
case IEEE80211_IF_TYPE_VLAN:
|
|
|
- list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
|
|
|
/* no need to tell driver */
|
|
|
break;
|
|
|
case IEEE80211_IF_TYPE_MNTR:
|
|
@@ -404,6 +382,10 @@ static int ieee80211_open(struct net_device *dev)
|
|
|
err_stop:
|
|
|
if (!local->open_count && local->ops->stop)
|
|
|
local->ops->stop(local_to_hw(local));
|
|
|
+ err_del_bss:
|
|
|
+ sdata->bss = NULL;
|
|
|
+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
|
|
|
+ list_del(&sdata->u.vlan.list);
|
|
|
return res;
|
|
|
}
|
|
|
|
|
@@ -486,7 +468,6 @@ static int ieee80211_stop(struct net_device *dev)
|
|
|
switch (sdata->vif.type) {
|
|
|
case IEEE80211_IF_TYPE_VLAN:
|
|
|
list_del(&sdata->u.vlan.list);
|
|
|
- sdata->u.vlan.ap = NULL;
|
|
|
/* no need to tell driver */
|
|
|
break;
|
|
|
case IEEE80211_IF_TYPE_MNTR:
|
|
@@ -549,6 +530,8 @@ static int ieee80211_stop(struct net_device *dev)
|
|
|
local->ops->remove_interface(local_to_hw(local), &conf);
|
|
|
}
|
|
|
|
|
|
+ sdata->bss = NULL;
|
|
|
+
|
|
|
if (local->open_count == 0) {
|
|
|
if (netif_running(local->mdev))
|
|
|
dev_close(local->mdev);
|
|
@@ -1659,7 +1642,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
int result;
|
|
|
enum ieee80211_band band;
|
|
|
struct net_device *mdev;
|
|
|
- struct ieee80211_sub_if_data *sdata;
|
|
|
+ struct wireless_dev *mwdev;
|
|
|
|
|
|
/*
|
|
|
* generic code guarantees at least one band,
|
|
@@ -1699,8 +1682,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
hw->ampdu_queues = 0;
|
|
|
#endif
|
|
|
|
|
|
- /* for now, mdev needs sub_if_data :/ */
|
|
|
- mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data),
|
|
|
+ mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
|
|
|
"wmaster%d", ether_setup,
|
|
|
ieee80211_num_queues(hw));
|
|
|
if (!mdev)
|
|
@@ -1709,13 +1691,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
if (ieee80211_num_queues(hw) > 1)
|
|
|
mdev->features |= NETIF_F_MULTI_QUEUE;
|
|
|
|
|
|
- sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
|
|
|
- mdev->ieee80211_ptr = &sdata->wdev;
|
|
|
- sdata->wdev.wiphy = local->hw.wiphy;
|
|
|
+ mwdev = netdev_priv(mdev);
|
|
|
+ mdev->ieee80211_ptr = mwdev;
|
|
|
+ mwdev->wiphy = local->hw.wiphy;
|
|
|
|
|
|
local->mdev = mdev;
|
|
|
|
|
|
- ieee80211_rx_bss_list_init(mdev);
|
|
|
+ ieee80211_rx_bss_list_init(local);
|
|
|
|
|
|
mdev->hard_start_xmit = ieee80211_master_start_xmit;
|
|
|
mdev->open = ieee80211_master_open;
|
|
@@ -1724,16 +1706,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
mdev->header_ops = &ieee80211_header_ops;
|
|
|
mdev->set_multicast_list = ieee80211_master_set_multicast_list;
|
|
|
|
|
|
- sdata->vif.type = IEEE80211_IF_TYPE_AP;
|
|
|
- sdata->dev = mdev;
|
|
|
- sdata->local = local;
|
|
|
- sdata->u.ap.force_unicast_rateidx = -1;
|
|
|
- sdata->u.ap.max_ratectrl_rateidx = -1;
|
|
|
- ieee80211_if_sdata_init(sdata);
|
|
|
-
|
|
|
- /* no RCU needed since we're still during init phase */
|
|
|
- list_add_tail(&sdata->list, &local->interfaces);
|
|
|
-
|
|
|
name = wiphy_dev(local->hw.wiphy)->driver->name;
|
|
|
local->hw.workqueue = create_freezeable_workqueue(name);
|
|
|
if (!local->hw.workqueue) {
|
|
@@ -1779,9 +1751,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
if (result < 0)
|
|
|
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,
|
|
|
hw->rate_control_algorithm);
|
|
|
if (result < 0) {
|
|
@@ -1801,7 +1770,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
ieee80211_install_qdisc(local->mdev);
|
|
|
|
|
|
/* add one default STA interface */
|
|
|
- result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
|
|
|
+ result = ieee80211_if_add(local, "wlan%d", NULL,
|
|
|
IEEE80211_IF_TYPE_STA, NULL);
|
|
|
if (result)
|
|
|
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
|
|
@@ -1817,7 +1786,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
fail_wep:
|
|
|
rate_control_deinitialize(local);
|
|
|
fail_rate:
|
|
|
- ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
|
|
|
unregister_netdevice(local->mdev);
|
|
|
local->mdev = NULL;
|
|
|
fail_dev:
|
|
@@ -1827,10 +1795,8 @@ fail_sta_info:
|
|
|
debugfs_hw_del(local);
|
|
|
destroy_workqueue(local->hw.workqueue);
|
|
|
fail_workqueue:
|
|
|
- if (local->mdev != NULL) {
|
|
|
- ieee80211_if_free(local->mdev);
|
|
|
- local->mdev = NULL;
|
|
|
- }
|
|
|
+ if (local->mdev)
|
|
|
+ free_netdev(local->mdev);
|
|
|
fail_mdev_alloc:
|
|
|
wiphy_unregister(local->hw.wiphy);
|
|
|
return result;
|
|
@@ -1858,24 +1824,19 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
- * 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.
|
|
|
+ * First, we remove all virtual interfaces.
|
|
|
*/
|
|
|
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));
|
|
|
+ unregister_netdevice(local->mdev);
|
|
|
|
|
|
rtnl_unlock();
|
|
|
|
|
|
- ieee80211_rx_bss_list_deinit(local->mdev);
|
|
|
+ ieee80211_rx_bss_list_deinit(local);
|
|
|
ieee80211_clear_tx_pending(local);
|
|
|
sta_info_stop(local);
|
|
|
rate_control_deinitialize(local);
|
|
@@ -1892,8 +1853,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
|
|
wiphy_unregister(local->hw.wiphy);
|
|
|
ieee80211_wep_free(local);
|
|
|
ieee80211_led_exit(local);
|
|
|
- ieee80211_if_free(local->mdev);
|
|
|
- local->mdev = NULL;
|
|
|
+ free_netdev(local->mdev);
|
|
|
}
|
|
|
EXPORT_SYMBOL(ieee80211_unregister_hw);
|
|
|
|