]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/ath/wil6210/cfg80211.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / ath / wil6210 / cfg80211.c
CommitLineData
2be7d22f 1/*
849a564b 2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
2be7d22f
VK
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
a82553bb 17#include <linux/etherdevice.h>
949c2d00 18#include <linux/moduleparam.h>
0216a895 19#include <net/netlink.h>
2be7d22f
VK
20#include "wil6210.h"
21#include "wmi.h"
22
e6d68341
DL
23#define WIL_MAX_ROC_DURATION_MS 5000
24
849a564b 25bool disable_ap_sme;
78484c44 26module_param(disable_ap_sme, bool, 0444);
849a564b
DL
27MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
28
2be7d22f 29#define CHAN60G(_channel, _flags) { \
57fbcce3 30 .band = NL80211_BAND_60GHZ, \
2be7d22f
VK
31 .center_freq = 56160 + (2160 * (_channel)), \
32 .hw_value = (_channel), \
33 .flags = (_flags), \
34 .max_antenna_gain = 0, \
35 .max_power = 40, \
36}
37
38static struct ieee80211_channel wil_60ghz_channels[] = {
39 CHAN60G(1, 0),
40 CHAN60G(2, 0),
41 CHAN60G(3, 0),
42/* channel 4 not supported yet */
43};
44
0216a895
LD
45/* Vendor id to be used in vendor specific command and events
46 * to user space.
47 * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID,
48 * vendor subcmd definitions prefixed with QCA_NL80211_VENDOR_SUBCMD, and
49 * qca_wlan_vendor_attr is open source file src/common/qca-vendor.h in
50 * git://w1.fi/srv/git/hostap.git; the values here are just a copy of that
51 */
52
53#define QCA_NL80211_VENDOR_ID 0x001374
54
55#define WIL_MAX_RF_SECTORS (128)
56#define WIL_CID_ALL (0xff)
57
58enum qca_wlan_vendor_attr_rf_sector {
59 QCA_ATTR_MAC_ADDR = 6,
60 QCA_ATTR_PAD = 13,
61 QCA_ATTR_TSF = 29,
62 QCA_ATTR_DMG_RF_SECTOR_INDEX = 30,
63 QCA_ATTR_DMG_RF_SECTOR_TYPE = 31,
64 QCA_ATTR_DMG_RF_MODULE_MASK = 32,
65 QCA_ATTR_DMG_RF_SECTOR_CFG = 33,
66 QCA_ATTR_DMG_RF_SECTOR_MAX,
67};
68
69enum qca_wlan_vendor_attr_dmg_rf_sector_type {
70 QCA_ATTR_DMG_RF_SECTOR_TYPE_RX,
71 QCA_ATTR_DMG_RF_SECTOR_TYPE_TX,
72 QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX
73};
74
75enum qca_wlan_vendor_attr_dmg_rf_sector_cfg {
76 QCA_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0,
77 QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
78 QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
79 QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
80 QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
81 QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
82 QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
83 QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
84
85 /* keep last */
86 QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST,
87 QCA_ATTR_DMG_RF_SECTOR_CFG_MAX =
88 QCA_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1
89};
90
91static const struct
92nla_policy wil_rf_sector_policy[QCA_ATTR_DMG_RF_SECTOR_MAX + 1] = {
93 [QCA_ATTR_MAC_ADDR] = { .len = ETH_ALEN },
94 [QCA_ATTR_DMG_RF_SECTOR_INDEX] = { .type = NLA_U16 },
95 [QCA_ATTR_DMG_RF_SECTOR_TYPE] = { .type = NLA_U8 },
96 [QCA_ATTR_DMG_RF_MODULE_MASK] = { .type = NLA_U32 },
97 [QCA_ATTR_DMG_RF_SECTOR_CFG] = { .type = NLA_NESTED },
98};
99
100static const struct
101nla_policy wil_rf_sector_cfg_policy[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1] = {
102 [QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] = { .type = NLA_U8 },
103 [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] = { .type = NLA_U32 },
104 [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] = { .type = NLA_U32 },
105 [QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] = { .type = NLA_U32 },
106 [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] = { .type = NLA_U32 },
107 [QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] = { .type = NLA_U32 },
108 [QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16] = { .type = NLA_U32 },
109};
110
111enum qca_nl80211_vendor_subcmds {
112 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139,
113 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140,
114 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141,
115 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142,
116};
117
118static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
119 struct wireless_dev *wdev,
120 const void *data, int data_len);
121static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
122 struct wireless_dev *wdev,
123 const void *data, int data_len);
124static int wil_rf_sector_get_selected(struct wiphy *wiphy,
125 struct wireless_dev *wdev,
126 const void *data, int data_len);
127static int wil_rf_sector_set_selected(struct wiphy *wiphy,
128 struct wireless_dev *wdev,
129 const void *data, int data_len);
130
131/* vendor specific commands */
132static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
133 {
134 .info.vendor_id = QCA_NL80211_VENDOR_ID,
135 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
136 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
137 WIPHY_VENDOR_CMD_NEED_RUNNING,
138 .doit = wil_rf_sector_get_cfg
139 },
140 {
141 .info.vendor_id = QCA_NL80211_VENDOR_ID,
142 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
143 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
144 WIPHY_VENDOR_CMD_NEED_RUNNING,
145 .doit = wil_rf_sector_set_cfg
146 },
147 {
148 .info.vendor_id = QCA_NL80211_VENDOR_ID,
149 .info.subcmd =
150 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
151 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
152 WIPHY_VENDOR_CMD_NEED_RUNNING,
153 .doit = wil_rf_sector_get_selected
154 },
155 {
156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
157 .info.subcmd =
158 QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
159 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
160 WIPHY_VENDOR_CMD_NEED_RUNNING,
161 .doit = wil_rf_sector_set_selected
162 },
163};
164
2be7d22f
VK
165static struct ieee80211_supported_band wil_band_60ghz = {
166 .channels = wil_60ghz_channels,
167 .n_channels = ARRAY_SIZE(wil_60ghz_channels),
168 .ht_cap = {
169 .ht_supported = true,
170 .cap = 0, /* TODO */
171 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */
172 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */
173 .mcs = {
174 /* MCS 1..12 - SC PHY */
175 .rx_mask = {0xfe, 0x1f}, /* 1..12 */
176 .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */
177 },
178 },
179};
180
181static const struct ieee80211_txrx_stypes
182wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
183 [NL80211_IFTYPE_STATION] = {
184 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
185 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
186 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
187 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
188 },
189 [NL80211_IFTYPE_AP] = {
190 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
849a564b
DL
191 BIT(IEEE80211_STYPE_PROBE_RESP >> 4) |
192 BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
193 BIT(IEEE80211_STYPE_DISASSOC >> 4),
2be7d22f 194 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
849a564b
DL
195 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
196 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
197 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
198 BIT(IEEE80211_STYPE_AUTH >> 4) |
199 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
200 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4)
2be7d22f
VK
201 },
202 [NL80211_IFTYPE_P2P_CLIENT] = {
203 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
204 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
205 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
206 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
207 },
208 [NL80211_IFTYPE_P2P_GO] = {
209 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
210 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
211 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
212 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
213 },
4332cac1
LD
214 [NL80211_IFTYPE_P2P_DEVICE] = {
215 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
216 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
217 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
218 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
219 },
2be7d22f
VK
220};
221
222static const u32 wil_cipher_suites[] = {
223 WLAN_CIPHER_SUITE_GCMP,
224};
225
58527421
VK
226static const char * const key_usage_str[] = {
227 [WMI_KEY_USE_PAIRWISE] = "PTK",
228 [WMI_KEY_USE_RX_GROUP] = "RX_GTK",
229 [WMI_KEY_USE_TX_GROUP] = "TX_GTK",
230};
231
2be7d22f
VK
232int wil_iftype_nl2wmi(enum nl80211_iftype type)
233{
234 static const struct {
235 enum nl80211_iftype nl;
236 enum wmi_network_type wmi;
237 } __nl2wmi[] = {
238 {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC},
239 {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA},
240 {NL80211_IFTYPE_AP, WMI_NETTYPE_AP},
241 {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P},
242 {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P},
243 {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */
244 };
245 uint i;
246
247 for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) {
248 if (__nl2wmi[i].nl == type)
249 return __nl2wmi[i].wmi;
250 }
251
252 return -EOPNOTSUPP;
253}
254
9eb82d43
VK
255int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
256 struct station_info *sinfo)
2be7d22f 257{
2be7d22f 258 struct wmi_notify_req_cmd cmd = {
3df2cd36 259 .cid = cid,
2be7d22f
VK
260 .interval_usec = 0,
261 };
ef28afdb 262 struct {
b874ddec 263 struct wmi_cmd_hdr wmi;
ef28afdb
VK
264 struct wmi_notify_req_done_event evt;
265 } __packed reply;
c8b78b5f 266 struct wil_net_stats *stats = &wil->sta[cid].stats;
ef28afdb 267 int rc;
2be7d22f 268
2be7d22f 269 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
ef28afdb 270 WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
2be7d22f
VK
271 if (rc)
272 return rc;
273
c8b78b5f
VK
274 wil_dbg_wmi(wil, "Link status for CID %d: {\n"
275 " MCS %d TSF 0x%016llx\n"
b8b33a3a 276 " BF status 0x%08x SNR 0x%08x SQI %d%%\n"
c8b78b5f
VK
277 " Tx Tpt %d goodput %d Rx goodput %d\n"
278 " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
279 cid, le16_to_cpu(reply.evt.bf_mcs),
280 le64_to_cpu(reply.evt.tsf), reply.evt.status,
281 le32_to_cpu(reply.evt.snr_val),
b8b33a3a 282 reply.evt.sqi,
c8b78b5f
VK
283 le32_to_cpu(reply.evt.tx_tpt),
284 le32_to_cpu(reply.evt.tx_goodput),
285 le32_to_cpu(reply.evt.rx_goodput),
286 le16_to_cpu(reply.evt.my_rx_sector),
287 le16_to_cpu(reply.evt.my_tx_sector),
288 le16_to_cpu(reply.evt.other_rx_sector),
289 le16_to_cpu(reply.evt.other_tx_sector));
290
2be7d22f
VK
291 sinfo->generation = wil->sinfo_gen;
292
319090bf
JB
293 sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) |
294 BIT(NL80211_STA_INFO_TX_BYTES) |
295 BIT(NL80211_STA_INFO_RX_PACKETS) |
296 BIT(NL80211_STA_INFO_TX_PACKETS) |
297 BIT(NL80211_STA_INFO_RX_BITRATE) |
298 BIT(NL80211_STA_INFO_TX_BITRATE) |
299 BIT(NL80211_STA_INFO_RX_DROP_MISC) |
300 BIT(NL80211_STA_INFO_TX_FAILED);
c8b78b5f 301
0c1eca4e 302 sinfo->txrate.flags = RATE_INFO_FLAGS_60G;
ef28afdb 303 sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
c8b78b5f
VK
304 sinfo->rxrate.mcs = stats->last_mcs_rx;
305 sinfo->rx_bytes = stats->rx_bytes;
306 sinfo->rx_packets = stats->rx_packets;
307 sinfo->rx_dropped_misc = stats->rx_dropped;
308 sinfo->tx_bytes = stats->tx_bytes;
309 sinfo->tx_packets = stats->tx_packets;
310 sinfo->tx_failed = stats->tx_errors;
2be7d22f 311
9419b6a2 312 if (test_bit(wil_status_fwconnected, wil->status)) {
319090bf 313 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
b8b33a3a 314 sinfo->signal = reply.evt.sqi;
2be7d22f
VK
315 }
316
ef28afdb
VK
317 return rc;
318}
319
320static int wil_cfg80211_get_station(struct wiphy *wiphy,
321 struct net_device *ndev,
3b3a0162 322 const u8 *mac, struct station_info *sinfo)
ef28afdb
VK
323{
324 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
325 int rc;
326
327 int cid = wil_find_cid(wil, mac);
328
af3db60a 329 wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid);
ef28afdb 330 if (cid < 0)
c14c5d99 331 return cid;
ef28afdb
VK
332
333 rc = wil_cid_fill_sinfo(wil, cid, sinfo);
334
335 return rc;
336}
337
338/*
339 * Find @idx-th active STA for station dump.
340 */
341static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx)
342{
343 int i;
344
345 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
346 if (wil->sta[i].status == wil_sta_unused)
347 continue;
348 if (idx == 0)
349 return i;
350 idx--;
351 }
352
353 return -ENOENT;
354}
355
356static int wil_cfg80211_dump_station(struct wiphy *wiphy,
357 struct net_device *dev, int idx,
358 u8 *mac, struct station_info *sinfo)
359{
360 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
361 int rc;
362 int cid = wil_find_cid_by_idx(wil, idx);
363
364 if (cid < 0)
365 return -ENOENT;
366
a82553bb 367 ether_addr_copy(mac, wil->sta[cid].addr);
af3db60a 368 wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid);
ef28afdb
VK
369
370 rc = wil_cid_fill_sinfo(wil, cid, sinfo);
371
372 return rc;
2be7d22f
VK
373}
374
4332cac1
LD
375static struct wireless_dev *
376wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
377 unsigned char name_assign_type,
378 enum nl80211_iftype type,
818a986e 379 struct vif_params *params)
4332cac1
LD
380{
381 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
382 struct net_device *ndev = wil_to_ndev(wil);
383 struct wireless_dev *p2p_wdev;
384
af3db60a 385 wil_dbg_misc(wil, "add_iface\n");
4332cac1
LD
386
387 if (type != NL80211_IFTYPE_P2P_DEVICE) {
af3db60a 388 wil_err(wil, "unsupported iftype %d\n", type);
4332cac1
LD
389 return ERR_PTR(-EINVAL);
390 }
391
392 if (wil->p2p_wdev) {
af3db60a 393 wil_err(wil, "P2P_DEVICE interface already created\n");
4332cac1
LD
394 return ERR_PTR(-EINVAL);
395 }
396
397 p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL);
398 if (!p2p_wdev)
399 return ERR_PTR(-ENOMEM);
400
401 p2p_wdev->iftype = type;
402 p2p_wdev->wiphy = wiphy;
403 /* use our primary ethernet address */
404 ether_addr_copy(p2p_wdev->address, ndev->perm_addr);
405
406 wil->p2p_wdev = p2p_wdev;
407
408 return p2p_wdev;
409}
410
411static int wil_cfg80211_del_iface(struct wiphy *wiphy,
412 struct wireless_dev *wdev)
413{
414 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
415
af3db60a 416 wil_dbg_misc(wil, "del_iface\n");
4332cac1
LD
417
418 if (wdev != wil->p2p_wdev) {
af3db60a 419 wil_err(wil, "delete of incorrect interface 0x%p\n", wdev);
4332cac1
LD
420 return -EINVAL;
421 }
422
423 wil_p2p_wdev_free(wil);
424
425 return 0;
426}
427
2be7d22f
VK
428static int wil_cfg80211_change_iface(struct wiphy *wiphy,
429 struct net_device *ndev,
818a986e 430 enum nl80211_iftype type,
2be7d22f
VK
431 struct vif_params *params)
432{
433 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
4332cac1 434 struct wireless_dev *wdev = wil_to_wdev(wil);
e6d68341
DL
435 int rc;
436
af3db60a 437 wil_dbg_misc(wil, "change_iface: type=%d\n", type);
e6d68341 438
375a173f 439 if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) {
e6d68341
DL
440 wil_dbg_misc(wil, "interface is up. resetting...\n");
441 mutex_lock(&wil->mutex);
442 __wil_down(wil);
443 rc = __wil_up(wil);
444 mutex_unlock(&wil->mutex);
445
446 if (rc)
447 return rc;
448 }
2be7d22f
VK
449
450 switch (type) {
451 case NL80211_IFTYPE_STATION:
452 case NL80211_IFTYPE_AP:
453 case NL80211_IFTYPE_P2P_CLIENT:
454 case NL80211_IFTYPE_P2P_GO:
455 break;
456 case NL80211_IFTYPE_MONITOR:
818a986e
JB
457 if (params->flags)
458 wil->monitor_flags = params->flags;
2be7d22f
VK
459 break;
460 default:
461 return -EOPNOTSUPP;
462 }
463
464 wdev->iftype = type;
465
466 return 0;
467}
468
469static int wil_cfg80211_scan(struct wiphy *wiphy,
470 struct cfg80211_scan_request *request)
471{
472 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
4332cac1 473 struct wireless_dev *wdev = request->wdev;
2be7d22f
VK
474 struct {
475 struct wmi_start_scan_cmd cmd;
476 u16 chnl[4];
477 } __packed cmd;
478 uint i, n;
ed6f9dc6 479 int rc;
2be7d22f 480
af3db60a 481 wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
e6d68341 482
2be7d22f
VK
483 /* check we are client side */
484 switch (wdev->iftype) {
485 case NL80211_IFTYPE_STATION:
486 case NL80211_IFTYPE_P2P_CLIENT:
4332cac1 487 case NL80211_IFTYPE_P2P_DEVICE:
2be7d22f
VK
488 break;
489 default:
490 return -EOPNOTSUPP;
2be7d22f
VK
491 }
492
493 /* FW don't support scan after connection attempt */
9419b6a2 494 if (test_bit(wil_status_dontscan, wil->status)) {
e83eb2fc 495 wil_err(wil, "Can't scan now\n");
2be7d22f
VK
496 return -EBUSY;
497 }
498
bb6743f7
LD
499 mutex_lock(&wil->mutex);
500
501 mutex_lock(&wil->p2p_wdev_mutex);
502 if (wil->scan_request || wil->p2p.discovery_started) {
503 wil_err(wil, "Already scanning\n");
504 mutex_unlock(&wil->p2p_wdev_mutex);
505 rc = -EAGAIN;
506 goto out;
507 }
508 mutex_unlock(&wil->p2p_wdev_mutex);
509
4a0e45a7 510 if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
eb57a5b3
LD
511 if (!wil->p2p.p2p_dev_started) {
512 wil_err(wil, "P2P search requested on stopped P2P device\n");
bb6743f7
LD
513 rc = -EIO;
514 goto out;
eb57a5b3 515 }
4a0e45a7
LD
516 /* social scan on P2P_DEVICE is handled as p2p search */
517 if (wil_p2p_is_social_scan(request)) {
518 wil->scan_request = request;
519 wil->radio_wdev = wdev;
520 rc = wil_p2p_search(wil, request);
521 if (rc) {
522 wil->radio_wdev = wil_to_wdev(wil);
523 wil->scan_request = NULL;
524 }
525 goto out;
4332cac1 526 }
e6d68341
DL
527 }
528
280ab987 529 (void)wil_p2p_stop_discovery(wil);
e6d68341 530
2a91d7d0 531 wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
8e52fe30
HK
532 wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
533
534 for (i = 0; i < request->n_ssids; i++) {
535 wil_dbg_misc(wil, "SSID[%d]", i);
5eb443e9
DL
536 wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
537 request->ssids[i].ssid,
538 request->ssids[i].ssid_len, true);
8e52fe30
HK
539 }
540
541 if (request->n_ssids)
542 rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
543 request->ssids[0].ssid);
544 else
545 rc = wmi_set_ssid(wil, 0, NULL);
546
547 if (rc) {
548 wil_err(wil, "set SSID for scan request failed: %d\n", rc);
bb6743f7 549 goto out;
8e52fe30
HK
550 }
551
2be7d22f 552 wil->scan_request = request;
047e5d74 553 mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
2be7d22f
VK
554
555 memset(&cmd, 0, sizeof(cmd));
74997a53 556 cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
2be7d22f
VK
557 cmd.cmd.num_channels = 0;
558 n = min(request->n_channels, 4U);
559 for (i = 0; i < n; i++) {
560 int ch = request->channels[i]->hw_value;
8fe59627 561
2be7d22f
VK
562 if (ch == 0) {
563 wil_err(wil,
564 "Scan requested for unknown frequency %dMhz\n",
565 request->channels[i]->center_freq);
566 continue;
567 }
568 /* 0-based channel indexes */
569 cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
7743882d 570 wil_dbg_misc(wil, "Scan for ch %d : %d MHz\n", ch,
2057ebb2 571 request->channels[i]->center_freq);
2be7d22f
VK
572 }
573
77c91295 574 if (request->ie_len)
5eb443e9
DL
575 wil_hex_dump_misc("Scan IE ", DUMP_PREFIX_OFFSET, 16, 1,
576 request->ie, request->ie_len, true);
77c91295
VK
577 else
578 wil_dbg_misc(wil, "Scan has no IE's\n");
579
5421bf0c
VK
580 rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
581 if (rc)
bb6743f7 582 goto out_restore;
77c91295 583
74997a53
LD
584 if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
585 cmd.cmd.discovery_mode = 1;
586 wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
587 }
588
4332cac1 589 wil->radio_wdev = wdev;
ed6f9dc6 590 rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
2be7d22f 591 cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
ed6f9dc6 592
bb6743f7 593out_restore:
a2142086
VK
594 if (rc) {
595 del_timer_sync(&wil->scan_timer);
4332cac1 596 wil->radio_wdev = wil_to_wdev(wil);
ed6f9dc6 597 wil->scan_request = NULL;
a2142086 598 }
bb6743f7
LD
599out:
600 mutex_unlock(&wil->mutex);
ed6f9dc6 601 return rc;
2be7d22f
VK
602}
603
035859a5
ME
604static void wil_cfg80211_abort_scan(struct wiphy *wiphy,
605 struct wireless_dev *wdev)
606{
607 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
608
609 wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
610
611 mutex_lock(&wil->mutex);
612 mutex_lock(&wil->p2p_wdev_mutex);
613
614 if (!wil->scan_request)
615 goto out;
616
617 if (wdev != wil->scan_request->wdev) {
618 wil_dbg_misc(wil, "abort scan was called on the wrong iface\n");
619 goto out;
620 }
621
622 if (wil->radio_wdev == wil->p2p_wdev)
623 wil_p2p_stop_radio_operations(wil);
624 else
625 wil_abort_scan(wil, true);
626
627out:
628 mutex_unlock(&wil->p2p_wdev_mutex);
629 mutex_unlock(&wil->mutex);
630}
631
feeac225
VK
632static void wil_print_crypto(struct wil6210_priv *wil,
633 struct cfg80211_crypto_settings *c)
634{
635 int i, n;
636
637 wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n",
638 c->wpa_versions, c->cipher_group);
639 wil_dbg_misc(wil, "Pairwise ciphers [%d] {\n", c->n_ciphers_pairwise);
640 n = min_t(int, c->n_ciphers_pairwise, ARRAY_SIZE(c->ciphers_pairwise));
641 for (i = 0; i < n; i++)
642 wil_dbg_misc(wil, " [%d] = 0x%08x\n", i,
643 c->ciphers_pairwise[i]);
644 wil_dbg_misc(wil, "}\n");
645 wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites);
646 n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites));
647 for (i = 0; i < n; i++)
648 wil_dbg_misc(wil, " [%d] = 0x%08x\n", i,
649 c->akm_suites[i]);
650 wil_dbg_misc(wil, "}\n");
651 wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n",
652 c->control_port, be16_to_cpu(c->control_port_ethertype),
653 c->control_port_no_encrypt);
654}
655
8ca26163
VK
656static void wil_print_connect_params(struct wil6210_priv *wil,
657 struct cfg80211_connect_params *sme)
658{
659 wil_info(wil, "Connecting to:\n");
660 if (sme->channel) {
661 wil_info(wil, " Channel: %d freq %d\n",
662 sme->channel->hw_value, sme->channel->center_freq);
663 }
664 if (sme->bssid)
665 wil_info(wil, " BSSID: %pM\n", sme->bssid);
666 if (sme->ssid)
667 print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET,
668 16, 1, sme->ssid, sme->ssid_len, true);
669 wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open");
eabb03b4 670 wil_info(wil, " PBSS: %d\n", sme->pbss);
feeac225 671 wil_print_crypto(wil, &sme->crypto);
8ca26163
VK
672}
673
2be7d22f
VK
674static int wil_cfg80211_connect(struct wiphy *wiphy,
675 struct net_device *ndev,
676 struct cfg80211_connect_params *sme)
677{
678 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
679 struct cfg80211_bss *bss;
680 struct wmi_connect_cmd conn;
681 const u8 *ssid_eid;
682 const u8 *rsn_eid;
683 int ch;
684 int rc = 0;
eabb03b4 685 enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
2be7d22f 686
af3db60a 687 wil_dbg_misc(wil, "connect\n");
344a7024
VK
688 wil_print_connect_params(wil, sme);
689
9419b6a2
VK
690 if (test_bit(wil_status_fwconnecting, wil->status) ||
691 test_bit(wil_status_fwconnected, wil->status))
4cd9e837
VK
692 return -EALREADY;
693
344a7024
VK
694 if (sme->ie_len > WMI_MAX_IE_LEN) {
695 wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len);
696 return -ERANGE;
697 }
698
699 rsn_eid = sme->ie ?
700 cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
701 NULL;
27aa6b71
VK
702 if (sme->privacy && !rsn_eid)
703 wil_info(wil, "WSC connection\n");
8ca26163 704
eabb03b4
LD
705 if (sme->pbss)
706 bss_type = IEEE80211_BSS_TYPE_PBSS;
34d50519 707
2be7d22f
VK
708 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
709 sme->ssid, sme->ssid_len,
eabb03b4 710 bss_type, IEEE80211_PRIVACY_ANY);
2be7d22f
VK
711 if (!bss) {
712 wil_err(wil, "Unable to find BSS\n");
713 return -ENOENT;
714 }
715
716 ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
717 if (!ssid_eid) {
718 wil_err(wil, "No SSID\n");
719 rc = -ENOENT;
720 goto out;
721 }
344a7024 722 wil->privacy = sme->privacy;
a895cb8b 723 wil->pbss = sme->pbss;
2be7d22f 724
344a7024 725 if (wil->privacy) {
230d8442
VK
726 /* For secure assoc, remove old keys */
727 rc = wmi_del_cipher_key(wil, 0, bss->bssid,
728 WMI_KEY_USE_PAIRWISE);
2be7d22f 729 if (rc) {
230d8442
VK
730 wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
731 goto out;
732 }
733 rc = wmi_del_cipher_key(wil, 0, bss->bssid,
734 WMI_KEY_USE_RX_GROUP);
735 if (rc) {
736 wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
2be7d22f
VK
737 goto out;
738 }
ac4acdb7
VK
739 }
740
741 /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info
742 * elements. Send it also in case it's empty, to erase previously set
743 * ies in FW.
744 */
745 rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
5421bf0c 746 if (rc)
ac4acdb7 747 goto out;
2be7d22f
VK
748
749 /* WMI_CONNECT_CMD */
750 memset(&conn, 0, sizeof(conn));
acc9780d 751 switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
2be7d22f
VK
752 case WLAN_CAPABILITY_DMG_TYPE_AP:
753 conn.network_type = WMI_NETTYPE_INFRA;
754 break;
755 case WLAN_CAPABILITY_DMG_TYPE_PBSS:
756 conn.network_type = WMI_NETTYPE_P2P;
757 break;
758 default:
759 wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
760 bss->capability);
761 goto out;
762 }
344a7024 763 if (wil->privacy) {
27aa6b71
VK
764 if (rsn_eid) { /* regular secure connection */
765 conn.dot11_auth_mode = WMI_AUTH11_SHARED;
766 conn.auth_mode = WMI_AUTH_WPA2_PSK;
767 conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
768 conn.pairwise_crypto_len = 16;
769 conn.group_crypto_type = WMI_CRYPT_AES_GCMP;
770 conn.group_crypto_len = 16;
771 } else { /* WSC */
772 conn.dot11_auth_mode = WMI_AUTH11_WSC;
773 conn.auth_mode = WMI_AUTH_NONE;
774 }
775 } else { /* insecure connection */
2be7d22f
VK
776 conn.dot11_auth_mode = WMI_AUTH11_OPEN;
777 conn.auth_mode = WMI_AUTH_NONE;
778 }
779
780 conn.ssid_len = min_t(u8, ssid_eid[1], 32);
781 memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
782
783 ch = bss->channel->hw_value;
784 if (ch == 0) {
785 wil_err(wil, "BSS at unknown frequency %dMhz\n",
786 bss->channel->center_freq);
787 rc = -EOPNOTSUPP;
788 goto out;
789 }
790 conn.channel = ch - 1;
791
a82553bb
VK
792 ether_addr_copy(conn.bssid, bss->bssid);
793 ether_addr_copy(conn.dst_mac, bss->bssid);
e83eb2fc 794
9419b6a2 795 set_bit(wil_status_fwconnecting, wil->status);
2be7d22f
VK
796
797 rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
798 if (rc == 0) {
c5e96c91 799 netif_carrier_on(ndev);
9953a782 800 wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
bcdd49b0 801 wil->bss = bss;
2be7d22f
VK
802 /* Connect can take lots of time */
803 mod_timer(&wil->connect_timer,
804 jiffies + msecs_to_jiffies(2000));
b338f74e 805 } else {
9419b6a2 806 clear_bit(wil_status_fwconnecting, wil->status);
2be7d22f
VK
807 }
808
809 out:
5b112d3d 810 cfg80211_put_bss(wiphy, bss);
2be7d22f
VK
811
812 return rc;
813}
814
815static int wil_cfg80211_disconnect(struct wiphy *wiphy,
816 struct net_device *ndev,
817 u16 reason_code)
818{
819 int rc;
820 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
821
af3db60a 822 wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code);
de9084ef 823
78771d76
VK
824 if (!(test_bit(wil_status_fwconnecting, wil->status) ||
825 test_bit(wil_status_fwconnected, wil->status))) {
af3db60a 826 wil_err(wil, "Disconnect was called while disconnected\n");
78771d76
VK
827 return 0;
828 }
829
3b56c15f 830 wil->locally_generated_disc = true;
78771d76
VK
831 rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
832 WMI_DISCONNECT_EVENTID, NULL, 0,
833 WIL6210_DISCONNECT_TO_MS);
834 if (rc)
af3db60a 835 wil_err(wil, "disconnect error %d\n", rc);
2be7d22f
VK
836
837 return rc;
838}
839
3fea18d0
LD
840static int wil_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
841{
842 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
843 int rc;
844
845 /* these parameters are explicitly not supported */
846 if (changed & (WIPHY_PARAM_RETRY_LONG |
847 WIPHY_PARAM_FRAG_THRESHOLD |
848 WIPHY_PARAM_RTS_THRESHOLD))
849 return -ENOTSUPP;
850
851 if (changed & WIPHY_PARAM_RETRY_SHORT) {
852 rc = wmi_set_mgmt_retry(wil, wiphy->retry_short);
853 if (rc)
854 return rc;
855 }
856
857 return 0;
858}
859
0b39aaf2
VK
860int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
861 struct cfg80211_mgmt_tx_params *params,
862 u64 *cookie)
1647f12f
VK
863{
864 const u8 *buf = params->buf;
865 size_t len = params->len;
866 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
867 int rc;
304464f4 868 bool tx_status = false;
1647f12f
VK
869 struct ieee80211_mgmt *mgmt_frame = (void *)buf;
870 struct wmi_sw_tx_req_cmd *cmd;
871 struct {
b874ddec 872 struct wmi_cmd_hdr wmi;
1647f12f
VK
873 struct wmi_sw_tx_complete_event evt;
874 } __packed evt;
875
e6d68341
DL
876 /* Note, currently we do not support the "wait" parameter, user-space
877 * must call remain_on_channel before mgmt_tx or listen on a channel
878 * another way (AP/PCP or connected station)
879 * in addition we need to check if specified "chan" argument is
880 * different from currently "listened" channel and fail if it is.
881 */
882
af3db60a 883 wil_dbg_misc(wil, "mgmt_tx\n");
5eb443e9
DL
884 wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
885 len, true);
e6d68341 886
1647f12f 887 cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
304464f4
VK
888 if (!cmd) {
889 rc = -ENOMEM;
890 goto out;
891 }
1647f12f
VK
892
893 memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
894 cmd->len = cpu_to_le16(len);
895 memcpy(cmd->payload, buf, len);
896
897 rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
898 WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
899 if (rc == 0)
304464f4 900 tx_status = !evt.evt.status;
1647f12f
VK
901
902 kfree(cmd);
304464f4
VK
903 out:
904 cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
905 tx_status, GFP_KERNEL);
1647f12f
VK
906 return rc;
907}
908
2be7d22f
VK
909static int wil_cfg80211_set_channel(struct wiphy *wiphy,
910 struct cfg80211_chan_def *chandef)
911{
912 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
4332cac1 913 struct wireless_dev *wdev = wil_to_wdev(wil);
2be7d22f
VK
914
915 wdev->preset_chandef = *chandef;
916
917 return 0;
918}
919
230d8442
VK
920static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
921 bool pairwise)
922{
4332cac1 923 struct wireless_dev *wdev = wil_to_wdev(wil);
230d8442 924 enum wmi_key_usage rc;
230d8442
VK
925
926 if (pairwise) {
927 rc = WMI_KEY_USE_PAIRWISE;
928 } else {
929 switch (wdev->iftype) {
930 case NL80211_IFTYPE_STATION:
e6d68341 931 case NL80211_IFTYPE_P2P_CLIENT:
230d8442
VK
932 rc = WMI_KEY_USE_RX_GROUP;
933 break;
934 case NL80211_IFTYPE_AP:
e6d68341 935 case NL80211_IFTYPE_P2P_GO:
230d8442
VK
936 rc = WMI_KEY_USE_TX_GROUP;
937 break;
938 default:
939 /* TODO: Rx GTK or Tx GTK? */
940 wil_err(wil, "Can't determine GTK type\n");
941 rc = WMI_KEY_USE_RX_GROUP;
942 break;
943 }
944 }
af3db60a 945 wil_dbg_misc(wil, "detect_key_usage: -> %s\n", key_usage_str[rc]);
230d8442
VK
946
947 return rc;
948}
949
74b6ac58
ME
950static struct wil_sta_info *
951wil_find_sta_by_key_usage(struct wil6210_priv *wil,
952 enum wmi_key_usage key_usage, const u8 *mac_addr)
58527421
VK
953{
954 int cid = -EINVAL;
58527421
VK
955
956 if (key_usage == WMI_KEY_USE_TX_GROUP)
957 return NULL; /* not needed */
958
959 /* supplicant provides Rx group key in STA mode with NULL MAC address */
960 if (mac_addr)
961 cid = wil_find_cid(wil, mac_addr);
962 else if (key_usage == WMI_KEY_USE_RX_GROUP)
963 cid = wil_find_cid_by_idx(wil, 0);
964 if (cid < 0) {
74b6ac58
ME
965 wil_err(wil, "No CID for %pM %s\n", mac_addr,
966 key_usage_str[key_usage]);
58527421
VK
967 return ERR_PTR(cid);
968 }
969
74b6ac58
ME
970 return &wil->sta[cid];
971}
58527421 972
74b6ac58
ME
973static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
974 struct wil_sta_info *cs,
975 struct key_params *params)
976{
977 struct wil_tid_crypto_rx_single *cc;
978 int tid;
979
980 if (!cs)
981 return;
982
983 switch (key_usage) {
984 case WMI_KEY_USE_PAIRWISE:
985 for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
986 cc = &cs->tid_crypto_rx[tid].key_id[key_index];
987 if (params->seq)
988 memcpy(cc->pn, params->seq,
989 IEEE80211_GCMP_PN_LEN);
990 else
991 memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
992 cc->key_set = true;
993 }
994 break;
995 case WMI_KEY_USE_RX_GROUP:
996 cc = &cs->group_crypto_rx.key_id[key_index];
997 if (params->seq)
998 memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
999 else
1000 memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
1001 cc->key_set = true;
1002 break;
1003 default:
1004 break;
1005 }
1006}
1007
1008static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
1009 struct wil_sta_info *cs)
1010{
1011 struct wil_tid_crypto_rx_single *cc;
1012 int tid;
1013
1014 if (!cs)
1015 return;
1016
1017 switch (key_usage) {
1018 case WMI_KEY_USE_PAIRWISE:
1019 for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
1020 cc = &cs->tid_crypto_rx[tid].key_id[key_index];
1021 cc->key_set = false;
1022 }
1023 break;
1024 case WMI_KEY_USE_RX_GROUP:
1025 cc = &cs->group_crypto_rx.key_id[key_index];
1026 cc->key_set = false;
1027 break;
1028 default:
1029 break;
1030 }
58527421
VK
1031}
1032
2be7d22f
VK
1033static int wil_cfg80211_add_key(struct wiphy *wiphy,
1034 struct net_device *ndev,
1035 u8 key_index, bool pairwise,
1036 const u8 *mac_addr,
1037 struct key_params *params)
1038{
58527421 1039 int rc;
2be7d22f 1040 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
230d8442 1041 enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
74b6ac58
ME
1042 struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
1043 mac_addr);
1044
1045 if (!params) {
1046 wil_err(wil, "NULL params\n");
1047 return -EINVAL;
1048 }
58527421 1049
af3db60a 1050 wil_dbg_misc(wil, "add_key: %pM %s[%d] PN %*phN\n",
58527421
VK
1051 mac_addr, key_usage_str[key_usage], key_index,
1052 params->seq_len, params->seq);
1053
74b6ac58 1054 if (IS_ERR(cs)) {
af3db60a
LA
1055 wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
1056 mac_addr, key_usage_str[key_usage], key_index,
58527421
VK
1057 params->seq_len, params->seq);
1058 return -EINVAL;
1059 }
1060
74b6ac58 1061 wil_del_rx_key(key_index, key_usage, cs);
58527421
VK
1062
1063 if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
1064 wil_err(wil,
af3db60a
LA
1065 "Wrong PN len %d, %pM %s[%d] PN %*phN\n",
1066 params->seq_len, mac_addr,
58527421
VK
1067 key_usage_str[key_usage], key_index,
1068 params->seq_len, params->seq);
1069 return -EINVAL;
1070 }
2be7d22f 1071
58527421
VK
1072 rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
1073 params->key, key_usage);
74b6ac58
ME
1074 if (!rc)
1075 wil_set_crypto_rx(key_index, key_usage, cs, params);
db8adcbf 1076
58527421 1077 return rc;
2be7d22f
VK
1078}
1079
1080static int wil_cfg80211_del_key(struct wiphy *wiphy,
1081 struct net_device *ndev,
1082 u8 key_index, bool pairwise,
1083 const u8 *mac_addr)
1084{
1085 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
230d8442 1086 enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
74b6ac58
ME
1087 struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
1088 mac_addr);
58527421 1089
af3db60a 1090 wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr,
58527421
VK
1091 key_usage_str[key_usage], key_index);
1092
74b6ac58 1093 if (IS_ERR(cs))
af3db60a 1094 wil_info(wil, "Not connected, %pM %s[%d]\n",
58527421 1095 mac_addr, key_usage_str[key_usage], key_index);
2be7d22f 1096
74b6ac58
ME
1097 if (!IS_ERR_OR_NULL(cs))
1098 wil_del_rx_key(key_index, key_usage, cs);
db8adcbf 1099
230d8442 1100 return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
2be7d22f
VK
1101}
1102
1103/* Need to be present or wiphy_new() will WARN */
1104static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
1105 struct net_device *ndev,
1106 u8 key_index, bool unicast,
1107 bool multicast)
1108{
280ab987
LD
1109 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1110
af3db60a 1111 wil_dbg_misc(wil, "set_default_key: entered\n");
2be7d22f
VK
1112 return 0;
1113}
1114
1647f12f
VK
1115static int wil_remain_on_channel(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 struct ieee80211_channel *chan,
1118 unsigned int duration,
1119 u64 *cookie)
1120{
1121 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1122 int rc;
1123
af3db60a
LA
1124 wil_dbg_misc(wil,
1125 "remain_on_channel: center_freq=%d, duration=%d iftype=%d\n",
1126 chan->center_freq, duration, wdev->iftype);
1647f12f 1127
bb6743f7
LD
1128 rc = wil_p2p_listen(wil, wdev, duration, chan, cookie);
1129 return rc;
1647f12f
VK
1130}
1131
1132static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
1133 struct wireless_dev *wdev,
1134 u64 cookie)
1135{
1136 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1647f12f 1137
af3db60a 1138 wil_dbg_misc(wil, "cancel_remain_on_channel\n");
1647f12f 1139
280ab987 1140 return wil_p2p_cancel_listen(wil, cookie);
1647f12f
VK
1141}
1142
c100c883
LD
1143/**
1144 * find a specific IE in a list of IEs
1145 * return a pointer to the beginning of IE in the list
1146 * or NULL if not found
1147 */
1148static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie,
1149 u16 ie_len)
1150{
1151 struct ieee80211_vendor_ie *vie;
1152 u32 oui;
1153
1154 /* IE tag at offset 0, length at offset 1 */
1155 if (ie_len < 2 || 2 + ie[1] > ie_len)
1156 return NULL;
1157
1158 if (ie[0] != WLAN_EID_VENDOR_SPECIFIC)
1159 return cfg80211_find_ie(ie[0], ies, ies_len);
1160
1161 /* make sure there is room for 3 bytes OUI + 1 byte OUI type */
1162 if (ie[1] < 4)
1163 return NULL;
1164 vie = (struct ieee80211_vendor_ie *)ie;
1165 oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2];
1166 return cfg80211_find_vendor_ie(oui, vie->oui_type, ies,
1167 ies_len);
1168}
1169
1170/**
1171 * merge the IEs in two lists into a single list.
1172 * do not include IEs from the second list which exist in the first list.
1173 * add only vendor specific IEs from second list to keep
1174 * the merged list sorted (since vendor-specific IE has the
1175 * highest tag number)
1176 * caller must free the allocated memory for merged IEs
1177 */
1178static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
1179 const u8 *ies2, u16 ies2_len,
1180 u8 **merged_ies, u16 *merged_len)
1181{
1182 u8 *buf, *dpos;
1183 const u8 *spos;
1184
1185 if (ies1_len == 0 && ies2_len == 0) {
1186 *merged_ies = NULL;
1187 *merged_len = 0;
1188 return 0;
1189 }
1190
1191 buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
1192 if (!buf)
1193 return -ENOMEM;
1194 memcpy(buf, ies1, ies1_len);
1195 dpos = buf + ies1_len;
1196 spos = ies2;
1197 while (spos + 1 < ies2 + ies2_len) {
1198 /* IE tag at offset 0, length at offset 1 */
1199 u16 ielen = 2 + spos[1];
1200
1201 if (spos + ielen > ies2 + ies2_len)
1202 break;
1203 if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
1204 !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
1205 memcpy(dpos, spos, ielen);
1206 dpos += ielen;
1207 }
1208 spos += ielen;
1209 }
1210
1211 *merged_ies = buf;
1212 *merged_len = dpos - buf;
1213 return 0;
1214}
1215
ca959773
VK
1216static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
1217{
5eb443e9
DL
1218 wil_hex_dump_misc("head ", DUMP_PREFIX_OFFSET, 16, 1,
1219 b->head, b->head_len, true);
1220 wil_hex_dump_misc("tail ", DUMP_PREFIX_OFFSET, 16, 1,
1221 b->tail, b->tail_len, true);
1222 wil_hex_dump_misc("BCON IE ", DUMP_PREFIX_OFFSET, 16, 1,
1223 b->beacon_ies, b->beacon_ies_len, true);
1224 wil_hex_dump_misc("PROBE ", DUMP_PREFIX_OFFSET, 16, 1,
1225 b->probe_resp, b->probe_resp_len, true);
1226 wil_hex_dump_misc("PROBE IE ", DUMP_PREFIX_OFFSET, 16, 1,
1227 b->proberesp_ies, b->proberesp_ies_len, true);
1228 wil_hex_dump_misc("ASSOC IE ", DUMP_PREFIX_OFFSET, 16, 1,
1229 b->assocresp_ies, b->assocresp_ies_len, true);
ca959773
VK
1230}
1231
33190ebf
VK
1232/* internal functions for device reset and starting AP */
1233static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
cab5abbf 1234 struct cfg80211_beacon_data *bcon)
33190ebf
VK
1235{
1236 int rc;
1237 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
c100c883
LD
1238 u16 len = 0, proberesp_len = 0;
1239 u8 *ies = NULL, *proberesp = NULL;
1240
1241 if (bcon->probe_resp) {
1242 struct ieee80211_mgmt *f =
1243 (struct ieee80211_mgmt *)bcon->probe_resp;
1244 size_t hlen = offsetof(struct ieee80211_mgmt,
1245 u.probe_resp.variable);
1246 proberesp = f->u.probe_resp.variable;
1247 proberesp_len = bcon->probe_resp_len - hlen;
1248 }
1249 rc = _wil_cfg80211_merge_extra_ies(proberesp,
1250 proberesp_len,
1251 bcon->proberesp_ies,
1252 bcon->proberesp_ies_len,
1253 &ies, &len);
33190ebf 1254
5421bf0c 1255 if (rc)
c100c883
LD
1256 goto out;
1257
1258 rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies);
1259 if (rc)
1260 goto out;
33190ebf 1261
c100c883
LD
1262 if (bcon->assocresp_ies)
1263 rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP,
1264 bcon->assocresp_ies_len, bcon->assocresp_ies);
1265 else
1266 rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies);
cab5abbf 1267#if 0 /* to use beacon IE's, remove this #if 0 */
5421bf0c 1268 if (rc)
c100c883 1269 goto out;
5421bf0c
VK
1270
1271 rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail);
cab5abbf 1272#endif
c100c883
LD
1273out:
1274 kfree(ies);
5421bf0c 1275 return rc;
33190ebf
VK
1276}
1277
1278static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
1279 struct net_device *ndev,
1280 const u8 *ssid, size_t ssid_len, u32 privacy,
1281 int bi, u8 chan,
cab5abbf 1282 struct cfg80211_beacon_data *bcon,
eabb03b4 1283 u8 hidden_ssid, u32 pbss)
33190ebf
VK
1284{
1285 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1286 int rc;
1287 struct wireless_dev *wdev = ndev->ieee80211_ptr;
1288 u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
b4944f2c 1289 u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
33190ebf 1290
eabb03b4
LD
1291 if (pbss)
1292 wmi_nettype = WMI_NETTYPE_P2P;
1293
af3db60a 1294 wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go);
b4944f2c 1295 if (is_go && !pbss) {
af3db60a 1296 wil_err(wil, "P2P GO must be in PBSS\n");
b4944f2c
LD
1297 return -ENOTSUPP;
1298 }
1299
33190ebf
VK
1300 wil_set_recovery_state(wil, fw_recovery_idle);
1301
1302 mutex_lock(&wil->mutex);
1303
1304 __wil_down(wil);
1305 rc = __wil_up(wil);
1306 if (rc)
1307 goto out;
1308
1309 rc = wmi_set_ssid(wil, ssid_len, ssid);
1310 if (rc)
1311 goto out;
1312
cab5abbf 1313 rc = _wil_cfg80211_set_ies(wiphy, bcon);
33190ebf
VK
1314 if (rc)
1315 goto out;
1316
1317 wil->privacy = privacy;
1318 wil->channel = chan;
1319 wil->hidden_ssid = hidden_ssid;
eabb03b4 1320 wil->pbss = pbss;
33190ebf
VK
1321
1322 netif_carrier_on(ndev);
9953a782 1323 wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
33190ebf 1324
b4944f2c 1325 rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
33190ebf
VK
1326 if (rc)
1327 goto err_pcp_start;
1328
1329 rc = wil_bcast_init(wil);
1330 if (rc)
1331 goto err_bcast;
1332
1333 goto out; /* success */
1334
1335err_bcast:
1336 wmi_pcp_stop(wil);
1337err_pcp_start:
1338 netif_carrier_off(ndev);
9953a782 1339 wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
33190ebf
VK
1340out:
1341 mutex_unlock(&wil->mutex);
1342 return rc;
1343}
1344
1bd922fc
VK
1345static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
1346 struct net_device *ndev,
1347 struct cfg80211_beacon_data *bcon)
1348{
1349 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1350 int rc;
33190ebf 1351 u32 privacy = 0;
1bd922fc 1352
af3db60a 1353 wil_dbg_misc(wil, "change_beacon\n");
1e7e5a0d
VK
1354 wil_print_bcon_data(bcon);
1355
c5a157e4
LD
1356 if (bcon->tail &&
1357 cfg80211_find_ie(WLAN_EID_RSN, bcon->tail,
1358 bcon->tail_len))
33190ebf 1359 privacy = 1;
1bd922fc 1360
33190ebf
VK
1361 /* in case privacy has changed, need to restart the AP */
1362 if (wil->privacy != privacy) {
1363 struct wireless_dev *wdev = ndev->ieee80211_ptr;
1364
1365 wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
1366 wil->privacy, privacy);
1367
1368 rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
1369 wdev->ssid_len, privacy,
1370 wdev->beacon_interval,
cab5abbf 1371 wil->channel, bcon,
eabb03b4
LD
1372 wil->hidden_ssid,
1373 wil->pbss);
33190ebf 1374 } else {
cab5abbf 1375 rc = _wil_cfg80211_set_ies(wiphy, bcon);
1bd922fc
VK
1376 }
1377
33190ebf 1378 return rc;
1bd922fc
VK
1379}
1380
2be7d22f
VK
1381static int wil_cfg80211_start_ap(struct wiphy *wiphy,
1382 struct net_device *ndev,
1383 struct cfg80211_ap_settings *info)
1384{
33190ebf 1385 int rc;
2be7d22f 1386 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2be7d22f
VK
1387 struct ieee80211_channel *channel = info->chandef.chan;
1388 struct cfg80211_beacon_data *bcon = &info->beacon;
ca959773 1389 struct cfg80211_crypto_settings *crypto = &info->crypto;
8e52fe30 1390 u8 hidden_ssid;
2be7d22f 1391
af3db60a 1392 wil_dbg_misc(wil, "start_ap\n");
ca959773 1393
2be7d22f
VK
1394 if (!channel) {
1395 wil_err(wil, "AP: No channel???\n");
1396 return -EINVAL;
1397 }
1398
33190ebf
VK
1399 switch (info->hidden_ssid) {
1400 case NL80211_HIDDEN_SSID_NOT_IN_USE:
1401 hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
1402 break;
1403
1404 case NL80211_HIDDEN_SSID_ZERO_LEN:
1405 hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
1406 break;
1407
1408 case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1409 hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
1410 break;
1411
1412 default:
1413 wil_err(wil, "AP: Invalid hidden SSID %d\n", info->hidden_ssid);
1414 return -EOPNOTSUPP;
1415 }
7743882d 1416 wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
2057ebb2 1417 channel->center_freq, info->privacy ? "secure" : "open");
ca959773
VK
1418 wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
1419 info->privacy, info->auth_type);
8e52fe30
HK
1420 wil_dbg_misc(wil, "Hidden SSID mode: %d\n",
1421 info->hidden_ssid);
ca959773
VK
1422 wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
1423 info->dtim_period);
eabb03b4 1424 wil_dbg_misc(wil, "PBSS %d\n", info->pbss);
5eb443e9
DL
1425 wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
1426 info->ssid, info->ssid_len, true);
ca959773
VK
1427 wil_print_bcon_data(bcon);
1428 wil_print_crypto(wil, crypto);
2be7d22f 1429
33190ebf
VK
1430 rc = _wil_cfg80211_start_ap(wiphy, ndev,
1431 info->ssid, info->ssid_len, info->privacy,
1432 info->beacon_interval, channel->hw_value,
eabb03b4 1433 bcon, hidden_ssid, info->pbss);
2be7d22f
VK
1434
1435 return rc;
1436}
1437
1438static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
1439 struct net_device *ndev)
1440{
2be7d22f 1441 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
2be7d22f 1442
af3db60a 1443 wil_dbg_misc(wil, "stop_ap\n");
ca959773 1444
c5e96c91 1445 netif_carrier_off(ndev);
9953a782 1446 wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
c33407a8
VK
1447 wil_set_recovery_state(wil, fw_recovery_idle);
1448
646d402d
HK
1449 set_bit(wil_status_resetting, wil->status);
1450
9c3bde56
VK
1451 mutex_lock(&wil->mutex);
1452
32a20d46 1453 wmi_pcp_stop(wil);
2be7d22f 1454
73d839ae 1455 __wil_down(wil);
73d839ae 1456
9c3bde56 1457 mutex_unlock(&wil->mutex);
73d839ae 1458
32a20d46 1459 return 0;
2be7d22f
VK
1460}
1461
849a564b
DL
1462static int wil_cfg80211_add_station(struct wiphy *wiphy,
1463 struct net_device *dev,
1464 const u8 *mac,
1465 struct station_parameters *params)
1466{
1467 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1468
1469 wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid);
1470
1471 if (!disable_ap_sme) {
1472 wil_err(wil, "not supported with AP SME enabled\n");
1473 return -EOPNOTSUPP;
1474 }
1475
1476 if (params->aid > WIL_MAX_DMG_AID) {
1477 wil_err(wil, "invalid aid\n");
1478 return -EINVAL;
1479 }
1480
1481 return wmi_new_sta(wil, mac, params->aid);
1482}
1483
4d55a0a1 1484static int wil_cfg80211_del_station(struct wiphy *wiphy,
89c771e5
JM
1485 struct net_device *dev,
1486 struct station_del_parameters *params)
4d55a0a1
VK
1487{
1488 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
097638a0 1489
af3db60a 1490 wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac,
de9084ef
VK
1491 params->reason_code);
1492
097638a0 1493 mutex_lock(&wil->mutex);
4821e6d8 1494 wil6210_disconnect(wil, params->mac, params->reason_code, false);
097638a0
VK
1495 mutex_unlock(&wil->mutex);
1496
4d55a0a1
VK
1497 return 0;
1498}
1499
849a564b
DL
1500static int wil_cfg80211_change_station(struct wiphy *wiphy,
1501 struct net_device *dev,
1502 const u8 *mac,
1503 struct station_parameters *params)
1504{
1505 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1506 int authorize;
1507 int cid, i;
1508 struct vring_tx_data *txdata = NULL;
1509
1510 wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac,
1511 params->sta_flags_mask, params->sta_flags_set);
1512
1513 if (!disable_ap_sme) {
1514 wil_dbg_misc(wil, "not supported with AP SME enabled\n");
1515 return -EOPNOTSUPP;
1516 }
1517
1518 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
1519 return 0;
1520
1521 cid = wil_find_cid(wil, mac);
1522 if (cid < 0) {
1523 wil_err(wil, "station not found\n");
1524 return -ENOLINK;
1525 }
1526
1527 for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++)
1528 if (wil->vring2cid_tid[i][0] == cid) {
1529 txdata = &wil->vring_tx_data[i];
1530 break;
1531 }
1532
1533 if (!txdata) {
1534 wil_err(wil, "vring data not found\n");
1535 return -ENOLINK;
1536 }
1537
1538 authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED);
1539 txdata->dot1x_open = authorize ? 1 : 0;
1540 wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i,
1541 txdata->dot1x_open);
1542
1543 return 0;
1544}
1545
40822a90
VK
1546/* probe_client handling */
1547static void wil_probe_client_handle(struct wil6210_priv *wil,
1548 struct wil_probe_client_req *req)
1549{
1550 struct net_device *ndev = wil_to_ndev(wil);
1551 struct wil_sta_info *sta = &wil->sta[req->cid];
1552 /* assume STA is alive if it is still connected,
1553 * else FW will disconnect it
1554 */
1555 bool alive = (sta->status == wil_sta_connected);
1556
1557 cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL);
1558}
1559
1560static struct list_head *next_probe_client(struct wil6210_priv *wil)
1561{
1562 struct list_head *ret = NULL;
1563
1564 mutex_lock(&wil->probe_client_mutex);
1565
1566 if (!list_empty(&wil->probe_client_pending)) {
1567 ret = wil->probe_client_pending.next;
1568 list_del(ret);
1569 }
1570
1571 mutex_unlock(&wil->probe_client_mutex);
1572
1573 return ret;
1574}
1575
1576void wil_probe_client_worker(struct work_struct *work)
1577{
1578 struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1579 probe_client_worker);
1580 struct wil_probe_client_req *req;
1581 struct list_head *lh;
1582
1583 while ((lh = next_probe_client(wil)) != NULL) {
1584 req = list_entry(lh, struct wil_probe_client_req, list);
1585
1586 wil_probe_client_handle(wil, req);
1587 kfree(req);
1588 }
1589}
1590
1591void wil_probe_client_flush(struct wil6210_priv *wil)
1592{
1593 struct wil_probe_client_req *req, *t;
1594
af3db60a 1595 wil_dbg_misc(wil, "probe_client_flush\n");
40822a90
VK
1596
1597 mutex_lock(&wil->probe_client_mutex);
1598
1599 list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) {
1600 list_del(&req->list);
1601 kfree(req);
1602 }
1603
1604 mutex_unlock(&wil->probe_client_mutex);
1605}
1606
1607static int wil_cfg80211_probe_client(struct wiphy *wiphy,
1608 struct net_device *dev,
1609 const u8 *peer, u64 *cookie)
1610{
1611 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1612 struct wil_probe_client_req *req;
1613 int cid = wil_find_cid(wil, peer);
1614
af3db60a 1615 wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid);
40822a90
VK
1616
1617 if (cid < 0)
1618 return -ENOLINK;
1619
1620 req = kzalloc(sizeof(*req), GFP_KERNEL);
1621 if (!req)
1622 return -ENOMEM;
1623
1624 req->cid = cid;
1625 req->cookie = cid;
1626
1627 mutex_lock(&wil->probe_client_mutex);
1628 list_add_tail(&req->list, &wil->probe_client_pending);
1629 mutex_unlock(&wil->probe_client_mutex);
1630
1631 *cookie = req->cookie;
1632 queue_work(wil->wq_service, &wil->probe_client_worker);
1633 return 0;
1634}
1635
02beaf1a
VK
1636static int wil_cfg80211_change_bss(struct wiphy *wiphy,
1637 struct net_device *dev,
1638 struct bss_parameters *params)
1639{
1640 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1641
1642 if (params->ap_isolate >= 0) {
af3db60a 1643 wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n",
02beaf1a
VK
1644 wil->ap_isolate, params->ap_isolate);
1645 wil->ap_isolate = params->ap_isolate;
1646 }
1647
1648 return 0;
1649}
1650
4332cac1
LD
1651static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
1652 struct wireless_dev *wdev)
1653{
1654 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1655
af3db60a 1656 wil_dbg_misc(wil, "start_p2p_device: entered\n");
eb57a5b3 1657 wil->p2p.p2p_dev_started = 1;
4332cac1
LD
1658 return 0;
1659}
1660
1661static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
1662 struct wireless_dev *wdev)
1663{
1664 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
d35c2b6f
ME
1665 struct wil_p2p_info *p2p = &wil->p2p;
1666
1667 if (!p2p->p2p_dev_started)
1668 return;
4332cac1 1669
af3db60a 1670 wil_dbg_misc(wil, "stop_p2p_device: entered\n");
eb57a5b3 1671 mutex_lock(&wil->mutex);
035859a5 1672 mutex_lock(&wil->p2p_wdev_mutex);
d35c2b6f
ME
1673 wil_p2p_stop_radio_operations(wil);
1674 p2p->p2p_dev_started = 0;
035859a5 1675 mutex_unlock(&wil->p2p_wdev_mutex);
eb57a5b3 1676 mutex_unlock(&wil->mutex);
4332cac1
LD
1677}
1678
2c207eb8
ME
1679static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1680 struct net_device *dev,
1681 bool enabled, int timeout)
1682{
1683 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1684 enum wmi_ps_profile_type ps_profile;
2c207eb8
ME
1685
1686 wil_dbg_misc(wil, "enabled=%d, timeout=%d\n",
1687 enabled, timeout);
1688
1689 if (enabled)
1690 ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
1691 else
1692 ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED;
1693
8b068c03 1694 return wil_ps_update(wil, ps_profile);
2c207eb8
ME
1695}
1696
fe9ee51e
ME
1697static int wil_cfg80211_suspend(struct wiphy *wiphy,
1698 struct cfg80211_wowlan *wow)
1699{
1700 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1701 int rc;
1702
1703 /* Setting the wakeup trigger based on wow is TBD */
1704
1705 if (test_bit(wil_status_suspended, wil->status)) {
1706 wil_dbg_pm(wil, "trying to suspend while suspended\n");
1707 return 0;
1708 }
1709
1710 rc = wil_can_suspend(wil, false);
1711 if (rc)
1712 goto out;
1713
1714 wil_dbg_pm(wil, "suspending\n");
1715
1716 wil_p2p_stop_discovery(wil);
1717
1718 wil_abort_scan(wil, true);
1719
1720out:
1721 return rc;
1722}
1723
1724static int wil_cfg80211_resume(struct wiphy *wiphy)
1725{
1726 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1727
1728 wil_dbg_pm(wil, "resuming\n");
1729
1730 return 0;
1731}
1732
b59eb961 1733static const struct cfg80211_ops wil_cfg80211_ops = {
4332cac1
LD
1734 .add_virtual_intf = wil_cfg80211_add_iface,
1735 .del_virtual_intf = wil_cfg80211_del_iface,
2be7d22f 1736 .scan = wil_cfg80211_scan,
035859a5 1737 .abort_scan = wil_cfg80211_abort_scan,
2be7d22f
VK
1738 .connect = wil_cfg80211_connect,
1739 .disconnect = wil_cfg80211_disconnect,
3fea18d0 1740 .set_wiphy_params = wil_cfg80211_set_wiphy_params,
2be7d22f
VK
1741 .change_virtual_intf = wil_cfg80211_change_iface,
1742 .get_station = wil_cfg80211_get_station,
ef28afdb 1743 .dump_station = wil_cfg80211_dump_station,
1647f12f
VK
1744 .remain_on_channel = wil_remain_on_channel,
1745 .cancel_remain_on_channel = wil_cancel_remain_on_channel,
1746 .mgmt_tx = wil_cfg80211_mgmt_tx,
2be7d22f
VK
1747 .set_monitor_channel = wil_cfg80211_set_channel,
1748 .add_key = wil_cfg80211_add_key,
1749 .del_key = wil_cfg80211_del_key,
1750 .set_default_key = wil_cfg80211_set_default_key,
1751 /* AP mode */
1bd922fc 1752 .change_beacon = wil_cfg80211_change_beacon,
2be7d22f
VK
1753 .start_ap = wil_cfg80211_start_ap,
1754 .stop_ap = wil_cfg80211_stop_ap,
849a564b 1755 .add_station = wil_cfg80211_add_station,
4d55a0a1 1756 .del_station = wil_cfg80211_del_station,
849a564b 1757 .change_station = wil_cfg80211_change_station,
40822a90 1758 .probe_client = wil_cfg80211_probe_client,
02beaf1a 1759 .change_bss = wil_cfg80211_change_bss,
4332cac1
LD
1760 /* P2P device */
1761 .start_p2p_device = wil_cfg80211_start_p2p_device,
1762 .stop_p2p_device = wil_cfg80211_stop_p2p_device,
2c207eb8 1763 .set_power_mgmt = wil_cfg80211_set_power_mgmt,
fe9ee51e
ME
1764 .suspend = wil_cfg80211_suspend,
1765 .resume = wil_cfg80211_resume,
2be7d22f
VK
1766};
1767
1768static void wil_wiphy_init(struct wiphy *wiphy)
1769{
8e52fe30 1770 wiphy->max_scan_ssids = 1;
77c91295 1771 wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
e6d68341 1772 wiphy->max_remain_on_channel_duration = WIL_MAX_ROC_DURATION_MS;
2be7d22f
VK
1773 wiphy->max_num_pmkids = 0 /* TODO: */;
1774 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1775 BIT(NL80211_IFTYPE_AP) |
e6d68341
DL
1776 BIT(NL80211_IFTYPE_P2P_CLIENT) |
1777 BIT(NL80211_IFTYPE_P2P_GO) |
4332cac1 1778 BIT(NL80211_IFTYPE_P2P_DEVICE) |
2be7d22f 1779 BIT(NL80211_IFTYPE_MONITOR);
849a564b 1780 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
2c207eb8
ME
1781 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
1782 WIPHY_FLAG_PS_ON_BY_DEFAULT;
849a564b
DL
1783 if (!disable_ap_sme)
1784 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
9cf10d62
VK
1785 dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
1786 __func__, wiphy->flags);
2be7d22f
VK
1787 wiphy->probe_resp_offload =
1788 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
1789 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
1790 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
1791
57fbcce3 1792 wiphy->bands[NL80211_BAND_60GHZ] = &wil_band_60ghz;
2be7d22f
VK
1793
1794 /* TODO: figure this out */
b8b33a3a 1795 wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
2be7d22f
VK
1796
1797 wiphy->cipher_suites = wil_cipher_suites;
1798 wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
1799 wiphy->mgmt_stypes = wil_mgmt_stypes;
713c8a29 1800 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
0216a895
LD
1801
1802 wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
1803 wiphy->vendor_commands = wil_nl80211_vendor_commands;
2be7d22f
VK
1804}
1805
1806struct wireless_dev *wil_cfg80211_init(struct device *dev)
1807{
1808 int rc = 0;
1809 struct wireless_dev *wdev;
1810
9cf10d62
VK
1811 dev_dbg(dev, "%s()\n", __func__);
1812
8fe59627 1813 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2be7d22f
VK
1814 if (!wdev)
1815 return ERR_PTR(-ENOMEM);
1816
1817 wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
1818 sizeof(struct wil6210_priv));
1819 if (!wdev->wiphy) {
1820 rc = -ENOMEM;
1821 goto out;
1822 }
1823
1824 set_wiphy_dev(wdev->wiphy, dev);
1825 wil_wiphy_init(wdev->wiphy);
1826
2be7d22f
VK
1827 return wdev;
1828
2be7d22f
VK
1829out:
1830 kfree(wdev);
1831
1832 return ERR_PTR(rc);
1833}
1834
1835void wil_wdev_free(struct wil6210_priv *wil)
1836{
1837 struct wireless_dev *wdev = wil_to_wdev(wil);
1838
9cf10d62
VK
1839 dev_dbg(wil_to_dev(wil), "%s()\n", __func__);
1840
2be7d22f
VK
1841 if (!wdev)
1842 return;
1843
2be7d22f
VK
1844 wiphy_free(wdev->wiphy);
1845 kfree(wdev);
1846}
4332cac1
LD
1847
1848void wil_p2p_wdev_free(struct wil6210_priv *wil)
1849{
1850 struct wireless_dev *p2p_wdev;
1851
1852 mutex_lock(&wil->p2p_wdev_mutex);
1853 p2p_wdev = wil->p2p_wdev;
d35c2b6f
ME
1854 wil->p2p_wdev = NULL;
1855 wil->radio_wdev = wil_to_wdev(wil);
1856 mutex_unlock(&wil->p2p_wdev_mutex);
4332cac1 1857 if (p2p_wdev) {
4332cac1
LD
1858 cfg80211_unregister_wdev(p2p_wdev);
1859 kfree(p2p_wdev);
1860 }
4332cac1 1861}
0216a895
LD
1862
1863static int wil_rf_sector_status_to_rc(u8 status)
1864{
1865 switch (status) {
1866 case WMI_RF_SECTOR_STATUS_SUCCESS:
1867 return 0;
1868 case WMI_RF_SECTOR_STATUS_BAD_PARAMETERS_ERROR:
1869 return -EINVAL;
1870 case WMI_RF_SECTOR_STATUS_BUSY_ERROR:
1871 return -EAGAIN;
1872 case WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR:
1873 return -EOPNOTSUPP;
1874 default:
1875 return -EINVAL;
1876 }
1877}
1878
1879static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
1880 struct wireless_dev *wdev,
1881 const void *data, int data_len)
1882{
1883 struct wil6210_priv *wil = wdev_to_wil(wdev);
1884 int rc;
1885 struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
1886 u16 sector_index;
1887 u8 sector_type;
1888 u32 rf_modules_vec;
1889 struct wmi_get_rf_sector_params_cmd cmd;
1890 struct {
1891 struct wmi_cmd_hdr wmi;
1892 struct wmi_get_rf_sector_params_done_event evt;
1893 } __packed reply;
1894 struct sk_buff *msg;
1895 struct nlattr *nl_cfgs, *nl_cfg;
1896 u32 i;
1897 struct wmi_rf_sector_info *si;
1898
1899 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
1900 return -EOPNOTSUPP;
1901
1902 rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
1903 wil_rf_sector_policy, NULL);
1904 if (rc) {
1905 wil_err(wil, "Invalid rf sector ATTR\n");
1906 return rc;
1907 }
1908
1909 if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
1910 !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
1911 !tb[QCA_ATTR_DMG_RF_MODULE_MASK]) {
1912 wil_err(wil, "Invalid rf sector spec\n");
1913 return -EINVAL;
1914 }
1915
1916 sector_index = nla_get_u16(
1917 tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
1918 if (sector_index >= WIL_MAX_RF_SECTORS) {
1919 wil_err(wil, "Invalid sector index %d\n", sector_index);
1920 return -EINVAL;
1921 }
1922
1923 sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
1924 if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
1925 wil_err(wil, "Invalid sector type %d\n", sector_type);
1926 return -EINVAL;
1927 }
1928
1929 rf_modules_vec = nla_get_u32(
1930 tb[QCA_ATTR_DMG_RF_MODULE_MASK]);
1931 if (rf_modules_vec >= BIT(WMI_MAX_RF_MODULES_NUM)) {
1932 wil_err(wil, "Invalid rf module mask 0x%x\n", rf_modules_vec);
1933 return -EINVAL;
1934 }
1935
1936 cmd.sector_idx = cpu_to_le16(sector_index);
1937 cmd.sector_type = sector_type;
1938 cmd.rf_modules_vec = rf_modules_vec & 0xFF;
1939 memset(&reply, 0, sizeof(reply));
1940 rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
1941 WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
1942 &reply, sizeof(reply),
1943 500);
1944 if (rc)
1945 return rc;
1946 if (reply.evt.status) {
1947 wil_err(wil, "get rf sector cfg failed with status %d\n",
1948 reply.evt.status);
1949 return wil_rf_sector_status_to_rc(reply.evt.status);
1950 }
1951
1952 msg = cfg80211_vendor_cmd_alloc_reply_skb(
1953 wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
1954 if (!msg)
1955 return -ENOMEM;
1956
1957 if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
1958 le64_to_cpu(reply.evt.tsf),
1959 QCA_ATTR_PAD))
1960 goto nla_put_failure;
1961
1962 nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG);
1963 if (!nl_cfgs)
1964 goto nla_put_failure;
1965 for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) {
1966 if (!(rf_modules_vec & BIT(i)))
1967 continue;
1968 nl_cfg = nla_nest_start(msg, i);
1969 if (!nl_cfg)
1970 goto nla_put_failure;
1971 si = &reply.evt.sectors_info[i];
1972 if (nla_put_u8(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX,
1973 i) ||
1974 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0,
1975 le32_to_cpu(si->etype0)) ||
1976 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1,
1977 le32_to_cpu(si->etype1)) ||
1978 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2,
1979 le32_to_cpu(si->etype2)) ||
1980 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI,
1981 le32_to_cpu(si->psh_hi)) ||
1982 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO,
1983 le32_to_cpu(si->psh_lo)) ||
1984 nla_put_u32(msg, QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16,
1985 le32_to_cpu(si->dtype_swch_off)))
1986 goto nla_put_failure;
1987 nla_nest_end(msg, nl_cfg);
1988 }
1989
1990 nla_nest_end(msg, nl_cfgs);
1991 rc = cfg80211_vendor_cmd_reply(msg);
1992 return rc;
1993nla_put_failure:
1994 kfree_skb(msg);
1995 return -ENOBUFS;
1996}
1997
1998static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
1999 struct wireless_dev *wdev,
2000 const void *data, int data_len)
2001{
2002 struct wil6210_priv *wil = wdev_to_wil(wdev);
2003 int rc, tmp;
2004 struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2005 struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1];
2006 u16 sector_index, rf_module_index;
2007 u8 sector_type;
2008 u32 rf_modules_vec = 0;
2009 struct wmi_set_rf_sector_params_cmd cmd;
2010 struct {
2011 struct wmi_cmd_hdr wmi;
2012 struct wmi_set_rf_sector_params_done_event evt;
2013 } __packed reply;
2014 struct nlattr *nl_cfg;
2015 struct wmi_rf_sector_info *si;
2016
2017 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2018 return -EOPNOTSUPP;
2019
2020 rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2021 wil_rf_sector_policy, NULL);
2022 if (rc) {
2023 wil_err(wil, "Invalid rf sector ATTR\n");
2024 return rc;
2025 }
2026
2027 if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
2028 !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE] ||
2029 !tb[QCA_ATTR_DMG_RF_SECTOR_CFG]) {
2030 wil_err(wil, "Invalid rf sector spec\n");
2031 return -EINVAL;
2032 }
2033
2034 sector_index = nla_get_u16(
2035 tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
2036 if (sector_index >= WIL_MAX_RF_SECTORS) {
2037 wil_err(wil, "Invalid sector index %d\n", sector_index);
2038 return -EINVAL;
2039 }
2040
2041 sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2042 if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2043 wil_err(wil, "Invalid sector type %d\n", sector_type);
2044 return -EINVAL;
2045 }
2046
2047 memset(&cmd, 0, sizeof(cmd));
2048
2049 cmd.sector_idx = cpu_to_le16(sector_index);
2050 cmd.sector_type = sector_type;
2051 nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG],
2052 tmp) {
2053 rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX,
2054 nl_cfg, wil_rf_sector_cfg_policy,
2055 NULL);
2056 if (rc) {
2057 wil_err(wil, "invalid sector cfg\n");
2058 return -EINVAL;
2059 }
2060
2061 if (!tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX] ||
2062 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0] ||
2063 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1] ||
2064 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2] ||
2065 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI] ||
2066 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO] ||
2067 !tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]) {
2068 wil_err(wil, "missing cfg params\n");
2069 return -EINVAL;
2070 }
2071
2072 rf_module_index = nla_get_u8(
2073 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX]);
2074 if (rf_module_index >= WMI_MAX_RF_MODULES_NUM) {
2075 wil_err(wil, "invalid RF module index %d\n",
2076 rf_module_index);
2077 return -EINVAL;
2078 }
2079 rf_modules_vec |= BIT(rf_module_index);
2080 si = &cmd.sectors_info[rf_module_index];
2081 si->etype0 = cpu_to_le32(nla_get_u32(
2082 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE0]));
2083 si->etype1 = cpu_to_le32(nla_get_u32(
2084 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE1]));
2085 si->etype2 = cpu_to_le32(nla_get_u32(
2086 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_ETYPE2]));
2087 si->psh_hi = cpu_to_le32(nla_get_u32(
2088 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_HI]));
2089 si->psh_lo = cpu_to_le32(nla_get_u32(
2090 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_PSH_LO]));
2091 si->dtype_swch_off = cpu_to_le32(nla_get_u32(
2092 tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16]));
2093 }
2094
2095 cmd.rf_modules_vec = rf_modules_vec & 0xFF;
2096 memset(&reply, 0, sizeof(reply));
2097 rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
2098 WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
2099 &reply, sizeof(reply),
2100 500);
2101 if (rc)
2102 return rc;
2103 return wil_rf_sector_status_to_rc(reply.evt.status);
2104}
2105
2106static int wil_rf_sector_get_selected(struct wiphy *wiphy,
2107 struct wireless_dev *wdev,
2108 const void *data, int data_len)
2109{
2110 struct wil6210_priv *wil = wdev_to_wil(wdev);
2111 int rc;
2112 struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2113 u8 sector_type, mac_addr[ETH_ALEN];
2114 int cid = 0;
2115 struct wmi_get_selected_rf_sector_index_cmd cmd;
2116 struct {
2117 struct wmi_cmd_hdr wmi;
2118 struct wmi_get_selected_rf_sector_index_done_event evt;
2119 } __packed reply;
2120 struct sk_buff *msg;
2121
2122 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2123 return -EOPNOTSUPP;
2124
2125 rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2126 wil_rf_sector_policy, NULL);
2127 if (rc) {
2128 wil_err(wil, "Invalid rf sector ATTR\n");
2129 return rc;
2130 }
2131
2132 if (!tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
2133 wil_err(wil, "Invalid rf sector spec\n");
2134 return -EINVAL;
2135 }
2136 sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2137 if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2138 wil_err(wil, "Invalid sector type %d\n", sector_type);
2139 return -EINVAL;
2140 }
2141
2142 if (tb[QCA_ATTR_MAC_ADDR]) {
2143 ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
2144 cid = wil_find_cid(wil, mac_addr);
2145 if (cid < 0) {
2146 wil_err(wil, "invalid MAC address %pM\n", mac_addr);
2147 return -ENOENT;
2148 }
2149 } else {
2150 if (test_bit(wil_status_fwconnected, wil->status)) {
2151 wil_err(wil, "must specify MAC address when connected\n");
2152 return -EINVAL;
2153 }
2154 }
2155
2156 memset(&cmd, 0, sizeof(cmd));
2157 cmd.cid = (u8)cid;
2158 cmd.sector_type = sector_type;
2159 memset(&reply, 0, sizeof(reply));
2160 rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID,
2161 &cmd, sizeof(cmd),
2162 WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
2163 &reply, sizeof(reply),
2164 500);
2165 if (rc)
2166 return rc;
2167 if (reply.evt.status) {
2168 wil_err(wil, "get rf selected sector cfg failed with status %d\n",
2169 reply.evt.status);
2170 return wil_rf_sector_status_to_rc(reply.evt.status);
2171 }
2172
2173 msg = cfg80211_vendor_cmd_alloc_reply_skb(
2174 wiphy, 64 * WMI_MAX_RF_MODULES_NUM);
2175 if (!msg)
2176 return -ENOMEM;
2177
2178 if (nla_put_u64_64bit(msg, QCA_ATTR_TSF,
2179 le64_to_cpu(reply.evt.tsf),
2180 QCA_ATTR_PAD) ||
2181 nla_put_u16(msg, QCA_ATTR_DMG_RF_SECTOR_INDEX,
2182 le16_to_cpu(reply.evt.sector_idx)))
2183 goto nla_put_failure;
2184
2185 rc = cfg80211_vendor_cmd_reply(msg);
2186 return rc;
2187nla_put_failure:
2188 kfree_skb(msg);
2189 return -ENOBUFS;
2190}
2191
2192static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
2193 u16 sector_index,
2194 u8 sector_type, u8 cid)
2195{
2196 struct wmi_set_selected_rf_sector_index_cmd cmd;
2197 struct {
2198 struct wmi_cmd_hdr wmi;
2199 struct wmi_set_selected_rf_sector_index_done_event evt;
2200 } __packed reply;
2201 int rc;
2202
2203 memset(&cmd, 0, sizeof(cmd));
2204 cmd.sector_idx = cpu_to_le16(sector_index);
2205 cmd.sector_type = sector_type;
2206 cmd.cid = (u8)cid;
2207 memset(&reply, 0, sizeof(reply));
2208 rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID,
2209 &cmd, sizeof(cmd),
2210 WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
2211 &reply, sizeof(reply),
2212 500);
2213 if (rc)
2214 return rc;
2215 return wil_rf_sector_status_to_rc(reply.evt.status);
2216}
2217
2218static int wil_rf_sector_set_selected(struct wiphy *wiphy,
2219 struct wireless_dev *wdev,
2220 const void *data, int data_len)
2221{
2222 struct wil6210_priv *wil = wdev_to_wil(wdev);
2223 int rc;
2224 struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
2225 u16 sector_index;
2226 u8 sector_type, mac_addr[ETH_ALEN], i;
2227 int cid = 0;
2228
2229 if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities))
2230 return -EOPNOTSUPP;
2231
2232 rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len,
2233 wil_rf_sector_policy, NULL);
2234 if (rc) {
2235 wil_err(wil, "Invalid rf sector ATTR\n");
2236 return rc;
2237 }
2238
2239 if (!tb[QCA_ATTR_DMG_RF_SECTOR_INDEX] ||
2240 !tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]) {
2241 wil_err(wil, "Invalid rf sector spec\n");
2242 return -EINVAL;
2243 }
2244
2245 sector_index = nla_get_u16(
2246 tb[QCA_ATTR_DMG_RF_SECTOR_INDEX]);
2247 if (sector_index >= WIL_MAX_RF_SECTORS &&
2248 sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
2249 wil_err(wil, "Invalid sector index %d\n", sector_index);
2250 return -EINVAL;
2251 }
2252
2253 sector_type = nla_get_u8(tb[QCA_ATTR_DMG_RF_SECTOR_TYPE]);
2254 if (sector_type >= QCA_ATTR_DMG_RF_SECTOR_TYPE_MAX) {
2255 wil_err(wil, "Invalid sector type %d\n", sector_type);
2256 return -EINVAL;
2257 }
2258
2259 if (tb[QCA_ATTR_MAC_ADDR]) {
2260 ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
2261 if (!is_broadcast_ether_addr(mac_addr)) {
2262 cid = wil_find_cid(wil, mac_addr);
2263 if (cid < 0) {
2264 wil_err(wil, "invalid MAC address %pM\n",
2265 mac_addr);
2266 return -ENOENT;
2267 }
2268 } else {
2269 if (sector_index != WMI_INVALID_RF_SECTOR_INDEX) {
2270 wil_err(wil, "broadcast MAC valid only with unlocking\n");
2271 return -EINVAL;
2272 }
2273 cid = -1;
2274 }
2275 } else {
2276 if (test_bit(wil_status_fwconnected, wil->status)) {
2277 wil_err(wil, "must specify MAC address when connected\n");
2278 return -EINVAL;
2279 }
2280 /* otherwise, using cid=0 for unassociated station */
2281 }
2282
2283 if (cid >= 0) {
2284 rc = wil_rf_sector_wmi_set_selected(wil, sector_index,
2285 sector_type, cid);
2286 } else {
2287 /* unlock all cids */
2288 rc = wil_rf_sector_wmi_set_selected(
2289 wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type,
2290 WIL_CID_ALL);
2291 if (rc == -EINVAL) {
2292 for (i = 0; i < WIL6210_MAX_CID; i++) {
2293 rc = wil_rf_sector_wmi_set_selected(
2294 wil, WMI_INVALID_RF_SECTOR_INDEX,
2295 sector_type, i);
2296 /* the FW will silently ignore and return
2297 * success for unused cid, so abort the loop
2298 * on any other error
2299 */
2300 if (rc) {
2301 wil_err(wil, "unlock cid %d failed with status %d\n",
2302 i, rc);
2303 break;
2304 }
2305 }
2306 }
2307 }
2308
2309 return rc;
2310}