aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c197
1 files changed, 186 insertions, 11 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2762e8329986..16d76a807c2f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -11,6 +11,8 @@
11#include <net/ip.h> 11#include <net/ip.h>
12#include <net/dsfield.h> 12#include <net/dsfield.h>
13#include "core.h" 13#include "core.h"
14#include "rdev-ops.h"
15
14 16
15struct ieee80211_rate * 17struct ieee80211_rate *
16ieee80211_get_response_rate(struct ieee80211_supported_band *sband, 18ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
@@ -686,10 +688,13 @@ EXPORT_SYMBOL(cfg80211_classify8021d);
686 688
687const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) 689const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
688{ 690{
689 if (bss->information_elements == NULL) 691 const struct cfg80211_bss_ies *ies;
692
693 ies = rcu_dereference(bss->ies);
694 if (!ies)
690 return NULL; 695 return NULL;
691 return cfg80211_find_ie(ie, bss->information_elements, 696
692 bss->len_information_elements); 697 return cfg80211_find_ie(ie, ies->data, ies->len);
693} 698}
694EXPORT_SYMBOL(ieee80211_bss_get_ie); 699EXPORT_SYMBOL(ieee80211_bss_get_ie);
695 700
@@ -705,19 +710,18 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
705 for (i = 0; i < 6; i++) { 710 for (i = 0; i < 6; i++) {
706 if (!wdev->connect_keys->params[i].cipher) 711 if (!wdev->connect_keys->params[i].cipher)
707 continue; 712 continue;
708 if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL, 713 if (rdev_add_key(rdev, dev, i, false, NULL,
709 &wdev->connect_keys->params[i])) { 714 &wdev->connect_keys->params[i])) {
710 netdev_err(dev, "failed to set key %d\n", i); 715 netdev_err(dev, "failed to set key %d\n", i);
711 continue; 716 continue;
712 } 717 }
713 if (wdev->connect_keys->def == i) 718 if (wdev->connect_keys->def == i)
714 if (rdev->ops->set_default_key(wdev->wiphy, dev, 719 if (rdev_set_default_key(rdev, dev, i, true, true)) {
715 i, true, true)) {
716 netdev_err(dev, "failed to set defkey %d\n", i); 720 netdev_err(dev, "failed to set defkey %d\n", i);
717 continue; 721 continue;
718 } 722 }
719 if (wdev->connect_keys->defmgmt == i) 723 if (wdev->connect_keys->defmgmt == i)
720 if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i)) 724 if (rdev_set_default_mgmt_key(rdev, dev, i))
721 netdev_err(dev, "failed to set mgtdef %d\n", i); 725 netdev_err(dev, "failed to set mgtdef %d\n", i);
722 } 726 }
723 727
@@ -850,8 +854,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
850 cfg80211_process_rdev_events(rdev); 854 cfg80211_process_rdev_events(rdev);
851 } 855 }
852 856
853 err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, 857 err = rdev_change_virtual_intf(rdev, dev, ntype, flags, params);
854 ntype, flags, params);
855 858
856 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); 859 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
857 860
@@ -944,14 +947,86 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
944 return __mcs2bitrate[rate->mcs]; 947 return __mcs2bitrate[rate->mcs];
945} 948}
946 949
950static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
951{
952 static const u32 base[4][10] = {
953 { 6500000,
954 13000000,
955 19500000,
956 26000000,
957 39000000,
958 52000000,
959 58500000,
960 65000000,
961 78000000,
962 0,
963 },
964 { 13500000,
965 27000000,
966 40500000,
967 54000000,
968 81000000,
969 108000000,
970 121500000,
971 135000000,
972 162000000,
973 180000000,
974 },
975 { 29300000,
976 58500000,
977 87800000,
978 117000000,
979 175500000,
980 234000000,
981 263300000,
982 292500000,
983 351000000,
984 390000000,
985 },
986 { 58500000,
987 117000000,
988 175500000,
989 234000000,
990 351000000,
991 468000000,
992 526500000,
993 585000000,
994 702000000,
995 780000000,
996 },
997 };
998 u32 bitrate;
999 int idx;
1000
1001 if (WARN_ON_ONCE(rate->mcs > 9))
1002 return 0;
1003
1004 idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH |
1005 RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 :
1006 rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 :
1007 rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0;
1008
1009 bitrate = base[idx][rate->mcs];
1010 bitrate *= rate->nss;
1011
1012 if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1013 bitrate = (bitrate / 9) * 10;
1014
1015 /* do NOT round down here */
1016 return (bitrate + 50000) / 100000;
1017}
1018
947u32 cfg80211_calculate_bitrate(struct rate_info *rate) 1019u32 cfg80211_calculate_bitrate(struct rate_info *rate)
948{ 1020{
949 int modulation, streams, bitrate; 1021 int modulation, streams, bitrate;
950 1022
951 if (!(rate->flags & RATE_INFO_FLAGS_MCS)) 1023 if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
1024 !(rate->flags & RATE_INFO_FLAGS_VHT_MCS))
952 return rate->legacy; 1025 return rate->legacy;
953 if (rate->flags & RATE_INFO_FLAGS_60G) 1026 if (rate->flags & RATE_INFO_FLAGS_60G)
954 return cfg80211_calculate_bitrate_60g(rate); 1027 return cfg80211_calculate_bitrate_60g(rate);
1028 if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
1029 return cfg80211_calculate_bitrate_vht(rate);
955 1030
956 /* the formula below does only work for MCS values smaller than 32 */ 1031 /* the formula below does only work for MCS values smaller than 32 */
957 if (WARN_ON_ONCE(rate->mcs >= 32)) 1032 if (WARN_ON_ONCE(rate->mcs >= 32))
@@ -980,6 +1055,106 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
980} 1055}
981EXPORT_SYMBOL(cfg80211_calculate_bitrate); 1056EXPORT_SYMBOL(cfg80211_calculate_bitrate);
982 1057
1058int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
1059 enum ieee80211_p2p_attr_id attr,
1060 u8 *buf, unsigned int bufsize)
1061{
1062 u8 *out = buf;
1063 u16 attr_remaining = 0;
1064 bool desired_attr = false;
1065 u16 desired_len = 0;
1066
1067 while (len > 0) {
1068 unsigned int iedatalen;
1069 unsigned int copy;
1070 const u8 *iedata;
1071
1072 if (len < 2)
1073 return -EILSEQ;
1074 iedatalen = ies[1];
1075 if (iedatalen + 2 > len)
1076 return -EILSEQ;
1077
1078 if (ies[0] != WLAN_EID_VENDOR_SPECIFIC)
1079 goto cont;
1080
1081 if (iedatalen < 4)
1082 goto cont;
1083
1084 iedata = ies + 2;
1085
1086 /* check WFA OUI, P2P subtype */
1087 if (iedata[0] != 0x50 || iedata[1] != 0x6f ||
1088 iedata[2] != 0x9a || iedata[3] != 0x09)
1089 goto cont;
1090
1091 iedatalen -= 4;
1092 iedata += 4;
1093
1094 /* check attribute continuation into this IE */
1095 copy = min_t(unsigned int, attr_remaining, iedatalen);
1096 if (copy && desired_attr) {
1097 desired_len += copy;
1098 if (out) {
1099 memcpy(out, iedata, min(bufsize, copy));
1100 out += min(bufsize, copy);
1101 bufsize -= min(bufsize, copy);
1102 }
1103
1104
1105 if (copy == attr_remaining)
1106 return desired_len;
1107 }
1108
1109 attr_remaining -= copy;
1110 if (attr_remaining)
1111 goto cont;
1112
1113 iedatalen -= copy;
1114 iedata += copy;
1115
1116 while (iedatalen > 0) {
1117 u16 attr_len;
1118
1119 /* P2P attribute ID & size must fit */
1120 if (iedatalen < 3)
1121 return -EILSEQ;
1122 desired_attr = iedata[0] == attr;
1123 attr_len = get_unaligned_le16(iedata + 1);
1124 iedatalen -= 3;
1125 iedata += 3;
1126
1127 copy = min_t(unsigned int, attr_len, iedatalen);
1128
1129 if (desired_attr) {
1130 desired_len += copy;
1131 if (out) {
1132 memcpy(out, iedata, min(bufsize, copy));
1133 out += min(bufsize, copy);
1134 bufsize -= min(bufsize, copy);
1135 }
1136
1137 if (copy == attr_len)
1138 return desired_len;
1139 }
1140
1141 iedata += copy;
1142 iedatalen -= copy;
1143 attr_remaining = attr_len - copy;
1144 }
1145
1146 cont:
1147 len -= ies[1] + 2;
1148 ies += ies[1] + 2;
1149 }
1150
1151 if (attr_remaining && desired_attr)
1152 return -EILSEQ;
1153
1154 return -ENOENT;
1155}
1156EXPORT_SYMBOL(cfg80211_get_p2p_attr);
1157
983int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 1158int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
984 u32 beacon_int) 1159 u32 beacon_int)
985{ 1160{