hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c
....@@ -241,9 +241,9 @@
241241 */
242242 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
243243 /* IEEE 802.11a, channel 36..64 */
244
- REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
244
+ REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
245245 /* IEEE 802.11a, channel 100..165 */
246
- REG_RULE(5470-10, 5850+10, 40, 6, 20, 0),
246
+ REG_RULE(5470-10, 5850+10, 80, 6, 20, 0),
247247 #ifdef WL_6G_BAND
248248 REG_RULE(6025-80, 6985+80, 160, 6, 20, 0),
249249 REG_RULE(5935-10, 7115+10, 20, 6, 20, 0),
....@@ -1089,12 +1089,86 @@
10891089 };
10901090 #endif /* CFG80211_6G_SUPPORT */
10911091
1092
+#ifdef WL_CAP_HE
1093
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_6GHZ_BKPORT)
1094
+static struct ieee80211_sband_iftype_data __wl_he_cap = {
1095
+ .types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
1096
+ .he_cap = {
1097
+ .has_he = true,
1098
+ .he_cap_elem = {
1099
+ .mac_cap_info[0] = (IEEE80211_HE_MAC_CAP0_HTC_HE |
1100
+ IEEE80211_HE_MAC_CAP0_TWT_REQ),
1101
+ .mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US,
1102
+ .mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_BSR,
1103
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1104
+ .mac_cap_info[5] = IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX,
1105
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1106
+
1107
+ .phy_cap_info[0] =
1108
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
1109
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G,
1110
+ .phy_cap_info[1] =
1111
+ IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
1112
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
1113
+ .phy_cap_info[2] =
1114
+ IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US,
1115
+ .phy_cap_info[3] =
1116
+ IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER,
1117
+ .phy_cap_info[4] =
1118
+ IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
1119
+ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK |
1120
+ IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4,
1121
+ .phy_cap_info[5] =
1122
+ IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2,
1123
+ .phy_cap_info[6] =
1124
+ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
1125
+ IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
1126
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0))
1127
+ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
1128
+ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
1129
+#else
1130
+ IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
1131
+ IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB |
1132
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) */
1133
+ IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
1134
+ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
1135
+ .phy_cap_info[7] =
1136
+ IEEE80211_HE_PHY_CAP7_MAX_NC_1,
1137
+ .phy_cap_info[8] =
1138
+ IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
1139
+ IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU,
1140
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
1141
+ .phy_cap_info[9] =
1142
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
1143
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU,
1144
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) */
1145
+ },
1146
+ .he_mcs_nss_supp = {
1147
+ .rx_mcs_80 = cpu_to_le16(0xfffa),
1148
+ .tx_mcs_80 = cpu_to_le16(0xfffa),
1149
+ .rx_mcs_160 = cpu_to_le16((0xfffa)),
1150
+ .tx_mcs_160 = cpu_to_le16((0xfffa)),
1151
+ }
1152
+ },
1153
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
1154
+ .he_6ghz_capa = {.capa = cpu_to_le16(0x3038)},
1155
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) */
1156
+};
1157
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) */
1158
+#endif /* WL_CAP_HE */
1159
+
10921160 static struct ieee80211_supported_band __wl_band_2ghz = {
10931161 .band = IEEE80211_BAND_2GHZ,
10941162 .channels = __wl_2ghz_channels,
10951163 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
10961164 .bitrates = wl_g_rates,
1097
- .n_bitrates = wl_g_rates_size
1165
+ .n_bitrates = wl_g_rates_size,
1166
+#ifdef WL_CAP_HE
1167
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_6GHZ_BKPORT)
1168
+ .iftype_data = &__wl_he_cap,
1169
+ .n_iftype_data = 1
1170
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) */
1171
+#endif /* WL_CAP_HE */
10981172 };
10991173
11001174 static struct ieee80211_supported_band __wl_band_5ghz_a = {
....@@ -1102,7 +1176,13 @@
11021176 .channels = __wl_5ghz_a_channels,
11031177 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
11041178 .bitrates = wl_a_rates,
1105
- .n_bitrates = wl_a_rates_size
1179
+ .n_bitrates = wl_a_rates_size,
1180
+#ifdef WL_CAP_HE
1181
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_6GHZ_BKPORT)
1182
+ .iftype_data = &__wl_he_cap,
1183
+ .n_iftype_data = 1
1184
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) */
1185
+#endif /* WL_CAP_HE */
11061186 };
11071187
11081188 #ifdef CFG80211_6G_SUPPORT
....@@ -1111,7 +1191,13 @@
11111191 .channels = __wl_6ghz_channels,
11121192 .n_channels = ARRAY_SIZE(__wl_6ghz_channels),
11131193 .bitrates = wl_a_rates,
1114
- .n_bitrates = wl_a_rates_size
1194
+ .n_bitrates = wl_a_rates_size,
1195
+#ifdef WL_CAP_HE
1196
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) || defined(CONFIG_6GHZ_BKPORT)
1197
+ .iftype_data = &__wl_he_cap,
1198
+ .n_iftype_data = 1
1199
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) */
1200
+#endif /* WL_CAP_HE */
11151201 };
11161202 #endif /* CFG80211_6G_SUPPORT */
11171203
....@@ -6556,11 +6642,11 @@
65566642 }
65576643 if (conn_in_progress || connected ||
65586644 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
6559
- wdev->u.client.ssid_len
6645
+ wdev->u.client.ssid_len)
65606646 #else
6561
- wdev->ssid_len
6562
-#endif
6563
- ) {
6647
+ wdev->ssid_len)
6648
+#endif /* CFG80211_BKPORT_MLO */
6649
+ {
65646650 #ifdef WL_EXT_IAPSTA
65656651 wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_PRE_DISCONNECTING, NULL);
65666652 #endif
....@@ -6607,13 +6693,11 @@
66076693 * disassoc indicates state mismatch with upper layer. Check for state
66086694 * and issue disconnect indication if required.
66096695 */
6610
-
66116696 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
6612
- // terence 20220911: fix me
6613
- if (wdev->links[0].client.current_bss || wdev->u.client.ssid_len)
6697
+ if (wdev->connected || wdev->u.client.ssid_len)
66146698 #else
66156699 if (wdev->current_bss || wdev->ssid_len)
6616
-#endif
6700
+#endif /* CFG80211_BKPORT_MLO */
66176701 {
66186702 WL_INFORM_MEM(("report disconnect event\n"));
66196703 CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
....@@ -10183,7 +10267,7 @@
1018310267 chan = &band->channels[idx];
1018410268 /* Setting current channel to the requested channel */
1018510269 if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
10186
- NL80211_CHAN_HT20) < 0)) {
10270
+ NL80211_CHAN_WIDTH_20) < 0)) {
1018710271 /*
1018810272 * FIXME:
1018910273 *
....@@ -13033,8 +13117,14 @@
1303313117 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1303413118 if (ndev) {
1303513119 wdev = ndev->ieee80211_ptr;
13120
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
13121
+ wdev->u.client.ssid_len =
13122
+ min(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
13123
+ memcpy(wdev->u.client.ssid, ssid->SSID, wdev->u.client.ssid_len);
13124
+#else
1303613125 wdev->ssid_len = min(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
1303713126 memcpy(wdev->ssid, ssid->SSID, wdev->ssid_len);
13127
+#endif /* CFG80211_BKPORT_MLO */
1303813128 WL_ERR(("SSID is %s\n", ssid->SSID));
1303913129 wl_update_prof(cfg, ndev, NULL, ssid, WL_PROF_SSID);
1304013130 } else {
....@@ -13732,13 +13822,13 @@
1373213822 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) || \
1373313823 defined(WL_FILS_ROAM_OFFLD) || defined(CFG80211_ROAM_API_GE_4_12)
1373413824 memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
13735
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
13825
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(CFG80211_BKPORT_MLO)
1373613826 roam_info.links[0].channel = notify_channel;
1373713827 roam_info.links[0].bssid = curbssid;
1373813828 #else
1373913829 roam_info.channel = notify_channel;
1374013830 roam_info.bssid = curbssid;
13741
-#endif
13831
+#endif /* CFG80211_BKPORT_MLO */
1374213832 roam_info.req_ie = conn_info->req_ie;
1374313833 roam_info.req_ie_len = conn_info->req_ie_len;
1374413834 roam_info.resp_ie = conn_info->resp_ie;
....@@ -13935,7 +14025,7 @@
1393514025
1393614026 resp_params = (struct cfg80211_connect_resp_params *)params;
1393714027 resp_params->status = status;
13938
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
14028
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(CFG80211_BKPORT_MLO)
1393914029 resp_params->links[0].bssid = curbssid;
1394014030 resp_params->links[0].bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
1394114031 ssid->SSID, ssid->SSID_len);
....@@ -13944,11 +14034,11 @@
1394414034 resp_params->bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
1394514035 ssid->SSID, ssid->SSID_len);
1394614036 #endif
13947
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
14037
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(CFG80211_BKPORT_MLO)
1394814038 if (!resp_params->links[0].bss)
1394914039 #else
1395014040 if (!resp_params->bss)
13951
-#endif
14041
+#endif /* CFG80211_BKPORT_MLO */
1395214042 {
1395314043 WL_ERR(("null bss\n"));
1395414044 return BCME_ERROR;
....@@ -14063,7 +14153,7 @@
1406314153 if (!ndev->ieee80211_ptr->u.client.ssid_len)
1406414154 #else
1406514155 if (!ndev->ieee80211_ptr->ssid_len)
14066
-#endif
14156
+#endif /* CFG80211_BKPORT_MLO */
1406714157 {
1406814158 /* In certain cases, the delayed cfg80211 work from
1406914159 * disconnect context will induce race conditions in
....@@ -16730,7 +16820,8 @@
1673016820 return err;
1673116821 }
1673216822
16733
-static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
16823
+static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap_2g,
16824
+ s32 bw_cap_5g, s32 bw_cap_6g)
1673416825 {
1673516826 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1673616827 struct ieee80211_channel *band_chan_arr = NULL;
....@@ -16798,14 +16889,13 @@
1679816889 (channel <= CH_MAX_2G_CHANNEL)) {
1679916890 band_chan_arr = __wl_2ghz_channels;
1680016891 array_size = ARRAYSIZE(__wl_2ghz_channels);
16801
- ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
1680216892 }
1680316893 #ifdef CFG80211_6G_SUPPORT
1680416894 else if (CHSPEC_IS6G(chspec) && (channel >= CH_MIN_6G_CHANNEL) &&
1680516895 (channel <= CH_MAX_6G_CHANNEL)) {
1680616896 band_chan_arr = __wl_6ghz_channels;
1680716897 array_size = ARRAYSIZE(__wl_6ghz_channels);
16808
- ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
16898
+ ht40_allowed = WL_BW_CAP_40MHZ(bw_cap_6g);
1680916899 }
1681016900 #endif /* CFG80211_6G_SUPPORT */
1681116901 else if (
....@@ -16819,7 +16909,7 @@
1681916909 (CHSPEC_IS5G(chspec) && channel >= CH_MIN_5G_CHANNEL)) {
1682016910 band_chan_arr = __wl_5ghz_a_channels;
1682116911 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
16822
- ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
16912
+ ht40_allowed = WL_BW_CAP_40MHZ(bw_cap_5g);
1682316913 } else {
1682416914 WL_ERR(("Invalid channel Sepc. 0x%x.\n", chspec));
1682516915 continue;
....@@ -16827,7 +16917,7 @@
1682716917 if (!ht40_allowed && CHSPEC_IS40(chspec))
1682816918 continue;
1682916919 for (j = 0; j < array_size; j++) {
16830
- if (band_chan_arr[j].hw_value == chspec) {
16920
+ if (band_chan_arr[j].hw_value == wf_chspec_primary20_chspec(chspec)) {
1683116921 break;
1683216922 }
1683316923 }
....@@ -16842,7 +16932,7 @@
1684216932 band_chan_arr[index].center_freq =
1684316933 wl_channel_to_frequency(channel, CHSPEC_BAND(chspec));
1684416934 #endif
16845
- band_chan_arr[index].hw_value = chspec;
16935
+ band_chan_arr[index].hw_value = wf_chspec_primary20_chspec(chspec);
1684616936 band_chan_arr[index].beacon_found = false;
1684716937 band_chan_arr[index].flags &= ~IEEE80211_CHAN_DISABLED;
1684816938
....@@ -16850,12 +16940,14 @@
1685016940 /* assuming the order is HT20, HT40 Upper,
1685116941 * HT40 lower from chanspecs
1685216942 */
16853
- u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
16943
+ u32 ht40_flag =
16944
+ band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
1685416945 if (CHSPEC_SB_UPPER(chspec)) {
1685516946 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
1685616947 band_chan_arr[index].flags &=
1685716948 ~IEEE80211_CHAN_NO_HT40;
16858
- band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
16949
+ band_chan_arr[index].flags |=
16950
+ IEEE80211_CHAN_NO_HT40PLUS;
1685916951 } else {
1686016952 /* It should be one of
1686116953 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
....@@ -16880,6 +16972,12 @@
1688016972 }
1688116973
1688216974 }
16975
+
16976
+ WL_CHANNEL_COPY_FLAG(__wl_2ghz_channels);
16977
+ WL_CHANNEL_COPY_FLAG(__wl_5ghz_a_channels);
16978
+#ifdef CFG80211_6G_SUPPORT
16979
+ WL_CHANNEL_COPY_FLAG(__wl_6ghz_channels);
16980
+#endif /* CFG80211_6G_SUPPORT */
1688316981
1688416982 __wl_band_2ghz.n_channels = ARRAYSIZE(__wl_2ghz_channels);
1688516983 __wl_band_5ghz_a.n_channels = ARRAYSIZE(__wl_5ghz_a_channels);
....@@ -16919,8 +17017,8 @@
1691917017 s32 err = 0;
1692017018 s32 index = 0;
1692117019 s32 nmode = 0;
16922
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) || defined(CUSTOMER_HW5)
1692317020 u32 j = 0;
17021
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1692417022 s32 vhtmode = 0;
1692517023 s32 txstreams = 0;
1692617024 s32 rxstreams = 0;
....@@ -16929,11 +17027,14 @@
1692917027 s32 stbc_tx = 0;
1693017028 s32 txbf_bfe_cap = 0;
1693117029 s32 txbf_bfr_cap = 0;
16932
-#endif /* KERNEL >= 3.6 || CUSTOMER_HW5 */
16933
- s32 bw_cap = 0;
17030
+#endif
17031
+ s32 txchain = 0;
17032
+ s32 rxchain = 0;
17033
+ s32 bw_cap_2g = 0, bw_cap_5g = 0, bw_cap_6g = 0;
1693417034 s32 cur_band = -1;
1693517035 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
1693617036
17037
+ WL_INFORM(("%s: Enter\n", __FUNCTION__));
1693717038 bzero(bandlist, sizeof(bandlist));
1693817039 err = wldev_ioctl_get(dev, WLC_GET_BANDLIST, bandlist,
1693917040 sizeof(bandlist));
....@@ -16953,7 +17054,7 @@
1695317054 WL_ERR(("error reading nmode (%d)\n", err));
1695417055 }
1695517056
16956
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) || defined(CUSTOMER_HW5)
17057
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1695717058 err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
1695817059 if (unlikely(err)) {
1695917060 WL_ERR(("error reading vhtmode (%d)\n", err));
....@@ -16995,25 +17096,58 @@
1699517096 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
1699617097 }
1699717098 }
16998
-#endif /* KERNEL >= 3.6 || CUSTOMER_HW5 */
17099
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
17100
+
17101
+ err = wldev_iovar_getint(dev, "txchain", &txchain);
17102
+ if (unlikely(err)) {
17103
+ WL_ERR(("error reading txchain (%d)\n", err));
17104
+ } else if (txchain == 0x03) {
17105
+ txchain = 2;
17106
+ } else {
17107
+ txchain = 1;
17108
+ }
17109
+ err = wldev_iovar_getint(dev, "rxchain", &rxchain);
17110
+ if (unlikely(err)) {
17111
+ WL_ERR(("error reading rxchain (%d)\n", err));
17112
+ } else if (rxchain == 0x03) {
17113
+ rxchain = 2;
17114
+ } else {
17115
+ rxchain = 1;
17116
+ }
1699917117
1700017118 /* For nmode and vhtmode check bw cap */
1700117119 if (nmode ||
17002
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) || defined(CUSTOMER_HW5)
17120
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1700317121 vhtmode ||
17004
-#endif /* KERNEL >= 3.6 || CUSTOMER_HW5 */
17122
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
1700517123 0) {
17006
- err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
17124
+ uint32 value;
17125
+
17126
+ value = WLC_BAND_2G;
17127
+ err = wldev_iovar_getint(dev, "bw_cap", &value);
1700717128 if (unlikely(err)) {
17008
- WL_ERR(("error get mimo_bw_cap (%d)\n", err));
17129
+ WL_ERR(("error get bw_cap 2g (%d)\n", err));
1700917130 }
17131
+ bw_cap_2g = dtoh32(value);
17132
+ value = WLC_BAND_5G;
17133
+ err = wldev_iovar_getint(dev, "bw_cap", &value);
17134
+ if (unlikely(err)) {
17135
+ WL_ERR(("error get bw_cap 5g (%d)\n", err));
17136
+ }
17137
+ bw_cap_5g = dtoh32(value);
17138
+ value = WLC_BAND_6G;
17139
+ err = wldev_iovar_getint(dev, "bw_cap", &value);
17140
+ if (unlikely(err)) {
17141
+ WL_ERR(("error get bw_cap 6g (%d)\n", err));
17142
+ }
17143
+ bw_cap_6g = dtoh32(value);
1701017144 }
1701117145
1701217146 #ifdef WL_6G_BAND
1701317147 wl_is_6g_supported(cfg, bandlist, bandlist[0]);
1701417148 #endif /* WL_6G_BAND */
1701517149
17016
- err = wl_construct_reginfo(cfg, bw_cap);
17150
+ err = wl_construct_reginfo(cfg, bw_cap_2g, bw_cap_5g, bw_cap_6g);
1701717151 if (err) {
1701817152 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
1701917153 if (err != BCME_UNSUPPORTED)
....@@ -17023,6 +17157,9 @@
1702317157 wiphy = bcmcfg_to_wiphy(cfg);
1702417158 nband = bandlist[0];
1702517159
17160
+ wiphy->available_antennas_tx = txchain;
17161
+ wiphy->available_antennas_rx = rxchain;
17162
+
1702617163 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
1702717164 index = -1;
1702817165
....@@ -17030,8 +17167,18 @@
1703017167 bands[IEEE80211_BAND_2GHZ] =
1703117168 &__wl_band_2ghz;
1703217169 index = IEEE80211_BAND_2GHZ;
17033
- if (bw_cap == WLC_N_BW_40ALL)
17034
- bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
17170
+ (void)memset_s(bands[index]->ht_cap.mcs.rx_mask, IEEE80211_HT_MCS_MASK_LEN,
17171
+ 0, IEEE80211_HT_MCS_MASK_LEN);
17172
+ if (nmode && (WL_BW_CAP_40MHZ(bw_cap_2g))) {
17173
+ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
17174
+ IEEE80211_HT_CAP_SGI_40;
17175
+ bands[index]->ht_cap.mcs.rx_mask[4] = 0x01;
17176
+ bands[index]->ht_cap.mcs.rx_highest =
17177
+ cpu_to_le16(150 * rxchain); /* Mbps */
17178
+ } else {
17179
+ bands[index]->ht_cap.mcs.rx_highest =
17180
+ cpu_to_le16(72 * rxchain); /* Mbps */
17181
+ }
1703517182 } else {
1703617183 if (bandlist[i] == WLC_BAND_6G) {
1703717184 #ifdef CFG80211_6G_SUPPORT
....@@ -17062,14 +17209,26 @@
1706217209 continue;
1706317210 }
1706417211
17065
- if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
17066
- bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
17212
+ (void)memset_s(bands[index]->ht_cap.mcs.rx_mask, IEEE80211_HT_MCS_MASK_LEN,
17213
+ 0, IEEE80211_HT_MCS_MASK_LEN);
17214
+ if (nmode && (WL_BW_CAP_40MHZ(bw_cap_5g))) {
17215
+ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
17216
+ IEEE80211_HT_CAP_SGI_40;
17217
+ bands[index]->ht_cap.mcs.rx_mask[4] = 0x01;
17218
+ bands[index]->ht_cap.mcs.rx_highest = cpu_to_le16(150 * rxchain);
17219
+ } else {
17220
+ bands[index]->ht_cap.mcs.rx_highest = cpu_to_le16(72 * rxchain);
17221
+ }
1706717222
17068
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) || defined(CUSTOMER_HW5)
17223
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1706917224 /* VHT capabilities. */
1707017225 if (vhtmode) {
1707117226 /* Supported */
1707217227 bands[index]->vht_cap.vht_supported = TRUE;
17228
+ bands[index]->vht_cap.vht_mcs.tx_highest =
17229
+ cpu_to_le16(433 * txstreams); /* Mbps */
17230
+ bands[index]->vht_cap.vht_mcs.rx_highest =
17231
+ cpu_to_le16(433 * txstreams); /* Mbps */
1707317232
1707417233 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
1707517234 /* TX stream rates. */
....@@ -17092,11 +17251,13 @@
1709217251 }
1709317252
1709417253 /* Capabilities */
17254
+ bands[index]->vht_cap.cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN
17255
+ | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
1709517256 /* 80 MHz is mandatory */
1709617257 bands[index]->vht_cap.cap |=
1709717258 IEEE80211_VHT_CAP_SHORT_GI_80;
1709817259
17099
- if (WL_BW_CAP_160MHZ(bw_cap)) {
17260
+ if (WL_BW_CAP_160MHZ(bw_cap_5g)) {
1710017261 bands[index]->vht_cap.cap |=
1710117262 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1710217263 bands[index]->vht_cap.cap |=
....@@ -17148,7 +17309,7 @@
1714817309 bands[index]->vht_cap.vht_mcs.rx_mcs_map,
1714917310 bands[index]->vht_cap.vht_mcs.tx_mcs_map));
1715017311 }
17151
-#endif /* KERNEL >= 3.6 || CUSTOMER_HW5 */
17312
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
1715217313 }
1715317314
1715417315 if ((index >= 0) && nmode) {
....@@ -17158,7 +17319,10 @@
1715817319 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
1715917320 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
1716017321 /* An HT shall support all EQM rates for one spatial stream */
17161
- bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
17322
+ for (j = 0; j < rxchain; j++) {
17323
+ bands[index]->ht_cap.mcs.rx_mask[j] = 0xff;
17324
+ }
17325
+ bands[index]->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
1716217326 }
1716317327
1716417328 }
....@@ -17623,11 +17787,10 @@
1762317787 struct wireless_dev *wdev = ndev->ieee80211_ptr;
1762417788 struct cfg80211_bss *bss = CFG80211_GET_BSS(wiphy, NULL, latest_bssid,
1762517789 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO)
17626
- wdev->u.client.ssid, wdev->u.client.ssid_len
17790
+ wdev->u.client.ssid, wdev->u.client.ssid_len);
1762717791 #else
17628
- wdev->ssid, wdev->ssid_len
17629
-#endif
17630
- );
17792
+ wdev->ssid, wdev->ssid_len);
17793
+#endif /* CFG80211_BKPORT_MLO */
1763117794
1763217795 BCM_REFERENCE(bss);
1763317796
....@@ -19536,7 +19699,12 @@
1953619699 while (ie) {
1953719700 if (count >= MAX_VNDR_IE_NUMBER)
1953819701 break;
19539
- if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID)) {
19702
+#ifdef HOSTAPD_EID_EXTENSION_SUPPORT
19703
+ if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID))
19704
+#else
19705
+ if (ie->id == DOT11_MNG_VS_ID)
19706
+#endif
19707
+ {
1954019708 vndrie = (const vndr_ie_t *) ie;
1954119709 if (ie->id == DOT11_MNG_ID_EXT_ID) {
1954219710 /* len should be bigger than sizeof ID extn field at least */
....@@ -19876,6 +20044,40 @@
1987620044 return 0;
1987720045 }
1987820046
20047
+#ifdef GET_FW_IE_DATA
20048
+static void
20049
+wl_dump_ie_buf(vndr_ie_buf_t *ie_getbuf)
20050
+{
20051
+ uchar *iebuf;
20052
+ uchar *data;
20053
+ int tot_ie, pktflag, iecount, datalen;
20054
+ vndr_ie_info_t *ie_info;
20055
+ vndr_ie_t *ie;
20056
+
20057
+ memcpy(&tot_ie, (void *)&ie_getbuf->iecount, sizeof(int));
20058
+ tot_ie = dtoh32(tot_ie);
20059
+ iebuf = (uchar *)&ie_getbuf->vndr_ie_list[0];
20060
+
20061
+ printf("-----------------\n");
20062
+ printf("Total IEs %d\n", tot_ie);
20063
+ for (iecount = 0; iecount < tot_ie; iecount++) {
20064
+ ie_info = (vndr_ie_info_t *) iebuf;
20065
+ memcpy(&pktflag, (void *)&ie_info->pktflag, sizeof(uint32));
20066
+ pktflag = dtoh32(pktflag);
20067
+ iebuf += sizeof(uint32);
20068
+ ie = &ie_info->vndr_ie_data;
20069
+ data = &ie->data[0];
20070
+ datalen = ie->len - VNDR_IE_MIN_LEN;
20071
+ printf("index=%d, pktflag=0x%x\n", iecount, pktflag);
20072
+ prhex("IE", (u8 *)ie, ie->len+VNDR_IE_HDR_LEN);
20073
+
20074
+ iebuf += ie->len + VNDR_IE_HDR_LEN;
20075
+ }
20076
+ printf("-----------------\n");
20077
+ printf("\n");
20078
+}
20079
+#endif /* GET_FW_IE_DATA */
20080
+
1987920081 static void
1988020082 wl_print_fw_ie_data(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx)
1988120083 {
....@@ -19887,18 +20089,10 @@
1988720089 bssidx, &cfg->ioctl_buf_sync);
1988820090 if (ret == BCME_OK) {
1988920091 ies = (vndr_ie_buf_t *)cfg->ioctl_buf;
19890
- WL_INFORM_MEM(("FW IE count:%d\n", ies->iecount));
1989120092 #ifdef GET_FW_IE_DATA
19892
- if (wl_dbg_level & WL_DBG_DBG) {
19893
- int i = 0;
19894
- /* If debug enabled, print each IE */
19895
- for (i = 0; i < ies->iecount; i++) {
19896
- vndr_ie_info_t *info = &ies->vndr_ie_list[i];
19897
- WL_DBG_MEM(("pktflag:0x%x\n", info->pktflag));
19898
- prhex("IE:", (u8 *)&info->vndr_ie_data,
19899
- info->vndr_ie_data.len + TLV_HDR_LEN);
19900
- }
19901
- }
20093
+ wl_dump_ie_buf((vndr_ie_buf_t *)cfg->ioctl_buf);
20094
+#else
20095
+ WL_MSG(ndev->name, "FW IE count:%d\n", ies->iecount);
1990220096 #endif /* GET_FW_IE_DATA */
1990320097 } else {
1990420098 WL_ERR(("IE retrieval failed! ret:%d\n", ret));
....@@ -19922,6 +20116,7 @@
1992220116 u32 parsed_ie_buf_len = 0;
1992320117 struct parsed_vndr_ies old_vndr_ies;
1992420118 struct parsed_vndr_ies new_vndr_ies;
20119
+ int del_add_cnt = 0;
1992520120 s32 i;
1992620121 u8 *ptr;
1992720122 s32 remained_buf_len;
....@@ -20065,6 +20260,7 @@
2006520260
2006620261 curr_ie_buf += del_add_ie_buf_len;
2006720262 total_ie_buf_len += del_add_ie_buf_len;
20263
+ del_add_cnt++;
2006820264 }
2006920265 }
2007020266
....@@ -20114,13 +20310,32 @@
2011420310 *mgmt_ie_len += vndrie_info->ie_len;
2011520311 curr_ie_buf += del_add_ie_buf_len;
2011620312 total_ie_buf_len += del_add_ie_buf_len;
20313
+ del_add_cnt++;
2011720314 }
2011820315 }
2011920316
2012020317 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
20121
- ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
20318
+#ifdef VNDR_IE_WAR
20319
+ curr_ie_buf = g_mgmt_ie_buf;
20320
+ for (i=0; i<del_add_cnt; i++) {
20321
+ vndr_ie_setbuf_t *vndr_ie_setbuf = (vndr_ie_setbuf_t *)curr_ie_buf;
20322
+ u32 curr_ie_buf_len;
20323
+ curr_ie_buf_len =
20324
+ (u8*)&vndr_ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] -
20325
+ (u8*)vndr_ie_setbuf;
20326
+ curr_ie_buf_len += vndr_ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len;
20327
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", curr_ie_buf,
20328
+ curr_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
20329
+ bssidx, &cfg->ioctl_buf_sync);
20330
+ if (ret)
20331
+ break;
20332
+ curr_ie_buf += curr_ie_buf_len;
20333
+ }
20334
+#else
20335
+ ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
2012220336 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
2012320337 bssidx, &cfg->ioctl_buf_sync);
20338
+#endif
2012420339 if (ret) {
2012520340 WL_ERR(("vndr_ie set error :%d\n", ret));
2012620341 if (ret == BCME_NOTFOUND) {