hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/wireless/ath/wil6210/wmi.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/moduleparam.h>
....@@ -24,8 +13,9 @@
2413 #include "wmi.h"
2514 #include "trace.h"
2615
27
-static uint max_assoc_sta = WIL6210_MAX_CID;
28
-module_param(max_assoc_sta, uint, 0644);
16
+/* set the default max assoc sta to max supported by driver */
17
+uint max_assoc_sta = WIL6210_MAX_CID;
18
+module_param(max_assoc_sta, uint, 0444);
2919 MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
3020
3121 int agg_wsize; /* = 0; */
....@@ -39,10 +29,10 @@
3929 " 60G device led enablement. Set the led ID (0-2) to enable");
4030
4131 #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
42
-#define WIL_WMI_CALL_GENERAL_TO_MS 100
32
+#define WIL_WMI_PCP_STOP_TO_MS 5000
4333
4434 /**
45
- * WMI event receiving - theory of operations
35
+ * DOC: WMI event receiving - theory of operations
4636 *
4737 * When firmware about to report WMI event, it fills memory area
4838 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
....@@ -59,7 +49,7 @@
5949 */
6050
6151 /**
62
- * Addressing - theory of operations
52
+ * DOC: Addressing - theory of operations
6353 *
6454 * There are several buses present on the WIL6210 card.
6555 * Same memory areas are visible at different address on
....@@ -76,8 +66,7 @@
7666 * AHB address must be used.
7767 */
7868
79
-/**
80
- * @sparrow_fw_mapping provides memory remapping table for sparrow
69
+/* sparrow_fw_mapping provides memory remapping table for sparrow
8170 *
8271 * array size should be in sync with the declaration in the wil6210.h
8372 *
....@@ -113,16 +102,14 @@
113102 {0x800000, 0x804000, 0x940000, "uc_data", false, false},
114103 };
115104
116
-/**
117
- * @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
105
+/* sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
118106 * it is a bit larger to support extra features
119107 */
120108 const struct fw_map sparrow_d0_mac_rgf_ext = {
121109 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
122110 };
123111
124
-/**
125
- * @talyn_fw_mapping provides memory remapping table for Talyn
112
+/* talyn_fw_mapping provides memory remapping table for Talyn
126113 *
127114 * array size should be in sync with the declaration in the wil6210.h
128115 *
....@@ -164,8 +151,7 @@
164151 {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
165152 };
166153
167
-/**
168
- * @talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
154
+/* talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
169155 *
170156 * array size should be in sync with the declaration in the wil6210.h
171157 *
....@@ -206,8 +192,8 @@
206192 {0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
207193 /* DMA OFU 296b */
208194 {0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
209
- /* ucode debug 4k */
210
- {0x8c3000, 0x8c4000, 0x8c3000, "ucode_debug", true, true},
195
+ /* ucode debug 256b */
196
+ {0x8c3000, 0x8c3100, 0x8c3000, "ucode_debug", true, true},
211197 /* upper area 1536k */
212198 {0x900000, 0xa80000, 0x900000, "upper", true, true},
213199 /* UCODE areas - accessible by debugfs blobs but not by
....@@ -227,11 +213,19 @@
227213 {WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
228214 };
229215
216
+struct auth_no_hdr {
217
+ __le16 auth_alg;
218
+ __le16 auth_transaction;
219
+ __le16 status_code;
220
+ /* possibly followed by Challenge text */
221
+ u8 variable[];
222
+} __packed;
223
+
230224 u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
231225
232226 /**
233227 * return AHB address for given firmware internal (linker) address
234
- * @x - internal address
228
+ * @x: internal address
235229 * If address have no valid AHB mapping, return 0
236230 */
237231 static u32 wmi_addr_remap(u32 x)
....@@ -249,7 +243,7 @@
249243
250244 /**
251245 * find fw_mapping entry by section name
252
- * @section - section name
246
+ * @section: section name
253247 *
254248 * Return pointer to section or NULL if not found
255249 */
....@@ -267,8 +261,9 @@
267261
268262 /**
269263 * Check address validity for WMI buffer; remap if needed
270
- * @ptr - internal (linker) fw/ucode address
271
- * @size - if non zero, validate the block does not
264
+ * @wil: driver data
265
+ * @ptr: internal (linker) fw/ucode address
266
+ * @size: if non zero, validate the block does not
272267 * exceed the device memory (bar)
273268 *
274269 * Valid buffer should be DWORD aligned
....@@ -302,9 +297,7 @@
302297 return wmi_buffer_block(wil, ptr_, 0);
303298 }
304299
305
-/**
306
- * Check address validity
307
- */
300
+/* Check address validity */
308301 void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
309302 {
310303 u32 off;
....@@ -468,6 +461,18 @@
468461 return "WMI_LINK_STATS_CMD";
469462 case WMI_SW_TX_REQ_EXT_CMDID:
470463 return "WMI_SW_TX_REQ_EXT_CMDID";
464
+ case WMI_FT_AUTH_CMDID:
465
+ return "WMI_FT_AUTH_CMD";
466
+ case WMI_FT_REASSOC_CMDID:
467
+ return "WMI_FT_REASSOC_CMD";
468
+ case WMI_UPDATE_FT_IES_CMDID:
469
+ return "WMI_UPDATE_FT_IES_CMD";
470
+ case WMI_RBUFCAP_CFG_CMDID:
471
+ return "WMI_RBUFCAP_CFG_CMD";
472
+ case WMI_TEMP_SENSE_ALL_CMDID:
473
+ return "WMI_TEMP_SENSE_ALL_CMDID";
474
+ case WMI_SET_LINK_MONITOR_CMDID:
475
+ return "WMI_SET_LINK_MONITOR_CMD";
471476 default:
472477 return "Untracked CMD";
473478 }
....@@ -606,6 +611,20 @@
606611 return "WMI_LINK_STATS_CONFIG_DONE_EVENT";
607612 case WMI_LINK_STATS_EVENTID:
608613 return "WMI_LINK_STATS_EVENT";
614
+ case WMI_COMMAND_NOT_SUPPORTED_EVENTID:
615
+ return "WMI_COMMAND_NOT_SUPPORTED_EVENT";
616
+ case WMI_FT_AUTH_STATUS_EVENTID:
617
+ return "WMI_FT_AUTH_STATUS_EVENT";
618
+ case WMI_FT_REASSOC_STATUS_EVENTID:
619
+ return "WMI_FT_REASSOC_STATUS_EVENT";
620
+ case WMI_RBUFCAP_CFG_EVENTID:
621
+ return "WMI_RBUFCAP_CFG_EVENT";
622
+ case WMI_TEMP_SENSE_ALL_DONE_EVENTID:
623
+ return "WMI_TEMP_SENSE_ALL_DONE_EVENTID";
624
+ case WMI_SET_LINK_MONITOR_EVENTID:
625
+ return "WMI_SET_LINK_MONITOR_EVENT";
626
+ case WMI_LINK_MONITOR_EVENTID:
627
+ return "WMI_LINK_MONITOR_EVENT";
609628 default:
610629 return "Untracked EVENT";
611630 }
....@@ -750,6 +769,7 @@
750769 struct wil6210_priv *wil = vif_to_wil(vif);
751770 struct wiphy *wiphy = wil_to_wiphy(wil);
752771 struct wmi_ready_event *evt = d;
772
+ u8 fw_max_assoc_sta;
753773
754774 wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
755775 wil->fw_version, le32_to_cpu(evt->sw_version),
....@@ -767,6 +787,25 @@
767787 evt->rfc_read_calib_result);
768788 wil->fw_calib_result = evt->rfc_read_calib_result;
769789 }
790
+
791
+ fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID;
792
+ if (len > offsetof(struct wmi_ready_event, max_assoc_sta) &&
793
+ evt->max_assoc_sta > 0) {
794
+ fw_max_assoc_sta = evt->max_assoc_sta;
795
+ wil_dbg_wmi(wil, "fw reported max assoc sta %d\n",
796
+ fw_max_assoc_sta);
797
+
798
+ if (fw_max_assoc_sta > WIL6210_MAX_CID) {
799
+ wil_dbg_wmi(wil,
800
+ "fw max assoc sta %d exceeds max driver supported %d\n",
801
+ fw_max_assoc_sta, WIL6210_MAX_CID);
802
+ fw_max_assoc_sta = WIL6210_MAX_CID;
803
+ }
804
+ }
805
+
806
+ wil->max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta);
807
+ wil_dbg_wmi(wil, "setting max assoc sta to %d\n", wil->max_assoc_sta);
808
+
770809 wil_set_recovery_state(wil, fw_recovery_idle);
771810 set_bit(wil_status_fwready, wil->status);
772811 /* let the reset sequence continue */
....@@ -829,6 +868,12 @@
829868
830869 if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
831870 struct cfg80211_bss *bss;
871
+ struct cfg80211_inform_bss bss_data = {
872
+ .chan = channel,
873
+ .scan_width = NL80211_BSS_CHAN_WIDTH_20,
874
+ .signal = signal,
875
+ .boottime_ns = ktime_to_ns(ktime_get_boottime()),
876
+ };
832877 u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
833878 u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
834879 u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
....@@ -843,8 +888,9 @@
843888
844889 wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
845890
846
- bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
847
- d_len, signal, GFP_KERNEL);
891
+ bss = cfg80211_inform_bss_frame_data(wiphy, &bss_data,
892
+ rx_mgmt_frame,
893
+ d_len, GFP_KERNEL);
848894 if (bss) {
849895 wil_dbg_wmi(wil, "Added BSS %pM\n",
850896 rx_mgmt_frame->bssid);
....@@ -932,7 +978,7 @@
932978 evt->assoc_req_len, evt->assoc_resp_len);
933979 return;
934980 }
935
- if (evt->cid >= WIL6210_MAX_CID) {
981
+ if (evt->cid >= wil->max_assoc_sta) {
936982 wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
937983 return;
938984 }
....@@ -998,7 +1044,7 @@
9981044 wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
9991045 evt->cid, rc);
10001046 wmi_disconnect_sta(vif, wil->sta[evt->cid].addr,
1001
- WLAN_REASON_UNSPECIFIED, false, false);
1047
+ WLAN_REASON_UNSPECIFIED, false);
10021048 } else {
10031049 wil_info(wil, "successful connection to CID %d\n", evt->cid);
10041050 }
....@@ -1092,7 +1138,24 @@
10921138 }
10931139
10941140 mutex_lock(&wil->mutex);
1095
- wil6210_disconnect(vif, evt->bssid, reason_code, true);
1141
+ wil6210_disconnect_complete(vif, evt->bssid, reason_code);
1142
+ if (disable_ap_sme) {
1143
+ struct wireless_dev *wdev = vif_to_wdev(vif);
1144
+ struct net_device *ndev = vif_to_ndev(vif);
1145
+
1146
+ /* disconnect event in disable_ap_sme mode means link loss */
1147
+ switch (wdev->iftype) {
1148
+ /* AP-like interface */
1149
+ case NL80211_IFTYPE_AP:
1150
+ case NL80211_IFTYPE_P2P_GO:
1151
+ /* notify hostapd about link loss */
1152
+ cfg80211_cqm_pktloss_notify(ndev, evt->bssid, 0,
1153
+ GFP_KERNEL);
1154
+ break;
1155
+ default:
1156
+ break;
1157
+ }
1158
+ }
10961159 mutex_unlock(&wil->mutex);
10971160 }
10981161
....@@ -1156,6 +1219,9 @@
11561219 struct wmi_ring_en_event *evt = d;
11571220 u8 vri = evt->ring_index;
11581221 struct wireless_dev *wdev = vif_to_wdev(vif);
1222
+ struct wil_sta_info *sta;
1223
+ u8 cid;
1224
+ struct key_params params;
11591225
11601226 wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
11611227
....@@ -1164,13 +1230,33 @@
11641230 return;
11651231 }
11661232
1167
- if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme)
1168
- /* in AP mode with disable_ap_sme, this is done by
1169
- * wil_cfg80211_change_station()
1233
+ if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme ||
1234
+ test_bit(wil_vif_ft_roam, vif->status))
1235
+ /* in AP mode with disable_ap_sme that is not FT,
1236
+ * this is done by wil_cfg80211_change_station()
11701237 */
11711238 wil->ring_tx_data[vri].dot1x_open = true;
11721239 if (vri == vif->bcast_ring) /* no BA for bcast */
11731240 return;
1241
+
1242
+ cid = wil->ring2cid_tid[vri][0];
1243
+ if (!wil_cid_valid(wil, cid)) {
1244
+ wil_err(wil, "invalid cid %d for vring %d\n", cid, vri);
1245
+ return;
1246
+ }
1247
+
1248
+ /* In FT mode we get key but not store it as it is received
1249
+ * before WMI_CONNECT_EVENT received from FW.
1250
+ * wil_set_crypto_rx is called here to reset the security PN
1251
+ */
1252
+ sta = &wil->sta[cid];
1253
+ if (test_bit(wil_vif_ft_roam, vif->status)) {
1254
+ memset(&params, 0, sizeof(params));
1255
+ wil_set_crypto_rx(0, WMI_KEY_USE_PAIRWISE, sta, &params);
1256
+ if (wdev->iftype != NL80211_IFTYPE_AP)
1257
+ clear_bit(wil_vif_ft_roam, vif->status);
1258
+ }
1259
+
11741260 if (agg_wsize >= 0)
11751261 wil_addba_tx_request(wil, vri, agg_wsize);
11761262 }
....@@ -1211,9 +1297,16 @@
12111297 void *d, int len)
12121298 {
12131299 struct wil6210_priv *wil = vif_to_wil(vif);
1300
+ u8 cid, tid;
12141301 struct wmi_rcp_addba_req_event *evt = d;
12151302
1216
- wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token,
1303
+ if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
1304
+ parse_cidxtid(evt->cidxtid, &cid, &tid);
1305
+ } else {
1306
+ cid = evt->cid;
1307
+ tid = evt->tid;
1308
+ }
1309
+ wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token,
12171310 evt->ba_param_set, evt->ba_timeout,
12181311 evt->ba_seq_ctrl);
12191312 }
....@@ -1229,7 +1322,19 @@
12291322 struct wil_tid_ampdu_rx *r;
12301323
12311324 might_sleep();
1232
- parse_cidxtid(evt->cidxtid, &cid, &tid);
1325
+
1326
+ if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
1327
+ parse_cidxtid(evt->cidxtid, &cid, &tid);
1328
+ } else {
1329
+ cid = evt->cid;
1330
+ tid = evt->tid;
1331
+ }
1332
+
1333
+ if (!wil_cid_valid(wil, cid)) {
1334
+ wil_err(wil, "DELBA: Invalid CID %d\n", cid);
1335
+ return;
1336
+ }
1337
+
12331338 wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n",
12341339 vif->mid, cid, tid,
12351340 evt->from_initiator ? "originator" : "recipient",
....@@ -1283,6 +1388,10 @@
12831388 __le16 fc;
12841389 u32 d_len;
12851390 struct cfg80211_bss *bss;
1391
+ struct cfg80211_inform_bss bss_data = {
1392
+ .scan_width = NL80211_BSS_CHAN_WIDTH_20,
1393
+ .boottime_ns = ktime_to_ns(ktime_get_boottime()),
1394
+ };
12861395
12871396 if (flen < 0) {
12881397 wil_err(wil, "sched scan result event too short, len %d\n",
....@@ -1325,8 +1434,10 @@
13251434 return;
13261435 }
13271436
1328
- bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
1329
- d_len, signal, GFP_KERNEL);
1437
+ bss_data.signal = signal;
1438
+ bss_data.chan = channel;
1439
+ bss = cfg80211_inform_bss_frame_data(wiphy, &bss_data, rx_mgmt_frame,
1440
+ d_len, GFP_KERNEL);
13301441 if (bss) {
13311442 wil_dbg_wmi(wil, "Added BSS %pM\n", rx_mgmt_frame->bssid);
13321443 cfg80211_put_bss(wiphy, bss);
....@@ -1344,7 +1455,7 @@
13441455 u8 cid = basic->cid;
13451456 struct wil_sta_info *sta;
13461457
1347
- if (cid < 0 || cid >= WIL6210_MAX_CID) {
1458
+ if (cid < 0 || cid >= wil->max_assoc_sta) {
13481459 wil_err(wil, "invalid cid %d\n", cid);
13491460 return;
13501461 }
....@@ -1397,14 +1508,14 @@
13971508 if (vif->fw_stats_ready) {
13981509 /* clean old statistics */
13991510 vif->fw_stats_tsf = 0;
1400
- vif->fw_stats_ready = 0;
1511
+ vif->fw_stats_ready = false;
14011512 }
14021513
14031514 wil_link_stats_store_basic(vif, payload + hdr_size);
14041515
14051516 if (!has_next) {
14061517 vif->fw_stats_tsf = tsf;
1407
- vif->fw_stats_ready = 1;
1518
+ vif->fw_stats_ready = true;
14081519 }
14091520
14101521 break;
....@@ -1419,14 +1530,14 @@
14191530 if (wil->fw_stats_global.ready) {
14201531 /* clean old statistics */
14211532 wil->fw_stats_global.tsf = 0;
1422
- wil->fw_stats_global.ready = 0;
1533
+ wil->fw_stats_global.ready = false;
14231534 }
14241535
14251536 wil_link_stats_store_global(vif, payload + hdr_size);
14261537
14271538 if (!has_next) {
14281539 wil->fw_stats_global.tsf = tsf;
1429
- wil->fw_stats_global.ready = 1;
1540
+ wil->fw_stats_global.ready = true;
14301541 }
14311542
14321543 break;
....@@ -1461,8 +1572,297 @@
14611572 evt->payload, payload_size);
14621573 }
14631574
1464
-/**
1465
- * Some events are ignored for purpose; and need not be interpreted as
1575
+/* find cid and ringid for the station vif
1576
+ *
1577
+ * return error, if other interfaces are used or ring was not found
1578
+ */
1579
+static int wil_find_cid_ringid_sta(struct wil6210_priv *wil,
1580
+ struct wil6210_vif *vif,
1581
+ int *cid,
1582
+ int *ringid)
1583
+{
1584
+ struct wil_ring *ring;
1585
+ struct wil_ring_tx_data *txdata;
1586
+ int min_ring_id = wil_get_min_tx_ring_id(wil);
1587
+ int i;
1588
+ u8 lcid;
1589
+
1590
+ if (!(vif->wdev.iftype == NL80211_IFTYPE_STATION ||
1591
+ vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) {
1592
+ wil_err(wil, "invalid interface type %d\n", vif->wdev.iftype);
1593
+ return -EINVAL;
1594
+ }
1595
+
1596
+ /* In the STA mode, it is expected to have only one ring
1597
+ * for the AP we are connected to.
1598
+ * find it and return the cid associated with it.
1599
+ */
1600
+ for (i = min_ring_id; i < WIL6210_MAX_TX_RINGS; i++) {
1601
+ ring = &wil->ring_tx[i];
1602
+ txdata = &wil->ring_tx_data[i];
1603
+ if (!ring->va || !txdata->enabled || txdata->mid != vif->mid)
1604
+ continue;
1605
+
1606
+ lcid = wil->ring2cid_tid[i][0];
1607
+ if (lcid >= wil->max_assoc_sta) /* skip BCAST */
1608
+ continue;
1609
+
1610
+ wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid);
1611
+ *cid = lcid;
1612
+ *ringid = i;
1613
+ return 0;
1614
+ }
1615
+
1616
+ wil_dbg_wmi(wil, "find sta cid while no rings active?\n");
1617
+
1618
+ return -ENOENT;
1619
+}
1620
+
1621
+static void
1622
+wmi_evt_auth_status(struct wil6210_vif *vif, int id, void *d, int len)
1623
+{
1624
+ struct wil6210_priv *wil = vif_to_wil(vif);
1625
+ struct net_device *ndev = vif_to_ndev(vif);
1626
+ struct wmi_ft_auth_status_event *data = d;
1627
+ int ie_len = len - offsetof(struct wmi_ft_auth_status_event, ie_info);
1628
+ int rc, cid = 0, ringid = 0;
1629
+ struct cfg80211_ft_event_params ft;
1630
+ u16 d_len;
1631
+ /* auth_alg(u16) + auth_transaction(u16) + status_code(u16) */
1632
+ const size_t auth_ie_offset = sizeof(u16) * 3;
1633
+ struct auth_no_hdr *auth = (struct auth_no_hdr *)data->ie_info;
1634
+
1635
+ /* check the status */
1636
+ if (ie_len >= 0 && data->status != WMI_FW_STATUS_SUCCESS) {
1637
+ wil_err(wil, "FT: auth failed. status %d\n", data->status);
1638
+ goto fail;
1639
+ }
1640
+
1641
+ if (ie_len < auth_ie_offset) {
1642
+ wil_err(wil, "FT: auth event too short, len %d\n", len);
1643
+ goto fail;
1644
+ }
1645
+
1646
+ d_len = le16_to_cpu(data->ie_len);
1647
+ if (d_len != ie_len) {
1648
+ wil_err(wil,
1649
+ "FT: auth ie length mismatch, d_len %d should be %d\n",
1650
+ d_len, ie_len);
1651
+ goto fail;
1652
+ }
1653
+
1654
+ if (!test_bit(wil_vif_ft_roam, wil->status)) {
1655
+ wil_err(wil, "FT: Not in roaming state\n");
1656
+ goto fail;
1657
+ }
1658
+
1659
+ if (le16_to_cpu(auth->auth_transaction) != 2) {
1660
+ wil_err(wil, "FT: auth error. auth_transaction %d\n",
1661
+ le16_to_cpu(auth->auth_transaction));
1662
+ goto fail;
1663
+ }
1664
+
1665
+ if (le16_to_cpu(auth->auth_alg) != WLAN_AUTH_FT) {
1666
+ wil_err(wil, "FT: auth error. auth_alg %d\n",
1667
+ le16_to_cpu(auth->auth_alg));
1668
+ goto fail;
1669
+ }
1670
+
1671
+ wil_dbg_wmi(wil, "FT: Auth to %pM successfully\n", data->mac_addr);
1672
+ wil_hex_dump_wmi("FT Auth ies : ", DUMP_PREFIX_OFFSET, 16, 1,
1673
+ data->ie_info, d_len, true);
1674
+
1675
+ /* find cid and ringid */
1676
+ rc = wil_find_cid_ringid_sta(wil, vif, &cid, &ringid);
1677
+ if (rc) {
1678
+ wil_err(wil, "No valid cid found\n");
1679
+ goto fail;
1680
+ }
1681
+
1682
+ if (vif->privacy) {
1683
+ /* For secure assoc, remove old keys */
1684
+ rc = wmi_del_cipher_key(vif, 0, wil->sta[cid].addr,
1685
+ WMI_KEY_USE_PAIRWISE);
1686
+ if (rc) {
1687
+ wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
1688
+ goto fail;
1689
+ }
1690
+ rc = wmi_del_cipher_key(vif, 0, wil->sta[cid].addr,
1691
+ WMI_KEY_USE_RX_GROUP);
1692
+ if (rc) {
1693
+ wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
1694
+ goto fail;
1695
+ }
1696
+ }
1697
+
1698
+ memset(&ft, 0, sizeof(ft));
1699
+ ft.ies = data->ie_info + auth_ie_offset;
1700
+ ft.ies_len = d_len - auth_ie_offset;
1701
+ ft.target_ap = data->mac_addr;
1702
+ cfg80211_ft_event(ndev, &ft);
1703
+
1704
+ return;
1705
+
1706
+fail:
1707
+ wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
1708
+}
1709
+
1710
+static void
1711
+wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len)
1712
+{
1713
+ struct wil6210_priv *wil = vif_to_wil(vif);
1714
+ struct net_device *ndev = vif_to_ndev(vif);
1715
+ struct wiphy *wiphy = wil_to_wiphy(wil);
1716
+ struct wmi_ft_reassoc_status_event *data = d;
1717
+ int ies_len = len - offsetof(struct wmi_ft_reassoc_status_event,
1718
+ ie_info);
1719
+ int rc = -ENOENT, cid = 0, ringid = 0;
1720
+ int ch; /* channel number (primary) */
1721
+ size_t assoc_req_ie_len = 0, assoc_resp_ie_len = 0;
1722
+ u8 *assoc_req_ie = NULL, *assoc_resp_ie = NULL;
1723
+ /* capinfo(u16) + listen_interval(u16) + current_ap mac addr + IEs */
1724
+ const size_t assoc_req_ie_offset = sizeof(u16) * 2 + ETH_ALEN;
1725
+ /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
1726
+ const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
1727
+ u16 d_len;
1728
+ int freq;
1729
+ struct cfg80211_roam_info info;
1730
+
1731
+ if (ies_len < 0) {
1732
+ wil_err(wil, "ft reassoc event too short, len %d\n", len);
1733
+ goto fail;
1734
+ }
1735
+
1736
+ wil_dbg_wmi(wil, "Reasoc Status event: status=%d, aid=%d",
1737
+ data->status, data->aid);
1738
+ wil_dbg_wmi(wil, " mac_addr=%pM, beacon_ie_len=%d",
1739
+ data->mac_addr, data->beacon_ie_len);
1740
+ wil_dbg_wmi(wil, " reassoc_req_ie_len=%d, reassoc_resp_ie_len=%d",
1741
+ le16_to_cpu(data->reassoc_req_ie_len),
1742
+ le16_to_cpu(data->reassoc_resp_ie_len));
1743
+
1744
+ d_len = le16_to_cpu(data->beacon_ie_len) +
1745
+ le16_to_cpu(data->reassoc_req_ie_len) +
1746
+ le16_to_cpu(data->reassoc_resp_ie_len);
1747
+ if (d_len != ies_len) {
1748
+ wil_err(wil,
1749
+ "ft reassoc ie length mismatch, d_len %d should be %d\n",
1750
+ d_len, ies_len);
1751
+ goto fail;
1752
+ }
1753
+
1754
+ /* check the status */
1755
+ if (data->status != WMI_FW_STATUS_SUCCESS) {
1756
+ wil_err(wil, "ft reassoc failed. status %d\n", data->status);
1757
+ goto fail;
1758
+ }
1759
+
1760
+ /* find cid and ringid */
1761
+ rc = wil_find_cid_ringid_sta(wil, vif, &cid, &ringid);
1762
+ if (rc) {
1763
+ wil_err(wil, "No valid cid found\n");
1764
+ goto fail;
1765
+ }
1766
+
1767
+ ch = data->channel + 1;
1768
+ wil_info(wil, "FT: Roam %pM channel [%d] cid %d aid %d\n",
1769
+ data->mac_addr, ch, cid, data->aid);
1770
+
1771
+ wil_hex_dump_wmi("reassoc AI : ", DUMP_PREFIX_OFFSET, 16, 1,
1772
+ data->ie_info, len - sizeof(*data), true);
1773
+
1774
+ /* figure out IE's */
1775
+ if (le16_to_cpu(data->reassoc_req_ie_len) > assoc_req_ie_offset) {
1776
+ assoc_req_ie = &data->ie_info[assoc_req_ie_offset];
1777
+ assoc_req_ie_len = le16_to_cpu(data->reassoc_req_ie_len) -
1778
+ assoc_req_ie_offset;
1779
+ }
1780
+ if (le16_to_cpu(data->reassoc_resp_ie_len) <= assoc_resp_ie_offset) {
1781
+ wil_err(wil, "FT: reassoc resp ie len is too short, len %d\n",
1782
+ le16_to_cpu(data->reassoc_resp_ie_len));
1783
+ goto fail;
1784
+ }
1785
+
1786
+ assoc_resp_ie = &data->ie_info[le16_to_cpu(data->reassoc_req_ie_len) +
1787
+ assoc_resp_ie_offset];
1788
+ assoc_resp_ie_len = le16_to_cpu(data->reassoc_resp_ie_len) -
1789
+ assoc_resp_ie_offset;
1790
+
1791
+ if (test_bit(wil_status_resetting, wil->status) ||
1792
+ !test_bit(wil_status_fwready, wil->status)) {
1793
+ wil_err(wil, "FT: status_resetting, cancel reassoc event\n");
1794
+ /* no need for cleanup, wil_reset will do that */
1795
+ return;
1796
+ }
1797
+
1798
+ mutex_lock(&wil->mutex);
1799
+
1800
+ /* ring modify to set the ring for the roamed AP settings */
1801
+ wil_dbg_wmi(wil,
1802
+ "ft modify tx config for connection CID %d ring %d\n",
1803
+ cid, ringid);
1804
+
1805
+ rc = wil->txrx_ops.tx_ring_modify(vif, ringid, cid, 0);
1806
+ if (rc) {
1807
+ wil_err(wil, "modify TX for CID %d MID %d ring %d failed (%d)\n",
1808
+ cid, vif->mid, ringid, rc);
1809
+ mutex_unlock(&wil->mutex);
1810
+ goto fail;
1811
+ }
1812
+
1813
+ /* Update the driver STA members with the new bss */
1814
+ wil->sta[cid].aid = data->aid;
1815
+ wil->sta[cid].stats.ft_roams++;
1816
+ ether_addr_copy(wil->sta[cid].addr, vif->bss->bssid);
1817
+ mutex_unlock(&wil->mutex);
1818
+ del_timer_sync(&vif->connect_timer);
1819
+
1820
+ cfg80211_ref_bss(wiphy, vif->bss);
1821
+ freq = ieee80211_channel_to_frequency(ch, NL80211_BAND_60GHZ);
1822
+
1823
+ memset(&info, 0, sizeof(info));
1824
+ info.channel = ieee80211_get_channel(wiphy, freq);
1825
+ info.bss = vif->bss;
1826
+ info.req_ie = assoc_req_ie;
1827
+ info.req_ie_len = assoc_req_ie_len;
1828
+ info.resp_ie = assoc_resp_ie;
1829
+ info.resp_ie_len = assoc_resp_ie_len;
1830
+ cfg80211_roamed(ndev, &info, GFP_KERNEL);
1831
+ vif->bss = NULL;
1832
+
1833
+ return;
1834
+
1835
+fail:
1836
+ wil6210_disconnect(vif, NULL, WLAN_REASON_PREV_AUTH_NOT_VALID);
1837
+}
1838
+
1839
+static void
1840
+wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
1841
+{
1842
+ struct wil6210_priv *wil = vif_to_wil(vif);
1843
+ struct net_device *ndev = vif_to_ndev(vif);
1844
+ struct wmi_link_monitor_event *evt = d;
1845
+ enum nl80211_cqm_rssi_threshold_event event_type;
1846
+
1847
+ if (len < sizeof(*evt)) {
1848
+ wil_err(wil, "link monitor event too short %d\n", len);
1849
+ return;
1850
+ }
1851
+
1852
+ wil_dbg_wmi(wil, "link monitor event, type %d rssi %d (stored %d)\n",
1853
+ evt->type, evt->rssi_level, wil->cqm_rssi_thold);
1854
+
1855
+ if (evt->type != WMI_LINK_MONITOR_NOTIF_RSSI_THRESHOLD_EVT)
1856
+ /* ignore */
1857
+ return;
1858
+
1859
+ event_type = (evt->rssi_level > wil->cqm_rssi_thold ?
1860
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
1861
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW);
1862
+ cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL);
1863
+}
1864
+
1865
+/* Some events are ignored for purpose; and need not be interpreted as
14661866 * "unhandled events"
14671867 */
14681868 static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
....@@ -1492,6 +1892,9 @@
14921892 {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
14931893 {WMI_SCHED_SCAN_RESULT_EVENTID, wmi_evt_sched_scan_result},
14941894 {WMI_LINK_STATS_EVENTID, wmi_evt_link_stats},
1895
+ {WMI_FT_AUTH_STATUS_EVENTID, wmi_evt_auth_status},
1896
+ {WMI_FT_REASSOC_STATUS_EVENTID, wmi_evt_reassoc_status},
1897
+ {WMI_LINK_MONITOR_EVENTID, wmi_evt_link_monitor},
14951898 };
14961899
14971900 /*
....@@ -1689,7 +2092,8 @@
16892092 };
16902093
16912094 return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd),
1692
- WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
2095
+ WMI_ECHO_RSP_EVENTID, NULL, 0,
2096
+ WIL_WMI_CALL_GENERAL_TO_MS);
16932097 }
16942098
16952099 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
....@@ -1748,7 +2152,7 @@
17482152
17492153 rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
17502154 WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
1751
- 100);
2155
+ WIL_WMI_CALL_GENERAL_TO_MS);
17522156 if (rc)
17532157 goto out;
17542158
....@@ -1762,8 +2166,39 @@
17622166 return rc;
17632167 }
17642168
1765
-int wmi_pcp_start(struct wil6210_vif *vif,
1766
- int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go)
2169
+int wmi_rbufcap_cfg(struct wil6210_priv *wil, bool enable, u16 threshold)
2170
+{
2171
+ struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2172
+ int rc;
2173
+
2174
+ struct wmi_rbufcap_cfg_cmd cmd = {
2175
+ .enable = enable,
2176
+ .rx_desc_threshold = cpu_to_le16(threshold),
2177
+ };
2178
+ struct {
2179
+ struct wmi_cmd_hdr wmi;
2180
+ struct wmi_rbufcap_cfg_event evt;
2181
+ } __packed reply = {
2182
+ .evt = {.status = WMI_FW_STATUS_FAILURE},
2183
+ };
2184
+
2185
+ rc = wmi_call(wil, WMI_RBUFCAP_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
2186
+ WMI_RBUFCAP_CFG_EVENTID, &reply, sizeof(reply),
2187
+ WIL_WMI_CALL_GENERAL_TO_MS);
2188
+ if (rc)
2189
+ return rc;
2190
+
2191
+ if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
2192
+ wil_err(wil, "RBUFCAP_CFG failed. status %d\n",
2193
+ reply.evt.status);
2194
+ rc = -EINVAL;
2195
+ }
2196
+
2197
+ return rc;
2198
+}
2199
+
2200
+int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype,
2201
+ u8 chan, u8 wmi_edmg_chan, u8 hidden_ssid, u8 is_go)
17672202 {
17682203 struct wil6210_priv *wil = vif_to_wil(vif);
17692204 int rc;
....@@ -1773,7 +2208,8 @@
17732208 .network_type = wmi_nettype,
17742209 .disable_sec_offload = 1,
17752210 .channel = chan - 1,
1776
- .pcp_max_assoc_sta = max_assoc_sta,
2211
+ .edmg_channel = wmi_edmg_chan,
2212
+ .pcp_max_assoc_sta = wil->max_assoc_sta,
17772213 .hidden_ssid = hidden_ssid,
17782214 .is_go = is_go,
17792215 .ap_sme_offload_mode = disable_ap_sme ?
....@@ -1793,10 +2229,9 @@
17932229
17942230 if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
17952231 (cmd.pcp_max_assoc_sta <= 0)) {
1796
- wil_info(wil,
1797
- "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
1798
- max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
1799
- cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
2232
+ wil_err(wil, "unexpected max_assoc_sta %d\n",
2233
+ cmd.pcp_max_assoc_sta);
2234
+ return -EOPNOTSUPP;
18002235 }
18012236
18022237 if (disable_ap_sme &&
....@@ -1835,7 +2270,8 @@
18352270 return rc;
18362271
18372272 return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0,
1838
- WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
2273
+ WMI_PCP_STOPPED_EVENTID, NULL, 0,
2274
+ WIL_WMI_PCP_STOP_TO_MS);
18392275 }
18402276
18412277 int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid)
....@@ -1866,7 +2302,8 @@
18662302 memset(&reply, 0, sizeof(reply));
18672303
18682304 rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0,
1869
- WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20);
2305
+ WMI_GET_SSID_EVENTID, &reply, sizeof(reply),
2306
+ WIL_WMI_CALL_GENERAL_TO_MS);
18702307 if (rc)
18712308 return rc;
18722309
....@@ -1903,7 +2340,8 @@
19032340 memset(&reply, 0, sizeof(reply));
19042341
19052342 rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0,
1906
- WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
2343
+ WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply),
2344
+ WIL_WMI_CALL_GENERAL_TO_MS);
19072345 if (rc)
19082346 return rc;
19092347
....@@ -1999,7 +2437,8 @@
19992437 wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
20002438
20012439 rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
2002
- WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
2440
+ WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
2441
+ WIL_WMI_CALL_GENERAL_TO_MS);
20032442
20042443 if (rc)
20052444 wil_err(wil, "Failed to stop discovery\n");
....@@ -2033,10 +2472,17 @@
20332472 .key_len = key_len,
20342473 };
20352474
2036
- if (!key || (key_len > sizeof(cmd.key)))
2475
+ if (key_len > sizeof(cmd.key))
20372476 return -EINVAL;
20382477
2039
- memcpy(cmd.key, key, key_len);
2478
+ /* key len = 0 is allowed only for usage of WMI_KEY_USE_APPLY */
2479
+ if ((key_len == 0 || !key) &&
2480
+ key_usage != WMI_KEY_USE_APPLY_PTK)
2481
+ return -EINVAL;
2482
+
2483
+ if (key)
2484
+ memcpy(cmd.key, key, key_len);
2485
+
20402486 if (mac_addr)
20412487 memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
20422488
....@@ -2074,7 +2520,8 @@
20742520 cmd->mgmt_frm_type = type;
20752521 /* BUG: FW API define ieLen as u8. Will fix FW */
20762522 cmd->ie_len = cpu_to_le16(ie_len);
2077
- memcpy(cmd->ie_info, ie, ie_len);
2523
+ if (ie_len)
2524
+ memcpy(cmd->ie_info, ie, ie_len);
20782525 rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
20792526 kfree(cmd);
20802527 out:
....@@ -2087,8 +2534,44 @@
20872534 return rc;
20882535 }
20892536
2537
+int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
2538
+{
2539
+ struct wil6210_priv *wil = vif_to_wil(vif);
2540
+ u16 len;
2541
+ struct wmi_update_ft_ies_cmd *cmd;
2542
+ int rc;
2543
+
2544
+ if (!ie)
2545
+ ie_len = 0;
2546
+
2547
+ len = sizeof(struct wmi_update_ft_ies_cmd) + ie_len;
2548
+ if (len < ie_len) {
2549
+ wil_err(wil, "wraparound. ie len %d\n", ie_len);
2550
+ return -EINVAL;
2551
+ }
2552
+
2553
+ cmd = kzalloc(len, GFP_KERNEL);
2554
+ if (!cmd) {
2555
+ rc = -ENOMEM;
2556
+ goto out;
2557
+ }
2558
+
2559
+ cmd->ie_len = cpu_to_le16(ie_len);
2560
+ if (ie_len)
2561
+ memcpy(cmd->ie_info, ie, ie_len);
2562
+ rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
2563
+ kfree(cmd);
2564
+
2565
+out:
2566
+ if (rc)
2567
+ wil_err(wil, "update ft ies failed : %d\n", rc);
2568
+
2569
+ return rc;
2570
+}
2571
+
20902572 /**
20912573 * wmi_rxon - turn radio on/off
2574
+ * @wil: driver data
20922575 * @on: turn on if true, off otherwise
20932576 *
20942577 * Only switch radio. Channel should be set separately.
....@@ -2111,12 +2594,14 @@
21112594 if (on) {
21122595 rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
21132596 WMI_LISTEN_STARTED_EVENTID,
2114
- &reply, sizeof(reply), 100);
2597
+ &reply, sizeof(reply),
2598
+ WIL_WMI_CALL_GENERAL_TO_MS);
21152599 if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
21162600 rc = -EINVAL;
21172601 } else {
21182602 rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
2119
- WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
2603
+ WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0,
2604
+ WIL_WMI_CALL_GENERAL_TO_MS);
21202605 }
21212606
21222607 return rc;
....@@ -2155,7 +2640,7 @@
21552640 if (ch)
21562641 cmd.sniffer_cfg.channel = ch->hw_value - 1;
21572642 cmd.sniffer_cfg.phy_info_mode =
2158
- cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
2643
+ cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED);
21592644 cmd.sniffer_cfg.phy_support =
21602645 cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
21612646 ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
....@@ -2205,7 +2690,8 @@
22052690 memset(&reply, 0, sizeof(reply));
22062691
22072692 rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd),
2208
- WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
2693
+ WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply),
2694
+ WIL_WMI_CALL_GENERAL_TO_MS);
22092695 if (rc)
22102696 return rc;
22112697
....@@ -2217,12 +2703,49 @@
22172703 return 0;
22182704 }
22192705
2220
-int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
2221
- u16 reason, bool full_disconnect, bool del_sta)
2706
+int wmi_get_all_temperatures(struct wil6210_priv *wil,
2707
+ struct wmi_temp_sense_all_done_event
2708
+ *sense_all_evt)
2709
+{
2710
+ struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
2711
+ int rc;
2712
+ struct wmi_temp_sense_all_cmd cmd = {
2713
+ .measure_baseband_en = true,
2714
+ .measure_rf_en = true,
2715
+ .measure_mode = TEMPERATURE_MEASURE_NOW,
2716
+ };
2717
+ struct {
2718
+ struct wmi_cmd_hdr wmi;
2719
+ struct wmi_temp_sense_all_done_event evt;
2720
+ } __packed reply;
2721
+
2722
+ if (!sense_all_evt) {
2723
+ wil_err(wil, "Invalid sense_all_evt value\n");
2724
+ return -EINVAL;
2725
+ }
2726
+
2727
+ memset(&reply, 0, sizeof(reply));
2728
+ reply.evt.status = WMI_FW_STATUS_FAILURE;
2729
+ rc = wmi_call(wil, WMI_TEMP_SENSE_ALL_CMDID, vif->mid, &cmd,
2730
+ sizeof(cmd), WMI_TEMP_SENSE_ALL_DONE_EVENTID,
2731
+ &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
2732
+ if (rc)
2733
+ return rc;
2734
+
2735
+ if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
2736
+ wil_err(wil, "Failed getting TEMP_SENSE_ALL\n");
2737
+ return -EINVAL;
2738
+ }
2739
+
2740
+ memcpy(sense_all_evt, &reply.evt, sizeof(reply.evt));
2741
+ return 0;
2742
+}
2743
+
2744
+int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
2745
+ bool del_sta)
22222746 {
22232747 struct wil6210_priv *wil = vif_to_wil(vif);
22242748 int rc;
2225
- u16 reason_code;
22262749 struct wmi_disconnect_sta_cmd disc_sta_cmd = {
22272750 .disconnect_reason = cpu_to_le16(reason),
22282751 };
....@@ -2255,21 +2778,8 @@
22552778 wil_fw_error_recovery(wil);
22562779 return rc;
22572780 }
2781
+ wil->sinfo_gen++;
22582782
2259
- if (full_disconnect) {
2260
- /* call event handler manually after processing wmi_call,
2261
- * to avoid deadlock - disconnect event handler acquires
2262
- * wil->mutex while it is already held here
2263
- */
2264
- reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
2265
-
2266
- wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
2267
- reply.evt.bssid, reason_code,
2268
- reply.evt.disconnect_reason);
2269
-
2270
- wil->sinfo_gen++;
2271
- wil6210_disconnect(vif, reply.evt.bssid, reason_code, true);
2272
- }
22732783 return 0;
22742784 }
22752785
....@@ -2304,15 +2814,22 @@
23042814 return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
23052815 }
23062816
2307
-int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason)
2817
+int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason)
23082818 {
23092819 struct wmi_rcp_delba_cmd cmd = {
2310
- .cidxtid = cidxtid,
23112820 .reason = cpu_to_le16(reason),
23122821 };
23132822
2314
- wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
2315
- (cidxtid >> 4) & 0xf, reason);
2823
+ if (cid >= WIL6210_RX_DESC_MAX_CID) {
2824
+ cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
2825
+ cmd.cid = cid;
2826
+ cmd.tid = tid;
2827
+ } else {
2828
+ cmd.cidxtid = mk_cidxtid(cid, tid);
2829
+ }
2830
+
2831
+ wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid,
2832
+ tid, reason);
23162833
23172834 return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd));
23182835 }
....@@ -2323,11 +2840,10 @@
23232840 {
23242841 int rc;
23252842 struct wmi_rcp_addba_resp_cmd cmd = {
2326
- .cidxtid = mk_cidxtid(cid, tid),
23272843 .dialog_token = token,
23282844 .status_code = cpu_to_le16(status),
23292845 /* bit 0: A-MSDU supported
2330
- * bit 1: policy (should be 0 for us)
2846
+ * bit 1: policy (controlled by FW)
23312847 * bits 2..5: TID
23322848 * bits 6..15: buffer size
23332849 */
....@@ -2342,6 +2858,14 @@
23422858 .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
23432859 };
23442860
2861
+ if (cid >= WIL6210_RX_DESC_MAX_CID) {
2862
+ cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
2863
+ cmd.cid = cid;
2864
+ cmd.tid = tid;
2865
+ } else {
2866
+ cmd.cidxtid = mk_cidxtid(cid, tid);
2867
+ }
2868
+
23452869 wil_dbg_wmi(wil,
23462870 "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
23472871 mid, cid, tid, agg_wsize,
....@@ -2349,7 +2873,7 @@
23492873
23502874 rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd),
23512875 WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
2352
- 100);
2876
+ WIL_WMI_CALL_GENERAL_TO_MS);
23532877 if (rc)
23542878 return rc;
23552879
....@@ -2373,7 +2897,7 @@
23732897 .dialog_token = token,
23742898 .status_code = cpu_to_le16(status),
23752899 /* bit 0: A-MSDU supported
2376
- * bit 1: policy (should be 0 for us)
2900
+ * bit 1: policy (controlled by FW)
23772901 * bits 2..5: TID
23782902 * bits 6..15: buffer size
23792903 */
....@@ -2431,7 +2955,7 @@
24312955 rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid,
24322956 &cmd, sizeof(cmd),
24332957 WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
2434
- 100);
2958
+ WIL_WMI_CALL_GENERAL_TO_MS);
24352959 if (rc)
24362960 return rc;
24372961
....@@ -2468,7 +2992,7 @@
24682992 rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid,
24692993 &cmd, sizeof(cmd),
24702994 WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
2471
- 100);
2995
+ WIL_WMI_CALL_GENERAL_TO_MS);
24722996 if (rc)
24732997 return rc;
24742998
....@@ -2498,7 +3022,7 @@
24983022 memset(&reply, 0, sizeof(reply));
24993023 rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0,
25003024 WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
2501
- 100);
3025
+ WIL_WMI_CALL_GENERAL_TO_MS);
25023026 if (rc)
25033027 return rc;
25043028
....@@ -2563,6 +3087,10 @@
25633087 switch (status) {
25643088 case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE:
25653089 return "LINK_NOT_IDLE";
3090
+ case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT:
3091
+ return "DISCONNECT";
3092
+ case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER:
3093
+ return "OTHER";
25663094 default:
25673095 return "Untracked status";
25683096 }
....@@ -2652,6 +3180,9 @@
26523180
26533181 if (triggers & WMI_RESUME_TRIGGER_WMI_EVT)
26543182 strlcat(string, " WMI_EVT", str_size);
3183
+
3184
+ if (triggers & WMI_RESUME_TRIGGER_DISCONNECT)
3185
+ strlcat(string, " DISCONNECT", str_size);
26553186 }
26563187
26573188 int wmi_resume(struct wil6210_priv *wil)
....@@ -2802,7 +3333,7 @@
28023333
28033334 if (mid == MID_BROADCAST)
28043335 mid = 0;
2805
- if (mid >= ARRAY_SIZE(wil->vifs) || mid >= wil->max_vifs) {
3336
+ if (mid >= GET_MAX_VIFS(wil)) {
28063337 wil_dbg_wmi(wil, "invalid mid %d, event skipped\n",
28073338 mid);
28083339 return;
....@@ -3408,6 +3939,7 @@
34083939 .ring_size = cpu_to_le16(ring->size),
34093940 .ring_id = ring_id,
34103941 },
3942
+ .max_msdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
34113943 .status_ring_id = wil->tx_sring_idx,
34123944 .encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
34133945 };
....@@ -3476,3 +4008,46 @@
34764008
34774009 return 0;
34784010 }
4011
+
4012
+int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
4013
+ s32 rssi_thold, u32 rssi_hyst)
4014
+{
4015
+ struct net_device *ndev = wil->main_ndev;
4016
+ struct wil6210_vif *vif = ndev_to_vif(ndev);
4017
+ int rc;
4018
+ struct {
4019
+ struct wmi_set_link_monitor_cmd cmd;
4020
+ s8 rssi_thold;
4021
+ } __packed cmd = {
4022
+ .cmd = {
4023
+ .rssi_hyst = rssi_hyst,
4024
+ .rssi_thresholds_list_size = 1,
4025
+ },
4026
+ .rssi_thold = rssi_thold,
4027
+ };
4028
+ struct {
4029
+ struct wmi_cmd_hdr hdr;
4030
+ struct wmi_set_link_monitor_event evt;
4031
+ } __packed reply = {
4032
+ .evt = {.status = WMI_FW_STATUS_FAILURE},
4033
+ };
4034
+
4035
+ if (rssi_thold > S8_MAX || rssi_thold < S8_MIN || rssi_hyst > U8_MAX)
4036
+ return -EINVAL;
4037
+
4038
+ rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, &cmd,
4039
+ sizeof(cmd), WMI_SET_LINK_MONITOR_EVENTID,
4040
+ &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
4041
+ if (rc) {
4042
+ wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc);
4043
+ return rc;
4044
+ }
4045
+
4046
+ if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
4047
+ wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, status %d\n",
4048
+ reply.evt.status);
4049
+ return -EINVAL;
4050
+ }
4051
+
4052
+ return 0;
4053
+}