aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-11-02 23:56:40 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-11-02 23:56:40 -0400
commit31cbecb4ab538f433145bc5a46f3bea9b9627031 (patch)
treed6206d42dea7298f7ef05fd1f7bf474245f0d43a /net/mac80211/util.c
parent2b72c9ccd22c4a3299e5a358dcd639fb253730f4 (diff)
parent278c023a99b0d6b471d0f4a79835c703482e29ac (diff)
Merge branch 'osd-devel' into nfs-for-next
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c280
1 files changed, 88 insertions, 192 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ddeb1b998383..7439d26bf5f9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -19,7 +19,6 @@
19#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/bitmap.h> 21#include <linux/bitmap.h>
22#include <linux/crc32.h>
23#include <net/net_namespace.h> 22#include <net/net_namespace.h>
24#include <net/cfg80211.h> 23#include <net/cfg80211.h>
25#include <net/rtnetlink.h> 24#include <net/rtnetlink.h>
@@ -368,14 +367,14 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
368 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 367 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
369} 368}
370 369
371int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, 370void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
372 struct sk_buff_head *skbs, 371 struct sk_buff_head *skbs,
373 void (*fn)(void *data), void *data) 372 void (*fn)(void *data), void *data)
374{ 373{
375 struct ieee80211_hw *hw = &local->hw; 374 struct ieee80211_hw *hw = &local->hw;
376 struct sk_buff *skb; 375 struct sk_buff *skb;
377 unsigned long flags; 376 unsigned long flags;
378 int queue, ret = 0, i; 377 int queue, i;
379 378
380 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 379 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
381 for (i = 0; i < hw->queues; i++) 380 for (i = 0; i < hw->queues; i++)
@@ -390,7 +389,6 @@ int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
390 continue; 389 continue;
391 } 390 }
392 391
393 ret++;
394 queue = skb_get_queue_mapping(skb); 392 queue = skb_get_queue_mapping(skb);
395 __skb_queue_tail(&local->pending[queue], skb); 393 __skb_queue_tail(&local->pending[queue], skb);
396 } 394 }
@@ -402,14 +400,12 @@ int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
402 __ieee80211_wake_queue(hw, i, 400 __ieee80211_wake_queue(hw, i,
403 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 401 IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
404 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 402 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
405
406 return ret;
407} 403}
408 404
409int ieee80211_add_pending_skbs(struct ieee80211_local *local, 405void ieee80211_add_pending_skbs(struct ieee80211_local *local,
410 struct sk_buff_head *skbs) 406 struct sk_buff_head *skbs)
411{ 407{
412 return ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); 408 ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
413} 409}
414 410
415void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 411void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
@@ -573,172 +569,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
573 ieee802_11_parse_elems_crc(start, len, elems, 0, 0); 569 ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
574} 570}
575 571
576u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
577 struct ieee802_11_elems *elems,
578 u64 filter, u32 crc)
579{
580 size_t left = len;
581 u8 *pos = start;
582 bool calc_crc = filter != 0;
583
584 memset(elems, 0, sizeof(*elems));
585 elems->ie_start = start;
586 elems->total_len = len;
587
588 while (left >= 2) {
589 u8 id, elen;
590
591 id = *pos++;
592 elen = *pos++;
593 left -= 2;
594
595 if (elen > left)
596 break;
597
598 if (calc_crc && id < 64 && (filter & (1ULL << id)))
599 crc = crc32_be(crc, pos - 2, elen + 2);
600
601 switch (id) {
602 case WLAN_EID_SSID:
603 elems->ssid = pos;
604 elems->ssid_len = elen;
605 break;
606 case WLAN_EID_SUPP_RATES:
607 elems->supp_rates = pos;
608 elems->supp_rates_len = elen;
609 break;
610 case WLAN_EID_FH_PARAMS:
611 elems->fh_params = pos;
612 elems->fh_params_len = elen;
613 break;
614 case WLAN_EID_DS_PARAMS:
615 elems->ds_params = pos;
616 elems->ds_params_len = elen;
617 break;
618 case WLAN_EID_CF_PARAMS:
619 elems->cf_params = pos;
620 elems->cf_params_len = elen;
621 break;
622 case WLAN_EID_TIM:
623 if (elen >= sizeof(struct ieee80211_tim_ie)) {
624 elems->tim = (void *)pos;
625 elems->tim_len = elen;
626 }
627 break;
628 case WLAN_EID_IBSS_PARAMS:
629 elems->ibss_params = pos;
630 elems->ibss_params_len = elen;
631 break;
632 case WLAN_EID_CHALLENGE:
633 elems->challenge = pos;
634 elems->challenge_len = elen;
635 break;
636 case WLAN_EID_VENDOR_SPECIFIC:
637 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
638 pos[2] == 0xf2) {
639 /* Microsoft OUI (00:50:F2) */
640
641 if (calc_crc)
642 crc = crc32_be(crc, pos - 2, elen + 2);
643
644 if (pos[3] == 1) {
645 /* OUI Type 1 - WPA IE */
646 elems->wpa = pos;
647 elems->wpa_len = elen;
648 } else if (elen >= 5 && pos[3] == 2) {
649 /* OUI Type 2 - WMM IE */
650 if (pos[4] == 0) {
651 elems->wmm_info = pos;
652 elems->wmm_info_len = elen;
653 } else if (pos[4] == 1) {
654 elems->wmm_param = pos;
655 elems->wmm_param_len = elen;
656 }
657 }
658 }
659 break;
660 case WLAN_EID_RSN:
661 elems->rsn = pos;
662 elems->rsn_len = elen;
663 break;
664 case WLAN_EID_ERP_INFO:
665 elems->erp_info = pos;
666 elems->erp_info_len = elen;
667 break;
668 case WLAN_EID_EXT_SUPP_RATES:
669 elems->ext_supp_rates = pos;
670 elems->ext_supp_rates_len = elen;
671 break;
672 case WLAN_EID_HT_CAPABILITY:
673 if (elen >= sizeof(struct ieee80211_ht_cap))
674 elems->ht_cap_elem = (void *)pos;
675 break;
676 case WLAN_EID_HT_INFORMATION:
677 if (elen >= sizeof(struct ieee80211_ht_info))
678 elems->ht_info_elem = (void *)pos;
679 break;
680 case WLAN_EID_MESH_ID:
681 elems->mesh_id = pos;
682 elems->mesh_id_len = elen;
683 break;
684 case WLAN_EID_MESH_CONFIG:
685 if (elen >= sizeof(struct ieee80211_meshconf_ie))
686 elems->mesh_config = (void *)pos;
687 break;
688 case WLAN_EID_PEER_LINK:
689 elems->peer_link = pos;
690 elems->peer_link_len = elen;
691 break;
692 case WLAN_EID_PREQ:
693 elems->preq = pos;
694 elems->preq_len = elen;
695 break;
696 case WLAN_EID_PREP:
697 elems->prep = pos;
698 elems->prep_len = elen;
699 break;
700 case WLAN_EID_PERR:
701 elems->perr = pos;
702 elems->perr_len = elen;
703 break;
704 case WLAN_EID_RANN:
705 if (elen >= sizeof(struct ieee80211_rann_ie))
706 elems->rann = (void *)pos;
707 break;
708 case WLAN_EID_CHANNEL_SWITCH:
709 elems->ch_switch_elem = pos;
710 elems->ch_switch_elem_len = elen;
711 break;
712 case WLAN_EID_QUIET:
713 if (!elems->quiet_elem) {
714 elems->quiet_elem = pos;
715 elems->quiet_elem_len = elen;
716 }
717 elems->num_of_quiet_elem++;
718 break;
719 case WLAN_EID_COUNTRY:
720 elems->country_elem = pos;
721 elems->country_elem_len = elen;
722 break;
723 case WLAN_EID_PWR_CONSTRAINT:
724 elems->pwr_constr_elem = pos;
725 elems->pwr_constr_elem_len = elen;
726 break;
727 case WLAN_EID_TIMEOUT_INTERVAL:
728 elems->timeout_int = pos;
729 elems->timeout_int_len = elen;
730 break;
731 default:
732 break;
733 }
734
735 left -= elen;
736 pos += elen;
737 }
738
739 return crc;
740}
741
742void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 572void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
743{ 573{
744 struct ieee80211_local *local = sdata->local; 574 struct ieee80211_local *local = sdata->local;
@@ -799,8 +629,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
799 629
800 qparam.uapsd = false; 630 qparam.uapsd = false;
801 631
802 local->tx_conf[queue] = qparam; 632 sdata->tx_conf[queue] = qparam;
803 drv_conf_tx(local, queue, &qparam); 633 drv_conf_tx(local, sdata, queue, &qparam);
804 } 634 }
805 635
806 /* after reinitialize QoS TX queues setting to default, 636 /* after reinitialize QoS TX queues setting to default,
@@ -874,11 +704,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
874 704
875 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 705 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
876 sizeof(*mgmt) + 6 + extra_len); 706 sizeof(*mgmt) + 6 + extra_len);
877 if (!skb) { 707 if (!skb)
878 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
879 "frame\n", sdata->name);
880 return; 708 return;
881 } 709
882 skb_reserve(skb, local->hw.extra_tx_headroom); 710 skb_reserve(skb, local->hw.extra_tx_headroom);
883 711
884 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); 712 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
@@ -1031,11 +859,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1031 859
1032 /* FIXME: come up with a proper value */ 860 /* FIXME: come up with a proper value */
1033 buf = kmalloc(200 + ie_len, GFP_KERNEL); 861 buf = kmalloc(200 + ie_len, GFP_KERNEL);
1034 if (!buf) { 862 if (!buf)
1035 printk(KERN_DEBUG "%s: failed to allocate temporary IE "
1036 "buffer\n", sdata->name);
1037 return NULL; 863 return NULL;
1038 }
1039 864
1040 /* 865 /*
1041 * Do not send DS Channel parameter for directed probe requests 866 * Do not send DS Channel parameter for directed probe requests
@@ -1071,14 +896,18 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1071void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 896void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1072 const u8 *ssid, size_t ssid_len, 897 const u8 *ssid, size_t ssid_len,
1073 const u8 *ie, size_t ie_len, 898 const u8 *ie, size_t ie_len,
1074 u32 ratemask, bool directed) 899 u32 ratemask, bool directed, bool no_cck)
1075{ 900{
1076 struct sk_buff *skb; 901 struct sk_buff *skb;
1077 902
1078 skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, 903 skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
1079 ie, ie_len, directed); 904 ie, ie_len, directed);
1080 if (skb) 905 if (skb) {
906 if (no_cck)
907 IEEE80211_SKB_CB(skb)->flags |=
908 IEEE80211_TX_CTL_NO_CCK_RATE;
1081 ieee80211_tx_skb(sdata, skb); 909 ieee80211_tx_skb(sdata, skb);
910 }
1082} 911}
1083 912
1084u32 ieee80211_sta_get_rates(struct ieee80211_local *local, 913u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
@@ -1205,14 +1034,22 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1205 struct ieee80211_sub_if_data, 1034 struct ieee80211_sub_if_data,
1206 u.ap); 1035 u.ap);
1207 1036
1037 memset(&sta->sta.drv_priv, 0, hw->sta_data_size);
1208 WARN_ON(drv_sta_add(local, sdata, &sta->sta)); 1038 WARN_ON(drv_sta_add(local, sdata, &sta->sta));
1209 } 1039 }
1210 } 1040 }
1211 mutex_unlock(&local->sta_mtx); 1041 mutex_unlock(&local->sta_mtx);
1212 1042
1213 /* reconfigure tx conf */ 1043 /* reconfigure tx conf */
1214 for (i = 0; i < hw->queues; i++) 1044 list_for_each_entry(sdata, &local->interfaces, list) {
1215 drv_conf_tx(local, i, &local->tx_conf[i]); 1045 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
1046 sdata->vif.type == NL80211_IFTYPE_MONITOR ||
1047 !ieee80211_sdata_running(sdata))
1048 continue;
1049
1050 for (i = 0; i < hw->queues; i++)
1051 drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]);
1052 }
1216 1053
1217 /* reconfigure hardware */ 1054 /* reconfigure hardware */
1218 ieee80211_hw_config(local, ~0); 1055 ieee80211_hw_config(local, ~0);
@@ -1248,6 +1085,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1248 changed |= BSS_CHANGED_IBSS; 1085 changed |= BSS_CHANGED_IBSS;
1249 /* fall through */ 1086 /* fall through */
1250 case NL80211_IFTYPE_AP: 1087 case NL80211_IFTYPE_AP:
1088 changed |= BSS_CHANGED_SSID;
1089 /* fall through */
1251 case NL80211_IFTYPE_MESH_POINT: 1090 case NL80211_IFTYPE_MESH_POINT:
1252 changed |= BSS_CHANGED_BEACON | 1091 changed |= BSS_CHANGED_BEACON |
1253 BSS_CHANGED_BEACON_ENABLED; 1092 BSS_CHANGED_BEACON_ENABLED;
@@ -1283,7 +1122,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1283 1122
1284 list_for_each_entry(sta, &local->sta_list, list) { 1123 list_for_each_entry(sta, &local->sta_list, list) {
1285 ieee80211_sta_tear_down_BA_sessions(sta, true); 1124 ieee80211_sta_tear_down_BA_sessions(sta, true);
1286 clear_sta_flags(sta, WLAN_STA_BLOCK_BA); 1125 clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
1287 } 1126 }
1288 1127
1289 mutex_unlock(&local->sta_mtx); 1128 mutex_unlock(&local->sta_mtx);
@@ -1522,3 +1361,60 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
1522 _ieee80211_enable_rssi_reports(sdata, 0, 0); 1361 _ieee80211_enable_rssi_reports(sdata, 0, 0);
1523} 1362}
1524EXPORT_SYMBOL(ieee80211_disable_rssi_reports); 1363EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
1364
1365int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
1366{
1367 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1368 struct ieee80211_local *local = sdata->local;
1369 struct ieee80211_supported_band *sband;
1370 int rate;
1371 u8 i, rates, *pos;
1372
1373 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1374 rates = sband->n_bitrates;
1375 if (rates > 8)
1376 rates = 8;
1377
1378 if (skb_tailroom(skb) < rates + 2)
1379 return -ENOMEM;
1380
1381 pos = skb_put(skb, rates + 2);
1382 *pos++ = WLAN_EID_SUPP_RATES;
1383 *pos++ = rates;
1384 for (i = 0; i < rates; i++) {
1385 rate = sband->bitrates[i].bitrate;
1386 *pos++ = (u8) (rate / 5);
1387 }
1388
1389 return 0;
1390}
1391
1392int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
1393{
1394 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1395 struct ieee80211_local *local = sdata->local;
1396 struct ieee80211_supported_band *sband;
1397 int rate;
1398 u8 i, exrates, *pos;
1399
1400 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1401 exrates = sband->n_bitrates;
1402 if (exrates > 8)
1403 exrates -= 8;
1404 else
1405 exrates = 0;
1406
1407 if (skb_tailroom(skb) < exrates + 2)
1408 return -ENOMEM;
1409
1410 if (exrates) {
1411 pos = skb_put(skb, exrates + 2);
1412 *pos++ = WLAN_EID_EXT_SUPP_RATES;
1413 *pos++ = exrates;
1414 for (i = 8; i < sband->n_bitrates; i++) {
1415 rate = sband->bitrates[i].bitrate;
1416 *pos++ = (u8) (rate / 5);
1417 }
1418 }
1419 return 0;
1420}