diff options
Diffstat (limited to 'net/mac80211/util.c')
| -rw-r--r-- | net/mac80211/util.c | 162 |
1 files changed, 110 insertions, 52 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9c3200bcfc02..1220f5afdb7e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -567,18 +567,15 @@ void ieee80211_flush_queues(struct ieee80211_local *local, | |||
| 567 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | 567 | IEEE80211_QUEUE_STOP_REASON_FLUSH); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | void ieee80211_iterate_active_interfaces( | 570 | static void __iterate_active_interfaces(struct ieee80211_local *local, |
| 571 | struct ieee80211_hw *hw, u32 iter_flags, | 571 | u32 iter_flags, |
| 572 | void (*iterator)(void *data, u8 *mac, | 572 | void (*iterator)(void *data, u8 *mac, |
| 573 | struct ieee80211_vif *vif), | 573 | struct ieee80211_vif *vif), |
| 574 | void *data) | 574 | void *data) |
| 575 | { | 575 | { |
| 576 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 577 | struct ieee80211_sub_if_data *sdata; | 576 | struct ieee80211_sub_if_data *sdata; |
| 578 | 577 | ||
| 579 | mutex_lock(&local->iflist_mtx); | 578 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
| 580 | |||
| 581 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
| 582 | switch (sdata->vif.type) { | 579 | switch (sdata->vif.type) { |
| 583 | case NL80211_IFTYPE_MONITOR: | 580 | case NL80211_IFTYPE_MONITOR: |
| 584 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | 581 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) |
| @@ -597,13 +594,25 @@ void ieee80211_iterate_active_interfaces( | |||
| 597 | &sdata->vif); | 594 | &sdata->vif); |
| 598 | } | 595 | } |
| 599 | 596 | ||
| 600 | sdata = rcu_dereference_protected(local->monitor_sdata, | 597 | sdata = rcu_dereference_check(local->monitor_sdata, |
| 601 | lockdep_is_held(&local->iflist_mtx)); | 598 | lockdep_is_held(&local->iflist_mtx) || |
| 599 | lockdep_rtnl_is_held()); | ||
| 602 | if (sdata && | 600 | if (sdata && |
| 603 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | 601 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || |
| 604 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | 602 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) |
| 605 | iterator(data, sdata->vif.addr, &sdata->vif); | 603 | iterator(data, sdata->vif.addr, &sdata->vif); |
| 604 | } | ||
| 605 | |||
| 606 | void ieee80211_iterate_active_interfaces( | ||
| 607 | struct ieee80211_hw *hw, u32 iter_flags, | ||
| 608 | void (*iterator)(void *data, u8 *mac, | ||
| 609 | struct ieee80211_vif *vif), | ||
| 610 | void *data) | ||
| 611 | { | ||
| 612 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 606 | 613 | ||
| 614 | mutex_lock(&local->iflist_mtx); | ||
| 615 | __iterate_active_interfaces(local, iter_flags, iterator, data); | ||
| 607 | mutex_unlock(&local->iflist_mtx); | 616 | mutex_unlock(&local->iflist_mtx); |
| 608 | } | 617 | } |
| 609 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 618 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
| @@ -615,38 +624,26 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
| 615 | void *data) | 624 | void *data) |
| 616 | { | 625 | { |
| 617 | struct ieee80211_local *local = hw_to_local(hw); | 626 | struct ieee80211_local *local = hw_to_local(hw); |
| 618 | struct ieee80211_sub_if_data *sdata; | ||
| 619 | 627 | ||
| 620 | rcu_read_lock(); | 628 | rcu_read_lock(); |
| 629 | __iterate_active_interfaces(local, iter_flags, iterator, data); | ||
| 630 | rcu_read_unlock(); | ||
| 631 | } | ||
| 632 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | ||
| 621 | 633 | ||
| 622 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 634 | void ieee80211_iterate_active_interfaces_rtnl( |
| 623 | switch (sdata->vif.type) { | 635 | struct ieee80211_hw *hw, u32 iter_flags, |
| 624 | case NL80211_IFTYPE_MONITOR: | 636 | void (*iterator)(void *data, u8 *mac, |
| 625 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | 637 | struct ieee80211_vif *vif), |
| 626 | continue; | 638 | void *data) |
| 627 | break; | 639 | { |
| 628 | case NL80211_IFTYPE_AP_VLAN: | 640 | struct ieee80211_local *local = hw_to_local(hw); |
| 629 | continue; | ||
| 630 | default: | ||
| 631 | break; | ||
| 632 | } | ||
| 633 | if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && | ||
| 634 | !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
| 635 | continue; | ||
| 636 | if (ieee80211_sdata_running(sdata)) | ||
| 637 | iterator(data, sdata->vif.addr, | ||
| 638 | &sdata->vif); | ||
| 639 | } | ||
| 640 | 641 | ||
| 641 | sdata = rcu_dereference(local->monitor_sdata); | 642 | ASSERT_RTNL(); |
| 642 | if (sdata && | ||
| 643 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | ||
| 644 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
| 645 | iterator(data, sdata->vif.addr, &sdata->vif); | ||
| 646 | 643 | ||
| 647 | rcu_read_unlock(); | 644 | __iterate_active_interfaces(local, iter_flags, iterator, data); |
| 648 | } | 645 | } |
| 649 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 646 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); |
| 650 | 647 | ||
| 651 | /* | 648 | /* |
| 652 | * Nothing should have been stuffed into the workqueue during | 649 | * Nothing should have been stuffed into the workqueue during |
| @@ -1007,14 +1004,21 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
| 1007 | */ | 1004 | */ |
| 1008 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); | 1005 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); |
| 1009 | 1006 | ||
| 1010 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1007 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
| 1011 | /* Set defaults according to 802.11-2007 Table 7-37 */ | 1008 | aCWmax = 1023; |
| 1012 | aCWmax = 1023; | 1009 | if (use_11b) |
| 1013 | if (use_11b) | 1010 | aCWmin = 31; |
| 1014 | aCWmin = 31; | 1011 | else |
| 1015 | else | 1012 | aCWmin = 15; |
| 1016 | aCWmin = 15; | 1013 | |
| 1014 | /* Confiure old 802.11b/g medium access rules. */ | ||
| 1015 | qparam.cw_max = aCWmax; | ||
| 1016 | qparam.cw_min = aCWmin; | ||
| 1017 | qparam.txop = 0; | ||
| 1018 | qparam.aifs = 2; | ||
| 1017 | 1019 | ||
| 1020 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
| 1021 | /* Update if QoS is enabled. */ | ||
| 1018 | if (enable_qos) { | 1022 | if (enable_qos) { |
| 1019 | switch (ac) { | 1023 | switch (ac) { |
| 1020 | case IEEE80211_AC_BK: | 1024 | case IEEE80211_AC_BK: |
| @@ -1050,12 +1054,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
| 1050 | qparam.aifs = 2; | 1054 | qparam.aifs = 2; |
| 1051 | break; | 1055 | break; |
| 1052 | } | 1056 | } |
| 1053 | } else { | ||
| 1054 | /* Confiure old 802.11b/g medium access rules. */ | ||
| 1055 | qparam.cw_max = aCWmax; | ||
| 1056 | qparam.cw_min = aCWmin; | ||
| 1057 | qparam.txop = 0; | ||
| 1058 | qparam.aifs = 2; | ||
| 1059 | } | 1057 | } |
| 1060 | 1058 | ||
| 1061 | qparam.uapsd = false; | 1059 | qparam.uapsd = false; |
| @@ -1084,8 +1082,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
| 1084 | struct ieee80211_mgmt *mgmt; | 1082 | struct ieee80211_mgmt *mgmt; |
| 1085 | int err; | 1083 | int err; |
| 1086 | 1084 | ||
| 1087 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 1085 | /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ |
| 1088 | sizeof(*mgmt) + 6 + extra_len); | 1086 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 6 + extra_len); |
| 1089 | if (!skb) | 1087 | if (!skb) |
| 1090 | return; | 1088 | return; |
| 1091 | 1089 | ||
| @@ -2292,3 +2290,63 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw) | |||
| 2292 | ieee80211_queue_work(hw, &local->radar_detected_work); | 2290 | ieee80211_queue_work(hw, &local->radar_detected_work); |
| 2293 | } | 2291 | } |
| 2294 | EXPORT_SYMBOL(ieee80211_radar_detected); | 2292 | EXPORT_SYMBOL(ieee80211_radar_detected); |
| 2293 | |||
| 2294 | u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) | ||
| 2295 | { | ||
| 2296 | u32 ret; | ||
| 2297 | int tmp; | ||
| 2298 | |||
| 2299 | switch (c->width) { | ||
| 2300 | case NL80211_CHAN_WIDTH_20: | ||
| 2301 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
| 2302 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
| 2303 | break; | ||
| 2304 | case NL80211_CHAN_WIDTH_40: | ||
| 2305 | c->width = NL80211_CHAN_WIDTH_20; | ||
| 2306 | c->center_freq1 = c->chan->center_freq; | ||
| 2307 | ret = IEEE80211_STA_DISABLE_40MHZ | | ||
| 2308 | IEEE80211_STA_DISABLE_VHT; | ||
| 2309 | break; | ||
| 2310 | case NL80211_CHAN_WIDTH_80: | ||
| 2311 | tmp = (30 + c->chan->center_freq - c->center_freq1)/20; | ||
| 2312 | /* n_P40 */ | ||
| 2313 | tmp /= 2; | ||
| 2314 | /* freq_P40 */ | ||
| 2315 | c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; | ||
| 2316 | c->width = NL80211_CHAN_WIDTH_40; | ||
| 2317 | ret = IEEE80211_STA_DISABLE_VHT; | ||
| 2318 | break; | ||
| 2319 | case NL80211_CHAN_WIDTH_80P80: | ||
| 2320 | c->center_freq2 = 0; | ||
| 2321 | c->width = NL80211_CHAN_WIDTH_80; | ||
| 2322 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
| 2323 | IEEE80211_STA_DISABLE_160MHZ; | ||
| 2324 | break; | ||
| 2325 | case NL80211_CHAN_WIDTH_160: | ||
| 2326 | /* n_P20 */ | ||
| 2327 | tmp = (70 + c->chan->center_freq - c->center_freq1)/20; | ||
| 2328 | /* n_P80 */ | ||
| 2329 | tmp /= 4; | ||
| 2330 | c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; | ||
| 2331 | c->width = NL80211_CHAN_WIDTH_80; | ||
| 2332 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
| 2333 | IEEE80211_STA_DISABLE_160MHZ; | ||
| 2334 | break; | ||
| 2335 | default: | ||
| 2336 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
| 2337 | WARN_ON_ONCE(1); | ||
| 2338 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
| 2339 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
| 2340 | break; | ||
| 2341 | case NL80211_CHAN_WIDTH_5: | ||
| 2342 | case NL80211_CHAN_WIDTH_10: | ||
| 2343 | WARN_ON_ONCE(1); | ||
| 2344 | /* keep c->width */ | ||
| 2345 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
| 2346 | break; | ||
| 2347 | } | ||
| 2348 | |||
| 2349 | WARN_ON_ONCE(!cfg80211_chandef_valid(c)); | ||
| 2350 | |||
| 2351 | return ret; | ||
| 2352 | } | ||
