aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c162
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
570void ieee80211_iterate_active_interfaces( 570static 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
606void 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}
609EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 618EXPORT_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}
632EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
621 633
622 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 634void 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}
649EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 646EXPORT_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}
2294EXPORT_SYMBOL(ieee80211_radar_detected); 2292EXPORT_SYMBOL(ieee80211_radar_detected);
2293
2294u32 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}