diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 96 |
1 files changed, 28 insertions, 68 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1c4d3ba6b878..863923964d21 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct net_device *dev) | |||
105 | 105 | ||
106 | /* we hold the RTNL here so can safely walk the list */ | 106 | /* we hold the RTNL here so can safely walk the list */ |
107 | list_for_each_entry(sdata, &local->interfaces, list) { | 107 | list_for_each_entry(sdata, &local->interfaces, list) { |
108 | if (sdata->dev != dev && netif_running(sdata->dev)) { | 108 | if (netif_running(sdata->dev)) { |
109 | res = 0; | 109 | res = 0; |
110 | break; | 110 | break; |
111 | } | 111 | } |
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
126 | 126 | ||
127 | /* we hold the RTNL here so can safely walk the list */ | 127 | /* we hold the RTNL here so can safely walk the list */ |
128 | list_for_each_entry(sdata, &local->interfaces, list) | 128 | list_for_each_entry(sdata, &local->interfaces, list) |
129 | if (sdata->dev != dev && netif_running(sdata->dev)) | 129 | if (netif_running(sdata->dev)) |
130 | dev_close(sdata->dev); | 130 | dev_close(sdata->dev); |
131 | 131 | ||
132 | return 0; | 132 | return 0; |
@@ -194,7 +194,7 @@ static int ieee80211_open(struct net_device *dev) | |||
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | 194 | list_for_each_entry(nsdata, &local->interfaces, list) { |
195 | struct net_device *ndev = nsdata->dev; | 195 | struct net_device *ndev = nsdata->dev; |
196 | 196 | ||
197 | if (ndev != dev && ndev != local->mdev && netif_running(ndev)) { | 197 | if (ndev != dev && netif_running(ndev)) { |
198 | /* | 198 | /* |
199 | * Allow only a single IBSS interface to be up at any | 199 | * Allow only a single IBSS interface to be up at any |
200 | * time. This is restricted because beacon distribution | 200 | * time. This is restricted because beacon distribution |
@@ -210,30 +210,6 @@ static int ieee80211_open(struct net_device *dev) | |||
210 | return -EBUSY; | 210 | return -EBUSY; |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * Disallow multiple IBSS/STA mode interfaces. | ||
214 | * | ||
215 | * This is a technical restriction, it is possible although | ||
216 | * most likely not IEEE 802.11 compliant to have multiple | ||
217 | * STAs with just a single hardware (the TSF timer will not | ||
218 | * be adjusted properly.) | ||
219 | * | ||
220 | * However, because mac80211 uses the master device's BSS | ||
221 | * information for each STA/IBSS interface, doing this will | ||
222 | * currently corrupt that BSS information completely, unless, | ||
223 | * a not very useful case, both STAs are associated to the | ||
224 | * same BSS. | ||
225 | * | ||
226 | * To remove this restriction, the BSS information needs to | ||
227 | * be embedded in the STA/IBSS mode sdata instead of using | ||
228 | * the master device's BSS structure. | ||
229 | */ | ||
230 | if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
231 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && | ||
232 | (nsdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
233 | nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)) | ||
234 | return -EBUSY; | ||
235 | |||
236 | /* | ||
237 | * The remaining checks are only performed for interfaces | 213 | * The remaining checks are only performed for interfaces |
238 | * with the same MAC address. | 214 | * with the same MAC address. |
239 | */ | 215 | */ |
@@ -252,7 +228,7 @@ static int ieee80211_open(struct net_device *dev) | |||
252 | */ | 228 | */ |
253 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && | 229 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && |
254 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) | 230 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) |
255 | sdata->u.vlan.ap = nsdata; | 231 | sdata->bss = &nsdata->u.ap; |
256 | } | 232 | } |
257 | } | 233 | } |
258 | 234 | ||
@@ -262,10 +238,13 @@ static int ieee80211_open(struct net_device *dev) | |||
262 | return -ENOLINK; | 238 | return -ENOLINK; |
263 | break; | 239 | break; |
264 | case IEEE80211_IF_TYPE_VLAN: | 240 | case IEEE80211_IF_TYPE_VLAN: |
265 | if (!sdata->u.vlan.ap) | 241 | if (!sdata->bss) |
266 | return -ENOLINK; | 242 | return -ENOLINK; |
243 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
267 | break; | 244 | break; |
268 | case IEEE80211_IF_TYPE_AP: | 245 | case IEEE80211_IF_TYPE_AP: |
246 | sdata->bss = &sdata->u.ap; | ||
247 | break; | ||
269 | case IEEE80211_IF_TYPE_STA: | 248 | case IEEE80211_IF_TYPE_STA: |
270 | case IEEE80211_IF_TYPE_MNTR: | 249 | case IEEE80211_IF_TYPE_MNTR: |
271 | case IEEE80211_IF_TYPE_IBSS: | 250 | case IEEE80211_IF_TYPE_IBSS: |
@@ -283,14 +262,13 @@ static int ieee80211_open(struct net_device *dev) | |||
283 | if (local->ops->start) | 262 | if (local->ops->start) |
284 | res = local->ops->start(local_to_hw(local)); | 263 | res = local->ops->start(local_to_hw(local)); |
285 | if (res) | 264 | if (res) |
286 | return res; | 265 | goto err_del_bss; |
287 | need_hw_reconfig = 1; | 266 | need_hw_reconfig = 1; |
288 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | 267 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); |
289 | } | 268 | } |
290 | 269 | ||
291 | switch (sdata->vif.type) { | 270 | switch (sdata->vif.type) { |
292 | case IEEE80211_IF_TYPE_VLAN: | 271 | case IEEE80211_IF_TYPE_VLAN: |
293 | list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans); | ||
294 | /* no need to tell driver */ | 272 | /* no need to tell driver */ |
295 | break; | 273 | break; |
296 | case IEEE80211_IF_TYPE_MNTR: | 274 | case IEEE80211_IF_TYPE_MNTR: |
@@ -404,6 +382,10 @@ static int ieee80211_open(struct net_device *dev) | |||
404 | err_stop: | 382 | err_stop: |
405 | if (!local->open_count && local->ops->stop) | 383 | if (!local->open_count && local->ops->stop) |
406 | local->ops->stop(local_to_hw(local)); | 384 | local->ops->stop(local_to_hw(local)); |
385 | err_del_bss: | ||
386 | sdata->bss = NULL; | ||
387 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | ||
388 | list_del(&sdata->u.vlan.list); | ||
407 | return res; | 389 | return res; |
408 | } | 390 | } |
409 | 391 | ||
@@ -486,7 +468,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
486 | switch (sdata->vif.type) { | 468 | switch (sdata->vif.type) { |
487 | case IEEE80211_IF_TYPE_VLAN: | 469 | case IEEE80211_IF_TYPE_VLAN: |
488 | list_del(&sdata->u.vlan.list); | 470 | list_del(&sdata->u.vlan.list); |
489 | sdata->u.vlan.ap = NULL; | ||
490 | /* no need to tell driver */ | 471 | /* no need to tell driver */ |
491 | break; | 472 | break; |
492 | case IEEE80211_IF_TYPE_MNTR: | 473 | case IEEE80211_IF_TYPE_MNTR: |
@@ -549,6 +530,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
549 | local->ops->remove_interface(local_to_hw(local), &conf); | 530 | local->ops->remove_interface(local_to_hw(local), &conf); |
550 | } | 531 | } |
551 | 532 | ||
533 | sdata->bss = NULL; | ||
534 | |||
552 | if (local->open_count == 0) { | 535 | if (local->open_count == 0) { |
553 | if (netif_running(local->mdev)) | 536 | if (netif_running(local->mdev)) |
554 | dev_close(local->mdev); | 537 | dev_close(local->mdev); |
@@ -1659,7 +1642,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1659 | int result; | 1642 | int result; |
1660 | enum ieee80211_band band; | 1643 | enum ieee80211_band band; |
1661 | struct net_device *mdev; | 1644 | struct net_device *mdev; |
1662 | struct ieee80211_sub_if_data *sdata; | 1645 | struct wireless_dev *mwdev; |
1663 | 1646 | ||
1664 | /* | 1647 | /* |
1665 | * generic code guarantees at least one band, | 1648 | * generic code guarantees at least one band, |
@@ -1699,8 +1682,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1699 | hw->ampdu_queues = 0; | 1682 | hw->ampdu_queues = 0; |
1700 | #endif | 1683 | #endif |
1701 | 1684 | ||
1702 | /* for now, mdev needs sub_if_data :/ */ | 1685 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), |
1703 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), | ||
1704 | "wmaster%d", ether_setup, | 1686 | "wmaster%d", ether_setup, |
1705 | ieee80211_num_queues(hw)); | 1687 | ieee80211_num_queues(hw)); |
1706 | if (!mdev) | 1688 | if (!mdev) |
@@ -1709,13 +1691,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1709 | if (ieee80211_num_queues(hw) > 1) | 1691 | if (ieee80211_num_queues(hw) > 1) |
1710 | mdev->features |= NETIF_F_MULTI_QUEUE; | 1692 | mdev->features |= NETIF_F_MULTI_QUEUE; |
1711 | 1693 | ||
1712 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1694 | mwdev = netdev_priv(mdev); |
1713 | mdev->ieee80211_ptr = &sdata->wdev; | 1695 | mdev->ieee80211_ptr = mwdev; |
1714 | sdata->wdev.wiphy = local->hw.wiphy; | 1696 | mwdev->wiphy = local->hw.wiphy; |
1715 | 1697 | ||
1716 | local->mdev = mdev; | 1698 | local->mdev = mdev; |
1717 | 1699 | ||
1718 | ieee80211_rx_bss_list_init(mdev); | 1700 | ieee80211_rx_bss_list_init(local); |
1719 | 1701 | ||
1720 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | 1702 | mdev->hard_start_xmit = ieee80211_master_start_xmit; |
1721 | mdev->open = ieee80211_master_open; | 1703 | mdev->open = ieee80211_master_open; |
@@ -1724,16 +1706,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1724 | mdev->header_ops = &ieee80211_header_ops; | 1706 | mdev->header_ops = &ieee80211_header_ops; |
1725 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | 1707 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; |
1726 | 1708 | ||
1727 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
1728 | sdata->dev = mdev; | ||
1729 | sdata->local = local; | ||
1730 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1731 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1732 | ieee80211_if_sdata_init(sdata); | ||
1733 | |||
1734 | /* no RCU needed since we're still during init phase */ | ||
1735 | list_add_tail(&sdata->list, &local->interfaces); | ||
1736 | |||
1737 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1709 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1738 | local->hw.workqueue = create_freezeable_workqueue(name); | 1710 | local->hw.workqueue = create_freezeable_workqueue(name); |
1739 | if (!local->hw.workqueue) { | 1711 | if (!local->hw.workqueue) { |
@@ -1779,9 +1751,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1779 | if (result < 0) | 1751 | if (result < 0) |
1780 | goto fail_dev; | 1752 | goto fail_dev; |
1781 | 1753 | ||
1782 | ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1783 | ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); | ||
1784 | |||
1785 | result = ieee80211_init_rate_ctrl_alg(local, | 1754 | result = ieee80211_init_rate_ctrl_alg(local, |
1786 | hw->rate_control_algorithm); | 1755 | hw->rate_control_algorithm); |
1787 | if (result < 0) { | 1756 | if (result < 0) { |
@@ -1801,7 +1770,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1801 | ieee80211_install_qdisc(local->mdev); | 1770 | ieee80211_install_qdisc(local->mdev); |
1802 | 1771 | ||
1803 | /* add one default STA interface */ | 1772 | /* add one default STA interface */ |
1804 | result = ieee80211_if_add(local->mdev, "wlan%d", NULL, | 1773 | result = ieee80211_if_add(local, "wlan%d", NULL, |
1805 | IEEE80211_IF_TYPE_STA, NULL); | 1774 | IEEE80211_IF_TYPE_STA, NULL); |
1806 | if (result) | 1775 | if (result) |
1807 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 1776 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", |
@@ -1817,7 +1786,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1817 | fail_wep: | 1786 | fail_wep: |
1818 | rate_control_deinitialize(local); | 1787 | rate_control_deinitialize(local); |
1819 | fail_rate: | 1788 | fail_rate: |
1820 | ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1821 | unregister_netdevice(local->mdev); | 1789 | unregister_netdevice(local->mdev); |
1822 | local->mdev = NULL; | 1790 | local->mdev = NULL; |
1823 | fail_dev: | 1791 | fail_dev: |
@@ -1827,10 +1795,8 @@ fail_sta_info: | |||
1827 | debugfs_hw_del(local); | 1795 | debugfs_hw_del(local); |
1828 | destroy_workqueue(local->hw.workqueue); | 1796 | destroy_workqueue(local->hw.workqueue); |
1829 | fail_workqueue: | 1797 | fail_workqueue: |
1830 | if (local->mdev != NULL) { | 1798 | if (local->mdev) |
1831 | ieee80211_if_free(local->mdev); | 1799 | free_netdev(local->mdev); |
1832 | local->mdev = NULL; | ||
1833 | } | ||
1834 | fail_mdev_alloc: | 1800 | fail_mdev_alloc: |
1835 | wiphy_unregister(local->hw.wiphy); | 1801 | wiphy_unregister(local->hw.wiphy); |
1836 | return result; | 1802 | return result; |
@@ -1858,24 +1824,19 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1858 | */ | 1824 | */ |
1859 | 1825 | ||
1860 | /* | 1826 | /* |
1861 | * First, we remove all non-master interfaces. Do this because they | 1827 | * First, we remove all virtual interfaces. |
1862 | * may have bss pointer dependency on the master, and when we free | ||
1863 | * the master these would be freed as well, breaking our list | ||
1864 | * iteration completely. | ||
1865 | */ | 1828 | */ |
1866 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1829 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1867 | if (sdata->dev == local->mdev) | ||
1868 | continue; | ||
1869 | list_del(&sdata->list); | 1830 | list_del(&sdata->list); |
1870 | __ieee80211_if_del(local, sdata); | 1831 | __ieee80211_if_del(local, sdata); |
1871 | } | 1832 | } |
1872 | 1833 | ||
1873 | /* then, finally, remove the master interface */ | 1834 | /* then, finally, remove the master interface */ |
1874 | __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev)); | 1835 | unregister_netdevice(local->mdev); |
1875 | 1836 | ||
1876 | rtnl_unlock(); | 1837 | rtnl_unlock(); |
1877 | 1838 | ||
1878 | ieee80211_rx_bss_list_deinit(local->mdev); | 1839 | ieee80211_rx_bss_list_deinit(local); |
1879 | ieee80211_clear_tx_pending(local); | 1840 | ieee80211_clear_tx_pending(local); |
1880 | sta_info_stop(local); | 1841 | sta_info_stop(local); |
1881 | rate_control_deinitialize(local); | 1842 | rate_control_deinitialize(local); |
@@ -1892,8 +1853,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1892 | wiphy_unregister(local->hw.wiphy); | 1853 | wiphy_unregister(local->hw.wiphy); |
1893 | ieee80211_wep_free(local); | 1854 | ieee80211_wep_free(local); |
1894 | ieee80211_led_exit(local); | 1855 | ieee80211_led_exit(local); |
1895 | ieee80211_if_free(local->mdev); | 1856 | free_netdev(local->mdev); |
1896 | local->mdev = NULL; | ||
1897 | } | 1857 | } |
1898 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1858 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1899 | 1859 | ||