hc
2024-05-11 297b60346df8beafee954a0fd7c2d64f33f3b9bc
kernel/drivers/net/wireless/ath/wil6210/cfg80211.c
....@@ -1,18 +1,7 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4
- *
5
- * Permission to use, copy, modify, and/or distribute this software for any
6
- * purpose with or without fee is hereby granted, provided that the above
7
- * copyright notice and this permission notice appear in all copies.
8
- *
9
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
165 */
176
187 #include <linux/etherdevice.h>
....@@ -24,6 +13,22 @@
2413 #include "fw.h"
2514
2615 #define WIL_MAX_ROC_DURATION_MS 5000
16
+
17
+#define WIL_EDMG_CHANNEL_9_SUBCHANNELS (BIT(0) | BIT(1))
18
+#define WIL_EDMG_CHANNEL_10_SUBCHANNELS (BIT(1) | BIT(2))
19
+#define WIL_EDMG_CHANNEL_11_SUBCHANNELS (BIT(2) | BIT(3))
20
+
21
+/* WIL_EDMG_BW_CONFIGURATION define the allowed channel bandwidth
22
+ * configurations as defined by IEEE 802.11 section 9.4.2.251, Table 13.
23
+ * The value 5 allowing CB1 and CB2 of adjacent channels.
24
+ */
25
+#define WIL_EDMG_BW_CONFIGURATION 5
26
+
27
+/* WIL_EDMG_CHANNELS is a bitmap that indicates the 2.16 GHz channel(s) that
28
+ * are allowed to be used for EDMG transmissions in the BSS as defined by
29
+ * IEEE 802.11 section 9.4.2.251.
30
+ */
31
+#define WIL_EDMG_CHANNELS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
2732
2833 bool disable_ap_sme;
2934 module_param(disable_ap_sme, bool, 0444);
....@@ -48,8 +53,81 @@
4853 CHAN60G(1, 0),
4954 CHAN60G(2, 0),
5055 CHAN60G(3, 0),
51
-/* channel 4 not supported yet */
56
+ CHAN60G(4, 0),
5257 };
58
+
59
+/* Rx channel bonding mode */
60
+enum wil_rx_cb_mode {
61
+ WIL_RX_CB_MODE_DMG,
62
+ WIL_RX_CB_MODE_EDMG,
63
+ WIL_RX_CB_MODE_WIDE,
64
+};
65
+
66
+static int wil_rx_cb_mode_to_n_bonded(u8 cb_mode)
67
+{
68
+ switch (cb_mode) {
69
+ case WIL_RX_CB_MODE_DMG:
70
+ case WIL_RX_CB_MODE_EDMG:
71
+ return 1;
72
+ case WIL_RX_CB_MODE_WIDE:
73
+ return 2;
74
+ default:
75
+ return 1;
76
+ }
77
+}
78
+
79
+static int wil_tx_cb_mode_to_n_bonded(u8 cb_mode)
80
+{
81
+ switch (cb_mode) {
82
+ case WMI_TX_MODE_DMG:
83
+ case WMI_TX_MODE_EDMG_CB1:
84
+ return 1;
85
+ case WMI_TX_MODE_EDMG_CB2:
86
+ return 2;
87
+ default:
88
+ return 1;
89
+ }
90
+}
91
+
92
+static void
93
+wil_memdup_ie(u8 **pdst, size_t *pdst_len, const u8 *src, size_t src_len)
94
+{
95
+ kfree(*pdst);
96
+ *pdst = NULL;
97
+ *pdst_len = 0;
98
+ if (src_len > 0) {
99
+ *pdst = kmemdup(src, src_len, GFP_KERNEL);
100
+ if (*pdst)
101
+ *pdst_len = src_len;
102
+ }
103
+}
104
+
105
+static int wil_num_supported_channels(struct wil6210_priv *wil)
106
+{
107
+ int num_channels = ARRAY_SIZE(wil_60ghz_channels);
108
+
109
+ if (!test_bit(WMI_FW_CAPABILITY_CHANNEL_4, wil->fw_capabilities))
110
+ num_channels--;
111
+
112
+ return num_channels;
113
+}
114
+
115
+void update_supported_bands(struct wil6210_priv *wil)
116
+{
117
+ struct wiphy *wiphy = wil_to_wiphy(wil);
118
+
119
+ wil_dbg_misc(wil, "update supported bands");
120
+
121
+ wiphy->bands[NL80211_BAND_60GHZ]->n_channels =
122
+ wil_num_supported_channels(wil);
123
+
124
+ if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities)) {
125
+ wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.channels =
126
+ WIL_EDMG_CHANNELS;
127
+ wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.bw_config =
128
+ WIL_EDMG_BW_CONFIGURATION;
129
+ }
130
+}
53131
54132 /* Vendor id to be used in vendor specific command and events
55133 * to user space.
....@@ -144,6 +222,7 @@
144222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
145223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
146224 WIPHY_VENDOR_CMD_NEED_RUNNING,
225
+ .policy = wil_rf_sector_policy,
147226 .doit = wil_rf_sector_get_cfg
148227 },
149228 {
....@@ -151,6 +230,7 @@
151230 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
152231 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
153232 WIPHY_VENDOR_CMD_NEED_RUNNING,
233
+ .policy = wil_rf_sector_policy,
154234 .doit = wil_rf_sector_set_cfg
155235 },
156236 {
....@@ -159,6 +239,7 @@
159239 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
160240 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
161241 WIPHY_VENDOR_CMD_NEED_RUNNING,
242
+ .policy = wil_rf_sector_policy,
162243 .doit = wil_rf_sector_get_selected
163244 },
164245 {
....@@ -167,6 +248,7 @@
167248 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
168249 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
169250 WIPHY_VENDOR_CMD_NEED_RUNNING,
251
+ .policy = wil_rf_sector_policy,
170252 .doit = wil_rf_sector_set_selected
171253 },
172254 };
....@@ -199,7 +281,9 @@
199281 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
200282 BIT(IEEE80211_STYPE_PROBE_RESP >> 4) |
201283 BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
202
- BIT(IEEE80211_STYPE_DISASSOC >> 4),
284
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
285
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
286
+ BIT(IEEE80211_STYPE_REASSOC_RESP >> 4),
203287 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
204288 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
205289 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
....@@ -236,6 +320,8 @@
236320 [WMI_KEY_USE_PAIRWISE] = "PTK",
237321 [WMI_KEY_USE_RX_GROUP] = "RX_GTK",
238322 [WMI_KEY_USE_TX_GROUP] = "TX_GTK",
323
+ [WMI_KEY_USE_STORE_PTK] = "STORE_PTK",
324
+ [WMI_KEY_USE_APPLY_PTK] = "APPLY_PTK",
239325 };
240326
241327 int wil_iftype_nl2wmi(enum nl80211_iftype type)
....@@ -261,6 +347,86 @@
261347 return -EOPNOTSUPP;
262348 }
263349
350
+int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch)
351
+{
352
+ switch (spec_ch) {
353
+ case 1:
354
+ *wmi_ch = WMI_CHANNEL_1;
355
+ break;
356
+ case 2:
357
+ *wmi_ch = WMI_CHANNEL_2;
358
+ break;
359
+ case 3:
360
+ *wmi_ch = WMI_CHANNEL_3;
361
+ break;
362
+ case 4:
363
+ *wmi_ch = WMI_CHANNEL_4;
364
+ break;
365
+ case 5:
366
+ *wmi_ch = WMI_CHANNEL_5;
367
+ break;
368
+ case 6:
369
+ *wmi_ch = WMI_CHANNEL_6;
370
+ break;
371
+ case 9:
372
+ *wmi_ch = WMI_CHANNEL_9;
373
+ break;
374
+ case 10:
375
+ *wmi_ch = WMI_CHANNEL_10;
376
+ break;
377
+ case 11:
378
+ *wmi_ch = WMI_CHANNEL_11;
379
+ break;
380
+ case 12:
381
+ *wmi_ch = WMI_CHANNEL_12;
382
+ break;
383
+ default:
384
+ return -EINVAL;
385
+ }
386
+
387
+ return 0;
388
+}
389
+
390
+int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch)
391
+{
392
+ switch (wmi_ch) {
393
+ case WMI_CHANNEL_1:
394
+ *spec_ch = 1;
395
+ break;
396
+ case WMI_CHANNEL_2:
397
+ *spec_ch = 2;
398
+ break;
399
+ case WMI_CHANNEL_3:
400
+ *spec_ch = 3;
401
+ break;
402
+ case WMI_CHANNEL_4:
403
+ *spec_ch = 4;
404
+ break;
405
+ case WMI_CHANNEL_5:
406
+ *spec_ch = 5;
407
+ break;
408
+ case WMI_CHANNEL_6:
409
+ *spec_ch = 6;
410
+ break;
411
+ case WMI_CHANNEL_9:
412
+ *spec_ch = 9;
413
+ break;
414
+ case WMI_CHANNEL_10:
415
+ *spec_ch = 10;
416
+ break;
417
+ case WMI_CHANNEL_11:
418
+ *spec_ch = 11;
419
+ break;
420
+ case WMI_CHANNEL_12:
421
+ *spec_ch = 12;
422
+ break;
423
+ default:
424
+ return -EINVAL;
425
+ }
426
+
427
+ return 0;
428
+}
429
+
264430 int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
265431 struct station_info *sinfo)
266432 {
....@@ -275,11 +441,13 @@
275441 } __packed reply;
276442 struct wil_net_stats *stats = &wil->sta[cid].stats;
277443 int rc;
444
+ u8 txflag = RATE_INFO_FLAGS_DMG;
278445
279446 memset(&reply, 0, sizeof(reply));
280447
281448 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd),
282
- WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
449
+ WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply),
450
+ WIL_WMI_CALL_GENERAL_TO_MS);
283451 if (rc)
284452 return rc;
285453
....@@ -287,7 +455,8 @@
287455 " MCS %d TSF 0x%016llx\n"
288456 " BF status 0x%08x RSSI %d SQI %d%%\n"
289457 " Tx Tpt %d goodput %d Rx goodput %d\n"
290
- " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
458
+ " Sectors(rx:tx) my %d:%d peer %d:%d\n"
459
+ " Tx mode %d}\n",
291460 cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs),
292461 le64_to_cpu(reply.evt.tsf), reply.evt.status,
293462 reply.evt.rssi,
....@@ -298,7 +467,8 @@
298467 le16_to_cpu(reply.evt.my_rx_sector),
299468 le16_to_cpu(reply.evt.my_tx_sector),
300469 le16_to_cpu(reply.evt.other_rx_sector),
301
- le16_to_cpu(reply.evt.other_tx_sector));
470
+ le16_to_cpu(reply.evt.other_tx_sector),
471
+ reply.evt.tx_mode);
302472
303473 sinfo->generation = wil->sinfo_gen;
304474
....@@ -311,9 +481,16 @@
311481 BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
312482 BIT_ULL(NL80211_STA_INFO_TX_FAILED);
313483
314
- sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
484
+ if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG)
485
+ txflag = RATE_INFO_FLAGS_EDMG;
486
+
487
+ sinfo->txrate.flags = txflag;
315488 sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
316489 sinfo->rxrate.mcs = stats->last_mcs_rx;
490
+ sinfo->txrate.n_bonded_ch =
491
+ wil_tx_cb_mode_to_n_bonded(reply.evt.tx_mode);
492
+ sinfo->rxrate.n_bonded_ch =
493
+ wil_rx_cb_mode_to_n_bonded(stats->last_cb_mode_rx);
317494 sinfo->rx_bytes = stats->rx_bytes;
318495 sinfo->rx_packets = stats->rx_packets;
319496 sinfo->rx_dropped_misc = stats->rx_dropped;
....@@ -345,8 +522,8 @@
345522
346523 wil_dbg_misc(wil, "get_station: %pM CID %d MID %d\n", mac, cid,
347524 vif->mid);
348
- if (cid < 0)
349
- return cid;
525
+ if (!wil_cid_valid(wil, cid))
526
+ return -ENOENT;
350527
351528 rc = wil_cid_fill_sinfo(vif, cid, sinfo);
352529
....@@ -356,11 +533,11 @@
356533 /*
357534 * Find @idx-th active STA for specific MID for station dump.
358535 */
359
-static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
536
+int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
360537 {
361538 int i;
362539
363
- for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
540
+ for (i = 0; i < wil->max_assoc_sta; i++) {
364541 if (wil->sta[i].status == wil_sta_unused)
365542 continue;
366543 if (wil->sta[i].mid != mid)
....@@ -382,7 +559,7 @@
382559 int rc;
383560 int cid = wil_find_cid_by_idx(wil, vif->mid, idx);
384561
385
- if (cid < 0)
562
+ if (!wil_cid_valid(wil, cid))
386563 return -ENOENT;
387564
388565 ether_addr_copy(mac, wil->sta[cid].addr);
....@@ -430,7 +607,7 @@
430607 .num_different_channels = 1,
431608 };
432609
433
- for (i = 0; i < wil->max_vifs; i++) {
610
+ for (i = 0; i < GET_MAX_VIFS(wil); i++) {
434611 if (wil->vifs[i]) {
435612 wdev = vif_to_wdev(wil->vifs[i]);
436613 params.iftype_num[wdev->iftype]++;
....@@ -451,7 +628,7 @@
451628 };
452629 bool check_combos = false;
453630
454
- for (i = 0; i < wil->max_vifs; i++) {
631
+ for (i = 0; i < GET_MAX_VIFS(wil); i++) {
455632 struct wil6210_vif *vif_pos = wil->vifs[i];
456633
457634 if (vif_pos && vif != vif_pos) {
....@@ -608,6 +785,16 @@
608785 return rc;
609786 }
610787
788
+static bool wil_is_safe_switch(enum nl80211_iftype from,
789
+ enum nl80211_iftype to)
790
+{
791
+ if (from == NL80211_IFTYPE_STATION &&
792
+ to == NL80211_IFTYPE_P2P_CLIENT)
793
+ return true;
794
+
795
+ return false;
796
+}
797
+
611798 static int wil_cfg80211_change_iface(struct wiphy *wiphy,
612799 struct net_device *ndev,
613800 enum nl80211_iftype type,
....@@ -633,7 +820,8 @@
633820 * because it can cause significant disruption
634821 */
635822 if (!wil_has_other_active_ifaces(wil, ndev, true, false) &&
636
- netif_running(ndev) && !wil_is_recovery_blocked(wil)) {
823
+ netif_running(ndev) && !wil_is_recovery_blocked(wil) &&
824
+ !wil_is_safe_switch(wdev->iftype, type)) {
637825 wil_dbg_misc(wil, "interface is up. resetting...\n");
638826 mutex_lock(&wil->mutex);
639827 __wil_down(wil);
....@@ -871,6 +1059,26 @@
8711059 c->control_port_no_encrypt);
8721060 }
8731061
1062
+static const char *
1063
+wil_get_auth_type_name(enum nl80211_auth_type auth_type)
1064
+{
1065
+ switch (auth_type) {
1066
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
1067
+ return "OPEN_SYSTEM";
1068
+ case NL80211_AUTHTYPE_SHARED_KEY:
1069
+ return "SHARED_KEY";
1070
+ case NL80211_AUTHTYPE_FT:
1071
+ return "FT";
1072
+ case NL80211_AUTHTYPE_NETWORK_EAP:
1073
+ return "NETWORK_EAP";
1074
+ case NL80211_AUTHTYPE_SAE:
1075
+ return "SAE";
1076
+ case NL80211_AUTHTYPE_AUTOMATIC:
1077
+ return "AUTOMATIC";
1078
+ default:
1079
+ return "unknown";
1080
+ }
1081
+}
8741082 static void wil_print_connect_params(struct wil6210_priv *wil,
8751083 struct cfg80211_connect_params *sme)
8761084 {
....@@ -884,9 +1092,98 @@
8841092 if (sme->ssid)
8851093 print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET,
8861094 16, 1, sme->ssid, sme->ssid_len, true);
1095
+ if (sme->prev_bssid)
1096
+ wil_info(wil, " Previous BSSID=%pM\n", sme->prev_bssid);
1097
+ wil_info(wil, " Auth Type: %s\n",
1098
+ wil_get_auth_type_name(sme->auth_type));
8871099 wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open");
8881100 wil_info(wil, " PBSS: %d\n", sme->pbss);
8891101 wil_print_crypto(wil, &sme->crypto);
1102
+}
1103
+
1104
+static int wil_ft_connect(struct wiphy *wiphy,
1105
+ struct net_device *ndev,
1106
+ struct cfg80211_connect_params *sme)
1107
+{
1108
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1109
+ struct wil6210_vif *vif = ndev_to_vif(ndev);
1110
+ struct wmi_ft_auth_cmd auth_cmd;
1111
+ int rc;
1112
+
1113
+ if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) {
1114
+ wil_err(wil, "FT: FW does not support FT roaming\n");
1115
+ return -EOPNOTSUPP;
1116
+ }
1117
+
1118
+ if (!sme->prev_bssid) {
1119
+ wil_err(wil, "FT: prev_bssid was not set\n");
1120
+ return -EINVAL;
1121
+ }
1122
+
1123
+ if (ether_addr_equal(sme->prev_bssid, sme->bssid)) {
1124
+ wil_err(wil, "FT: can not roam to same AP\n");
1125
+ return -EINVAL;
1126
+ }
1127
+
1128
+ if (!test_bit(wil_vif_fwconnected, vif->status)) {
1129
+ wil_err(wil, "FT: roam while not connected\n");
1130
+ return -EINVAL;
1131
+ }
1132
+
1133
+ if (vif->privacy != sme->privacy) {
1134
+ wil_err(wil, "FT: privacy mismatch, current (%d) roam (%d)\n",
1135
+ vif->privacy, sme->privacy);
1136
+ return -EINVAL;
1137
+ }
1138
+
1139
+ if (sme->pbss) {
1140
+ wil_err(wil, "FT: roam is not valid for PBSS\n");
1141
+ return -EINVAL;
1142
+ }
1143
+
1144
+ memset(&auth_cmd, 0, sizeof(auth_cmd));
1145
+ auth_cmd.channel = sme->channel->hw_value - 1;
1146
+ ether_addr_copy(auth_cmd.bssid, sme->bssid);
1147
+
1148
+ wil_info(wil, "FT: roaming\n");
1149
+
1150
+ set_bit(wil_vif_ft_roam, vif->status);
1151
+ rc = wmi_send(wil, WMI_FT_AUTH_CMDID, vif->mid,
1152
+ &auth_cmd, sizeof(auth_cmd));
1153
+ if (rc == 0)
1154
+ mod_timer(&vif->connect_timer,
1155
+ jiffies + msecs_to_jiffies(5000));
1156
+ else
1157
+ clear_bit(wil_vif_ft_roam, vif->status);
1158
+
1159
+ return rc;
1160
+}
1161
+
1162
+static int wil_get_wmi_edmg_channel(struct wil6210_priv *wil, u8 edmg_bw_config,
1163
+ u8 edmg_channels, u8 *wmi_ch)
1164
+{
1165
+ if (!edmg_bw_config) {
1166
+ *wmi_ch = 0;
1167
+ return 0;
1168
+ } else if (edmg_bw_config == WIL_EDMG_BW_CONFIGURATION) {
1169
+ /* convert from edmg channel bitmap into edmg channel number */
1170
+ switch (edmg_channels) {
1171
+ case WIL_EDMG_CHANNEL_9_SUBCHANNELS:
1172
+ return wil_spec2wmi_ch(9, wmi_ch);
1173
+ case WIL_EDMG_CHANNEL_10_SUBCHANNELS:
1174
+ return wil_spec2wmi_ch(10, wmi_ch);
1175
+ case WIL_EDMG_CHANNEL_11_SUBCHANNELS:
1176
+ return wil_spec2wmi_ch(11, wmi_ch);
1177
+ default:
1178
+ wil_err(wil, "Unsupported edmg channel bitmap 0x%x\n",
1179
+ edmg_channels);
1180
+ return -EINVAL;
1181
+ }
1182
+ } else {
1183
+ wil_err(wil, "Unsupported EDMG BW configuration %d\n",
1184
+ edmg_bw_config);
1185
+ return -EINVAL;
1186
+ }
8901187 }
8911188
8921189 static int wil_cfg80211_connect(struct wiphy *wiphy,
....@@ -901,14 +1198,23 @@
9011198 const u8 *rsn_eid;
9021199 int ch;
9031200 int rc = 0;
1201
+ bool is_ft_roam = false;
1202
+ u8 network_type;
9041203 enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
9051204
9061205 wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid);
9071206 wil_print_connect_params(wil, sme);
9081207
909
- if (test_bit(wil_vif_fwconnecting, vif->status) ||
1208
+ if (sme->auth_type == NL80211_AUTHTYPE_FT)
1209
+ is_ft_roam = true;
1210
+ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC &&
9101211 test_bit(wil_vif_fwconnected, vif->status))
911
- return -EALREADY;
1212
+ is_ft_roam = true;
1213
+
1214
+ if (!is_ft_roam)
1215
+ if (test_bit(wil_vif_fwconnecting, vif->status) ||
1216
+ test_bit(wil_vif_fwconnected, vif->status))
1217
+ return -EALREADY;
9121218
9131219 if (sme->ie_len > WMI_MAX_IE_LEN) {
9141220 wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len);
....@@ -918,8 +1224,13 @@
9181224 rsn_eid = sme->ie ?
9191225 cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
9201226 NULL;
921
- if (sme->privacy && !rsn_eid)
1227
+ if (sme->privacy && !rsn_eid) {
9221228 wil_info(wil, "WSC connection\n");
1229
+ if (is_ft_roam) {
1230
+ wil_err(wil, "No WSC with FT roam\n");
1231
+ return -EINVAL;
1232
+ }
1233
+ }
9231234
9241235 if (sme->pbss)
9251236 bss_type = IEEE80211_BSS_TYPE_PBSS;
....@@ -941,6 +1252,45 @@
9411252 vif->privacy = sme->privacy;
9421253 vif->pbss = sme->pbss;
9431254
1255
+ rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
1256
+ if (rc)
1257
+ goto out;
1258
+
1259
+ switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
1260
+ case WLAN_CAPABILITY_DMG_TYPE_AP:
1261
+ network_type = WMI_NETTYPE_INFRA;
1262
+ break;
1263
+ case WLAN_CAPABILITY_DMG_TYPE_PBSS:
1264
+ network_type = WMI_NETTYPE_P2P;
1265
+ break;
1266
+ default:
1267
+ wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
1268
+ bss->capability);
1269
+ rc = -EINVAL;
1270
+ goto out;
1271
+ }
1272
+
1273
+ ch = bss->channel->hw_value;
1274
+ if (ch == 0) {
1275
+ wil_err(wil, "BSS at unknown frequency %dMhz\n",
1276
+ bss->channel->center_freq);
1277
+ rc = -EOPNOTSUPP;
1278
+ goto out;
1279
+ }
1280
+
1281
+ if (is_ft_roam) {
1282
+ if (network_type != WMI_NETTYPE_INFRA) {
1283
+ wil_err(wil, "FT: Unsupported BSS type, capability= 0x%04x\n",
1284
+ bss->capability);
1285
+ rc = -EINVAL;
1286
+ goto out;
1287
+ }
1288
+ rc = wil_ft_connect(wiphy, ndev, sme);
1289
+ if (rc == 0)
1290
+ vif->bss = bss;
1291
+ goto out;
1292
+ }
1293
+
9441294 if (vif->privacy) {
9451295 /* For secure assoc, remove old keys */
9461296 rc = wmi_del_cipher_key(vif, 0, bss->bssid,
....@@ -957,28 +1307,9 @@
9571307 }
9581308 }
9591309
960
- /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info
961
- * elements. Send it also in case it's empty, to erase previously set
962
- * ies in FW.
963
- */
964
- rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
965
- if (rc)
966
- goto out;
967
-
9681310 /* WMI_CONNECT_CMD */
9691311 memset(&conn, 0, sizeof(conn));
970
- switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
971
- case WLAN_CAPABILITY_DMG_TYPE_AP:
972
- conn.network_type = WMI_NETTYPE_INFRA;
973
- break;
974
- case WLAN_CAPABILITY_DMG_TYPE_PBSS:
975
- conn.network_type = WMI_NETTYPE_P2P;
976
- break;
977
- default:
978
- wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
979
- bss->capability);
980
- goto out;
981
- }
1312
+ conn.network_type = network_type;
9821313 if (vif->privacy) {
9831314 if (rsn_eid) { /* regular secure connection */
9841315 conn.dot11_auth_mode = WMI_AUTH11_SHARED;
....@@ -998,15 +1329,12 @@
9981329
9991330 conn.ssid_len = min_t(u8, ssid_eid[1], 32);
10001331 memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
1001
-
1002
- ch = bss->channel->hw_value;
1003
- if (ch == 0) {
1004
- wil_err(wil, "BSS at unknown frequency %dMhz\n",
1005
- bss->channel->center_freq);
1006
- rc = -EOPNOTSUPP;
1007
- goto out;
1008
- }
10091332 conn.channel = ch - 1;
1333
+
1334
+ rc = wil_get_wmi_edmg_channel(wil, sme->edmg.bw_config,
1335
+ sme->edmg.channels, &conn.edmg_channel);
1336
+ if (rc < 0)
1337
+ return rc;
10101338
10111339 ether_addr_copy(conn.bssid, bss->bssid);
10121340 ether_addr_copy(conn.dst_mac, bss->bssid);
....@@ -1206,9 +1534,9 @@
12061534 return &wil->sta[cid];
12071535 }
12081536
1209
-static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
1210
- struct wil_sta_info *cs,
1211
- struct key_params *params)
1537
+void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
1538
+ struct wil_sta_info *cs,
1539
+ struct key_params *params)
12121540 {
12131541 struct wil_tid_crypto_rx_single *cc;
12141542 int tid;
....@@ -1217,6 +1545,7 @@
12171545 return;
12181546
12191547 switch (key_usage) {
1548
+ case WMI_KEY_USE_STORE_PTK:
12201549 case WMI_KEY_USE_PAIRWISE:
12211550 for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
12221551 cc = &cs->tid_crypto_rx[tid].key_id[key_index];
....@@ -1291,13 +1620,19 @@
12911620 params->seq_len, params->seq);
12921621
12931622 if (IS_ERR(cs)) {
1294
- wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
1295
- mac_addr, key_usage_str[key_usage], key_index,
1296
- params->seq_len, params->seq);
1297
- return -EINVAL;
1623
+ /* in FT, sta info may not be available as add_key may be
1624
+ * sent by host before FW sends WMI_CONNECT_EVENT
1625
+ */
1626
+ if (!test_bit(wil_vif_ft_roam, vif->status)) {
1627
+ wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
1628
+ mac_addr, key_usage_str[key_usage], key_index,
1629
+ params->seq_len, params->seq);
1630
+ return -EINVAL;
1631
+ }
12981632 }
12991633
1300
- wil_del_rx_key(key_index, key_usage, cs);
1634
+ if (!IS_ERR(cs))
1635
+ wil_del_rx_key(key_index, key_usage, cs);
13011636
13021637 if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
13031638 wil_err(wil,
....@@ -1308,10 +1643,31 @@
13081643 return -EINVAL;
13091644 }
13101645
1646
+ spin_lock_bh(&wil->eap_lock);
1647
+ if (pairwise && wdev->iftype == NL80211_IFTYPE_STATION &&
1648
+ (vif->ptk_rekey_state == WIL_REKEY_M3_RECEIVED ||
1649
+ vif->ptk_rekey_state == WIL_REKEY_WAIT_M4_SENT)) {
1650
+ key_usage = WMI_KEY_USE_STORE_PTK;
1651
+ vif->ptk_rekey_state = WIL_REKEY_WAIT_M4_SENT;
1652
+ wil_dbg_misc(wil, "Store EAPOL key\n");
1653
+ }
1654
+ spin_unlock_bh(&wil->eap_lock);
1655
+
13111656 rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len,
13121657 params->key, key_usage);
1313
- if (!rc)
1658
+ if (!rc && !IS_ERR(cs)) {
1659
+ /* update local storage used for AP recovery */
1660
+ if (key_usage == WMI_KEY_USE_TX_GROUP && params->key &&
1661
+ params->key_len <= WMI_MAX_KEY_LEN) {
1662
+ vif->gtk_index = key_index;
1663
+ memcpy(vif->gtk, params->key, params->key_len);
1664
+ vif->gtk_len = params->key_len;
1665
+ }
1666
+ /* in FT set crypto will take place upon receiving
1667
+ * WMI_RING_EN_EVENTID event
1668
+ */
13141669 wil_set_crypto_rx(key_index, key_usage, cs, params);
1670
+ }
13151671
13161672 return rc;
13171673 }
....@@ -1383,7 +1739,7 @@
13831739 return wil_p2p_cancel_listen(vif, cookie);
13841740 }
13851741
1386
-/**
1742
+/*
13871743 * find a specific IE in a list of IEs
13881744 * return a pointer to the beginning of IE in the list
13891745 * or NULL if not found
....@@ -1410,7 +1766,7 @@
14101766 ies_len);
14111767 }
14121768
1413
-/**
1769
+/*
14141770 * merge the IEs in two lists into a single list.
14151771 * do not include IEs from the second list which exist in the first list.
14161772 * add only vendor specific IEs from second list to keep
....@@ -1481,21 +1837,44 @@
14811837 }
14821838
14831839 /* internal functions for device reset and starting AP */
1840
+static u8 *
1841
+_wil_cfg80211_get_proberesp_ies(const u8 *proberesp, u16 proberesp_len,
1842
+ u16 *ies_len)
1843
+{
1844
+ u8 *ies = NULL;
1845
+
1846
+ if (proberesp) {
1847
+ struct ieee80211_mgmt *f =
1848
+ (struct ieee80211_mgmt *)proberesp;
1849
+ size_t hlen = offsetof(struct ieee80211_mgmt,
1850
+ u.probe_resp.variable);
1851
+
1852
+ ies = f->u.probe_resp.variable;
1853
+ if (ies_len)
1854
+ *ies_len = proberesp_len - hlen;
1855
+ }
1856
+
1857
+ return ies;
1858
+}
1859
+
14841860 static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
14851861 struct cfg80211_beacon_data *bcon)
14861862 {
14871863 int rc;
14881864 u16 len = 0, proberesp_len = 0;
1489
- u8 *ies = NULL, *proberesp = NULL;
1865
+ u8 *ies = NULL, *proberesp;
14901866
1491
- if (bcon->probe_resp) {
1492
- struct ieee80211_mgmt *f =
1493
- (struct ieee80211_mgmt *)bcon->probe_resp;
1494
- size_t hlen = offsetof(struct ieee80211_mgmt,
1495
- u.probe_resp.variable);
1496
- proberesp = f->u.probe_resp.variable;
1497
- proberesp_len = bcon->probe_resp_len - hlen;
1498
- }
1867
+ /* update local storage used for AP recovery */
1868
+ wil_memdup_ie(&vif->proberesp, &vif->proberesp_len, bcon->probe_resp,
1869
+ bcon->probe_resp_len);
1870
+ wil_memdup_ie(&vif->proberesp_ies, &vif->proberesp_ies_len,
1871
+ bcon->proberesp_ies, bcon->proberesp_ies_len);
1872
+ wil_memdup_ie(&vif->assocresp_ies, &vif->assocresp_ies_len,
1873
+ bcon->assocresp_ies, bcon->assocresp_ies_len);
1874
+
1875
+ proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp,
1876
+ bcon->probe_resp_len,
1877
+ &proberesp_len);
14991878 rc = _wil_cfg80211_merge_extra_ies(proberesp,
15001879 proberesp_len,
15011880 bcon->proberesp_ies,
....@@ -1529,7 +1908,7 @@
15291908 static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
15301909 struct net_device *ndev,
15311910 const u8 *ssid, size_t ssid_len, u32 privacy,
1532
- int bi, u8 chan,
1911
+ int bi, u8 chan, u8 wmi_edmg_channel,
15331912 struct cfg80211_beacon_data *bcon,
15341913 u8 hidden_ssid, u32 pbss)
15351914 {
....@@ -1539,6 +1918,9 @@
15391918 struct wireless_dev *wdev = ndev->ieee80211_ptr;
15401919 u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
15411920 u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
1921
+ u16 proberesp_len = 0;
1922
+ u8 *proberesp;
1923
+ bool ft = false;
15421924
15431925 if (pbss)
15441926 wmi_nettype = WMI_NETTYPE_P2P;
....@@ -1550,6 +1932,25 @@
15501932 }
15511933
15521934 wil_set_recovery_state(wil, fw_recovery_idle);
1935
+
1936
+ proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp,
1937
+ bcon->probe_resp_len,
1938
+ &proberesp_len);
1939
+ /* check that the probe response IEs has a MDE */
1940
+ if ((proberesp && proberesp_len > 0 &&
1941
+ cfg80211_find_ie(WLAN_EID_MOBILITY_DOMAIN,
1942
+ proberesp,
1943
+ proberesp_len)))
1944
+ ft = true;
1945
+
1946
+ if (ft) {
1947
+ if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING,
1948
+ wil->fw_capabilities)) {
1949
+ wil_err(wil, "FW does not support FT roaming\n");
1950
+ return -ENOTSUPP;
1951
+ }
1952
+ set_bit(wil_vif_ft_roam, vif->status);
1953
+ }
15531954
15541955 mutex_lock(&wil->mutex);
15551956
....@@ -1570,14 +1971,19 @@
15701971
15711972 vif->privacy = privacy;
15721973 vif->channel = chan;
1974
+ vif->wmi_edmg_channel = wmi_edmg_channel;
15731975 vif->hidden_ssid = hidden_ssid;
15741976 vif->pbss = pbss;
1977
+ vif->bi = bi;
1978
+ memcpy(vif->ssid, ssid, ssid_len);
1979
+ vif->ssid_len = ssid_len;
15751980
15761981 netif_carrier_on(ndev);
15771982 if (!wil_has_other_active_ifaces(wil, ndev, false, true))
15781983 wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
15791984
1580
- rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go);
1985
+ rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, wmi_edmg_channel,
1986
+ hidden_ssid, is_go);
15811987 if (rc)
15821988 goto err_pcp_start;
15831989
....@@ -1598,11 +2004,65 @@
15982004 return rc;
15992005 }
16002006
2007
+void wil_cfg80211_ap_recovery(struct wil6210_priv *wil)
2008
+{
2009
+ int rc, i;
2010
+ struct wiphy *wiphy = wil_to_wiphy(wil);
2011
+
2012
+ for (i = 0; i < GET_MAX_VIFS(wil); i++) {
2013
+ struct wil6210_vif *vif = wil->vifs[i];
2014
+ struct net_device *ndev;
2015
+ struct cfg80211_beacon_data bcon = {};
2016
+ struct key_params key_params = {};
2017
+
2018
+ if (!vif || vif->ssid_len == 0)
2019
+ continue;
2020
+
2021
+ ndev = vif_to_ndev(vif);
2022
+ bcon.proberesp_ies = vif->proberesp_ies;
2023
+ bcon.assocresp_ies = vif->assocresp_ies;
2024
+ bcon.probe_resp = vif->proberesp;
2025
+ bcon.proberesp_ies_len = vif->proberesp_ies_len;
2026
+ bcon.assocresp_ies_len = vif->assocresp_ies_len;
2027
+ bcon.probe_resp_len = vif->proberesp_len;
2028
+
2029
+ wil_info(wil,
2030
+ "AP (vif %d) recovery: privacy %d, bi %d, channel %d, hidden %d, pbss %d\n",
2031
+ i, vif->privacy, vif->bi, vif->channel,
2032
+ vif->hidden_ssid, vif->pbss);
2033
+ wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
2034
+ vif->ssid, vif->ssid_len, true);
2035
+ rc = _wil_cfg80211_start_ap(wiphy, ndev,
2036
+ vif->ssid, vif->ssid_len,
2037
+ vif->privacy, vif->bi,
2038
+ vif->channel,
2039
+ vif->wmi_edmg_channel, &bcon,
2040
+ vif->hidden_ssid, vif->pbss);
2041
+ if (rc) {
2042
+ wil_err(wil, "vif %d recovery failed (%d)\n", i, rc);
2043
+ continue;
2044
+ }
2045
+
2046
+ if (!vif->privacy || vif->gtk_len == 0)
2047
+ continue;
2048
+
2049
+ key_params.key = vif->gtk;
2050
+ key_params.key_len = vif->gtk_len;
2051
+ key_params.seq_len = IEEE80211_GCMP_PN_LEN;
2052
+ rc = wil_cfg80211_add_key(wiphy, ndev, vif->gtk_index, false,
2053
+ NULL, &key_params);
2054
+ if (rc)
2055
+ wil_err(wil, "vif %d recovery add key failed (%d)\n",
2056
+ i, rc);
2057
+ }
2058
+}
2059
+
16012060 static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
16022061 struct net_device *ndev,
16032062 struct cfg80211_beacon_data *bcon)
16042063 {
16052064 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2065
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
16062066 struct wil6210_vif *vif = ndev_to_vif(ndev);
16072067 int rc;
16082068 u32 privacy = 0;
....@@ -1615,17 +2075,19 @@
16152075 bcon->tail_len))
16162076 privacy = 1;
16172077
2078
+ memcpy(vif->ssid, wdev->ssid, wdev->ssid_len);
2079
+ vif->ssid_len = wdev->ssid_len;
2080
+
16182081 /* in case privacy has changed, need to restart the AP */
16192082 if (vif->privacy != privacy) {
1620
- struct wireless_dev *wdev = ndev->ieee80211_ptr;
1621
-
16222083 wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
16232084 vif->privacy, privacy);
16242085
1625
- rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
1626
- wdev->ssid_len, privacy,
2086
+ rc = _wil_cfg80211_start_ap(wiphy, ndev, vif->ssid,
2087
+ vif->ssid_len, privacy,
16272088 wdev->beacon_interval,
1628
- vif->channel, bcon,
2089
+ vif->channel,
2090
+ vif->wmi_edmg_channel, bcon,
16292091 vif->hidden_ssid,
16302092 vif->pbss);
16312093 } else {
....@@ -1644,9 +2106,16 @@
16442106 struct ieee80211_channel *channel = info->chandef.chan;
16452107 struct cfg80211_beacon_data *bcon = &info->beacon;
16462108 struct cfg80211_crypto_settings *crypto = &info->crypto;
2109
+ u8 wmi_edmg_channel;
16472110 u8 hidden_ssid;
16482111
16492112 wil_dbg_misc(wil, "start_ap\n");
2113
+
2114
+ rc = wil_get_wmi_edmg_channel(wil, info->chandef.edmg.bw_config,
2115
+ info->chandef.edmg.channels,
2116
+ &wmi_edmg_channel);
2117
+ if (rc < 0)
2118
+ return rc;
16502119
16512120 if (!channel) {
16522121 wil_err(wil, "AP: No channel???\n");
....@@ -1687,7 +2156,8 @@
16872156 rc = _wil_cfg80211_start_ap(wiphy, ndev,
16882157 info->ssid, info->ssid_len, info->privacy,
16892158 info->beacon_interval, channel->hw_value,
1690
- bcon, hidden_ssid, info->pbss);
2159
+ wmi_edmg_channel, bcon, hidden_ssid,
2160
+ info->pbss);
16912161
16922162 return rc;
16932163 }
....@@ -1712,6 +2182,13 @@
17122182 mutex_lock(&wil->mutex);
17132183
17142184 wmi_pcp_stop(vif);
2185
+ clear_bit(wil_vif_ft_roam, vif->status);
2186
+ vif->ssid_len = 0;
2187
+ wil_memdup_ie(&vif->proberesp, &vif->proberesp_len, NULL, 0);
2188
+ wil_memdup_ie(&vif->proberesp_ies, &vif->proberesp_ies_len, NULL, 0);
2189
+ wil_memdup_ie(&vif->assocresp_ies, &vif->assocresp_ies_len, NULL, 0);
2190
+ memset(vif->gtk, 0, WMI_MAX_KEY_LEN);
2191
+ vif->gtk_len = 0;
17152192
17162193 if (last)
17172194 __wil_down(wil);
....@@ -1731,8 +2208,9 @@
17312208 struct wil6210_vif *vif = ndev_to_vif(dev);
17322209 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
17332210
1734
- wil_dbg_misc(wil, "add station %pM aid %d mid %d\n",
1735
- mac, params->aid, vif->mid);
2211
+ wil_dbg_misc(wil, "add station %pM aid %d mid %d mask 0x%x set 0x%x\n",
2212
+ mac, params->aid, vif->mid,
2213
+ params->sta_flags_mask, params->sta_flags_set);
17362214
17372215 if (!disable_ap_sme) {
17382216 wil_err(wil, "not supported with AP SME enabled\n");
....@@ -1758,7 +2236,7 @@
17582236 params->mac, params->reason_code, vif->mid);
17592237
17602238 mutex_lock(&wil->mutex);
1761
- wil6210_disconnect(vif, params->mac, params->reason_code, false);
2239
+ wil6210_disconnect(vif, params->mac, params->reason_code);
17622240 mutex_unlock(&wil->mutex);
17632241
17642242 return 0;
....@@ -2053,6 +2531,86 @@
20532531 return 0;
20542532 }
20552533
2534
+static int
2535
+wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
2536
+ struct cfg80211_update_ft_ies_params *ftie)
2537
+{
2538
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2539
+ struct wil6210_vif *vif = ndev_to_vif(dev);
2540
+ struct cfg80211_bss *bss;
2541
+ struct wmi_ft_reassoc_cmd reassoc;
2542
+ int rc = 0;
2543
+
2544
+ wil_dbg_misc(wil, "update ft ies, mid=%d\n", vif->mid);
2545
+ wil_hex_dump_misc("FT IE ", DUMP_PREFIX_OFFSET, 16, 1,
2546
+ ftie->ie, ftie->ie_len, true);
2547
+
2548
+ if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) {
2549
+ wil_err(wil, "FW does not support FT roaming\n");
2550
+ return -EOPNOTSUPP;
2551
+ }
2552
+
2553
+ rc = wmi_update_ft_ies(vif, ftie->ie_len, ftie->ie);
2554
+ if (rc)
2555
+ return rc;
2556
+
2557
+ if (!test_bit(wil_vif_ft_roam, vif->status))
2558
+ /* vif is not roaming */
2559
+ return 0;
2560
+
2561
+ /* wil_vif_ft_roam is set. wil_cfg80211_update_ft_ies is used as
2562
+ * a trigger for reassoc
2563
+ */
2564
+
2565
+ bss = vif->bss;
2566
+ if (!bss) {
2567
+ wil_err(wil, "FT: bss is NULL\n");
2568
+ return -EINVAL;
2569
+ }
2570
+
2571
+ memset(&reassoc, 0, sizeof(reassoc));
2572
+ ether_addr_copy(reassoc.bssid, bss->bssid);
2573
+
2574
+ rc = wmi_send(wil, WMI_FT_REASSOC_CMDID, vif->mid,
2575
+ &reassoc, sizeof(reassoc));
2576
+ if (rc)
2577
+ wil_err(wil, "FT: reassoc failed (%d)\n", rc);
2578
+
2579
+ return rc;
2580
+}
2581
+
2582
+static int wil_cfg80211_set_multicast_to_unicast(struct wiphy *wiphy,
2583
+ struct net_device *dev,
2584
+ const bool enabled)
2585
+{
2586
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2587
+
2588
+ if (wil->multicast_to_unicast == enabled)
2589
+ return 0;
2590
+
2591
+ wil_info(wil, "set multicast to unicast, enabled=%d\n", enabled);
2592
+ wil->multicast_to_unicast = enabled;
2593
+
2594
+ return 0;
2595
+}
2596
+
2597
+static int wil_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
2598
+ struct net_device *dev,
2599
+ s32 rssi_thold, u32 rssi_hyst)
2600
+{
2601
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2602
+ int rc;
2603
+
2604
+ wil->cqm_rssi_thold = rssi_thold;
2605
+
2606
+ rc = wmi_set_cqm_rssi_config(wil, rssi_thold, rssi_hyst);
2607
+ if (rc)
2608
+ /* reset stored value upon failure */
2609
+ wil->cqm_rssi_thold = 0;
2610
+
2611
+ return rc;
2612
+}
2613
+
20562614 static const struct cfg80211_ops wil_cfg80211_ops = {
20572615 .add_virtual_intf = wil_cfg80211_add_iface,
20582616 .del_virtual_intf = wil_cfg80211_del_iface,
....@@ -2084,10 +2642,13 @@
20842642 .start_p2p_device = wil_cfg80211_start_p2p_device,
20852643 .stop_p2p_device = wil_cfg80211_stop_p2p_device,
20862644 .set_power_mgmt = wil_cfg80211_set_power_mgmt,
2645
+ .set_cqm_rssi_config = wil_cfg80211_set_cqm_rssi_config,
20872646 .suspend = wil_cfg80211_suspend,
20882647 .resume = wil_cfg80211_resume,
20892648 .sched_scan_start = wil_cfg80211_sched_scan_start,
20902649 .sched_scan_stop = wil_cfg80211_sched_scan_stop,
2650
+ .update_ft_ies = wil_cfg80211_update_ft_ies,
2651
+ .set_multicast_to_unicast = wil_cfg80211_set_multicast_to_unicast,
20912652 };
20922653
20932654 static void wil_wiphy_init(struct wiphy *wiphy)
....@@ -2306,8 +2867,8 @@
23062867 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
23072868 return -EOPNOTSUPP;
23082869
2309
- rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2310
- wil_rf_sector_policy, NULL);
2870
+ rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data,
2871
+ data_len, wil_rf_sector_policy, NULL);
23112872 if (rc) {
23122873 wil_err(wil, "Invalid rf sector ATTR\n");
23132874 return rc;
....@@ -2365,13 +2926,13 @@
23652926 QCA_ATTR_PAD))
23662927 goto nla_put_failure;
23672928
2368
- nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
2929
+ nl_cfgs = nla_nest_start_noflag(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
23692930 if (!nl_cfgs)
23702931 goto nla_put_failure;
23712932 for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) {
23722933 if (!(rf_modules_vec & BIT(i)))
23732934 continue;
2374
- nl_cfg = nla_nest_start(msg, i);
2935
+ nl_cfg = nla_nest_start_noflag(msg, i);
23752936 if (!nl_cfg)
23762937 goto nla_put_failure;
23772938 si = &reply.evt.sectors_info[i];
....@@ -2426,8 +2987,8 @@
24262987 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
24272988 return -EOPNOTSUPP;
24282989
2429
- rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2430
- wil_rf_sector_policy, NULL);
2990
+ rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data,
2991
+ data_len, wil_rf_sector_policy, NULL);
24312992 if (rc) {
24322993 wil_err(wil, "Invalid rf sector ATTR\n");
24332994 return rc;
....@@ -2459,9 +3020,11 @@
24593020 cmd.sector_type = sector_type;
24603021 nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG],
24613022 tmp) {
2462
- rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
2463
- nl_cfg, wil_rf_sector_cfg_policy,
2464
- NULL);
3023
+ rc = nla_parse_nested_deprecated(tb2,
3024
+ QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
3025
+ nl_cfg,
3026
+ wil_rf_sector_cfg_policy,
3027
+ NULL);
24653028 if (rc) {
24663029 wil_err(wil, "invalid sector cfg\n");
24673030 return -EINVAL;
....@@ -2533,8 +3096,8 @@
25333096 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
25343097 return -EOPNOTSUPP;
25353098
2536
- rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2537
- wil_rf_sector_policy, NULL);
3099
+ rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data,
3100
+ data_len, wil_rf_sector_policy, NULL);
25383101 if (rc) {
25393102 wil_err(wil, "Invalid rf sector ATTR\n");
25403103 return rc;
....@@ -2641,8 +3204,8 @@
26413204 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
26423205 return -EOPNOTSUPP;
26433206
2644
- rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2645
- wil_rf_sector_policy, NULL);
3207
+ rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data,
3208
+ data_len, wil_rf_sector_policy, NULL);
26463209 if (rc) {
26473210 wil_err(wil, "Invalid rf sector ATTR\n");
26483211 return rc;
....@@ -2701,7 +3264,7 @@
27013264 wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,
27023265 sector_type, WIL_CID_ALL);
27033266 if (rc == -EINVAL) {
2704
- for (i = 0; i < WIL6210_MAX_CID; i++) {
3267
+ for (i = 0; i < wil->max_assoc_sta; i++) {
27053268 if (wil->sta[i].mid != vif->mid)
27063269 continue;
27073270 rc = wil_rf_sector_wmi_set_selected(