xref: /openbmc/linux/drivers/net/wireless/ath/wil6210/cfg80211.c (revision 74997a53d257e327699e359b78b3ecfd33f80cab)
1 /*
2  * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
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 
17 #include <linux/etherdevice.h>
18 #include "wil6210.h"
19 #include "wmi.h"
20 
21 #define CHAN60G(_channel, _flags) {				\
22 	.band			= IEEE80211_BAND_60GHZ,		\
23 	.center_freq		= 56160 + (2160 * (_channel)),	\
24 	.hw_value		= (_channel),			\
25 	.flags			= (_flags),			\
26 	.max_antenna_gain	= 0,				\
27 	.max_power		= 40,				\
28 }
29 
30 static struct ieee80211_channel wil_60ghz_channels[] = {
31 	CHAN60G(1, 0),
32 	CHAN60G(2, 0),
33 	CHAN60G(3, 0),
34 /* channel 4 not supported yet */
35 };
36 
37 static struct ieee80211_supported_band wil_band_60ghz = {
38 	.channels = wil_60ghz_channels,
39 	.n_channels = ARRAY_SIZE(wil_60ghz_channels),
40 	.ht_cap = {
41 		.ht_supported = true,
42 		.cap = 0, /* TODO */
43 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */
44 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */
45 		.mcs = {
46 				/* MCS 1..12 - SC PHY */
47 			.rx_mask = {0xfe, 0x1f}, /* 1..12 */
48 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */
49 		},
50 	},
51 };
52 
53 static const struct ieee80211_txrx_stypes
54 wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
55 	[NL80211_IFTYPE_STATION] = {
56 		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
57 		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
58 		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
59 		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
60 	},
61 	[NL80211_IFTYPE_AP] = {
62 		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
63 		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
64 		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
65 		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
66 	},
67 	[NL80211_IFTYPE_P2P_CLIENT] = {
68 		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
69 		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
70 		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
71 		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
72 	},
73 	[NL80211_IFTYPE_P2P_GO] = {
74 		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
75 		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
76 		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
77 		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
78 	},
79 };
80 
81 static const u32 wil_cipher_suites[] = {
82 	WLAN_CIPHER_SUITE_GCMP,
83 };
84 
85 static const char * const key_usage_str[] = {
86 	[WMI_KEY_USE_PAIRWISE]	= "PTK",
87 	[WMI_KEY_USE_RX_GROUP]	= "RX_GTK",
88 	[WMI_KEY_USE_TX_GROUP]	= "TX_GTK",
89 };
90 
91 int wil_iftype_nl2wmi(enum nl80211_iftype type)
92 {
93 	static const struct {
94 		enum nl80211_iftype nl;
95 		enum wmi_network_type wmi;
96 	} __nl2wmi[] = {
97 		{NL80211_IFTYPE_ADHOC,		WMI_NETTYPE_ADHOC},
98 		{NL80211_IFTYPE_STATION,	WMI_NETTYPE_INFRA},
99 		{NL80211_IFTYPE_AP,		WMI_NETTYPE_AP},
100 		{NL80211_IFTYPE_P2P_CLIENT,	WMI_NETTYPE_P2P},
101 		{NL80211_IFTYPE_P2P_GO,		WMI_NETTYPE_P2P},
102 		{NL80211_IFTYPE_MONITOR,	WMI_NETTYPE_ADHOC}, /* FIXME */
103 	};
104 	uint i;
105 
106 	for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) {
107 		if (__nl2wmi[i].nl == type)
108 			return __nl2wmi[i].wmi;
109 	}
110 
111 	return -EOPNOTSUPP;
112 }
113 
114 int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
115 		       struct station_info *sinfo)
116 {
117 	struct wmi_notify_req_cmd cmd = {
118 		.cid = cid,
119 		.interval_usec = 0,
120 	};
121 	struct {
122 		struct wil6210_mbox_hdr_wmi wmi;
123 		struct wmi_notify_req_done_event evt;
124 	} __packed reply;
125 	struct wil_net_stats *stats = &wil->sta[cid].stats;
126 	int rc;
127 
128 	rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
129 		      WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
130 	if (rc)
131 		return rc;
132 
133 	wil_dbg_wmi(wil, "Link status for CID %d: {\n"
134 		    "  MCS %d TSF 0x%016llx\n"
135 		    "  BF status 0x%08x SNR 0x%08x SQI %d%%\n"
136 		    "  Tx Tpt %d goodput %d Rx goodput %d\n"
137 		    "  Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
138 		    cid, le16_to_cpu(reply.evt.bf_mcs),
139 		    le64_to_cpu(reply.evt.tsf), reply.evt.status,
140 		    le32_to_cpu(reply.evt.snr_val),
141 		    reply.evt.sqi,
142 		    le32_to_cpu(reply.evt.tx_tpt),
143 		    le32_to_cpu(reply.evt.tx_goodput),
144 		    le32_to_cpu(reply.evt.rx_goodput),
145 		    le16_to_cpu(reply.evt.my_rx_sector),
146 		    le16_to_cpu(reply.evt.my_tx_sector),
147 		    le16_to_cpu(reply.evt.other_rx_sector),
148 		    le16_to_cpu(reply.evt.other_tx_sector));
149 
150 	sinfo->generation = wil->sinfo_gen;
151 
152 	sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) |
153 			BIT(NL80211_STA_INFO_TX_BYTES) |
154 			BIT(NL80211_STA_INFO_RX_PACKETS) |
155 			BIT(NL80211_STA_INFO_TX_PACKETS) |
156 			BIT(NL80211_STA_INFO_RX_BITRATE) |
157 			BIT(NL80211_STA_INFO_TX_BITRATE) |
158 			BIT(NL80211_STA_INFO_RX_DROP_MISC) |
159 			BIT(NL80211_STA_INFO_TX_FAILED);
160 
161 	sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
162 	sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
163 	sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
164 	sinfo->rxrate.mcs = stats->last_mcs_rx;
165 	sinfo->rx_bytes = stats->rx_bytes;
166 	sinfo->rx_packets = stats->rx_packets;
167 	sinfo->rx_dropped_misc = stats->rx_dropped;
168 	sinfo->tx_bytes = stats->tx_bytes;
169 	sinfo->tx_packets = stats->tx_packets;
170 	sinfo->tx_failed = stats->tx_errors;
171 
172 	if (test_bit(wil_status_fwconnected, wil->status)) {
173 		sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
174 		sinfo->signal = reply.evt.sqi;
175 	}
176 
177 	return rc;
178 }
179 
180 static int wil_cfg80211_get_station(struct wiphy *wiphy,
181 				    struct net_device *ndev,
182 				    const u8 *mac, struct station_info *sinfo)
183 {
184 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
185 	int rc;
186 
187 	int cid = wil_find_cid(wil, mac);
188 
189 	wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid);
190 	if (cid < 0)
191 		return cid;
192 
193 	rc = wil_cid_fill_sinfo(wil, cid, sinfo);
194 
195 	return rc;
196 }
197 
198 /*
199  * Find @idx-th active STA for station dump.
200  */
201 static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx)
202 {
203 	int i;
204 
205 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
206 		if (wil->sta[i].status == wil_sta_unused)
207 			continue;
208 		if (idx == 0)
209 			return i;
210 		idx--;
211 	}
212 
213 	return -ENOENT;
214 }
215 
216 static int wil_cfg80211_dump_station(struct wiphy *wiphy,
217 				     struct net_device *dev, int idx,
218 				     u8 *mac, struct station_info *sinfo)
219 {
220 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
221 	int rc;
222 	int cid = wil_find_cid_by_idx(wil, idx);
223 
224 	if (cid < 0)
225 		return -ENOENT;
226 
227 	ether_addr_copy(mac, wil->sta[cid].addr);
228 	wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid);
229 
230 	rc = wil_cid_fill_sinfo(wil, cid, sinfo);
231 
232 	return rc;
233 }
234 
235 static int wil_cfg80211_change_iface(struct wiphy *wiphy,
236 				     struct net_device *ndev,
237 				     enum nl80211_iftype type, u32 *flags,
238 				     struct vif_params *params)
239 {
240 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
241 	struct wireless_dev *wdev = wil->wdev;
242 
243 	switch (type) {
244 	case NL80211_IFTYPE_STATION:
245 	case NL80211_IFTYPE_AP:
246 	case NL80211_IFTYPE_P2P_CLIENT:
247 	case NL80211_IFTYPE_P2P_GO:
248 		break;
249 	case NL80211_IFTYPE_MONITOR:
250 		if (flags)
251 			wil->monitor_flags = *flags;
252 		else
253 			wil->monitor_flags = 0;
254 
255 		break;
256 	default:
257 		return -EOPNOTSUPP;
258 	}
259 
260 	wdev->iftype = type;
261 
262 	return 0;
263 }
264 
265 static int wil_cfg80211_scan(struct wiphy *wiphy,
266 			     struct cfg80211_scan_request *request)
267 {
268 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
269 	struct wireless_dev *wdev = wil->wdev;
270 	struct {
271 		struct wmi_start_scan_cmd cmd;
272 		u16 chnl[4];
273 	} __packed cmd;
274 	uint i, n;
275 	int rc;
276 
277 	if (wil->scan_request) {
278 		wil_err(wil, "Already scanning\n");
279 		return -EAGAIN;
280 	}
281 
282 	/* check we are client side */
283 	switch (wdev->iftype) {
284 	case NL80211_IFTYPE_STATION:
285 	case NL80211_IFTYPE_P2P_CLIENT:
286 		break;
287 	default:
288 		return -EOPNOTSUPP;
289 	}
290 
291 	/* FW don't support scan after connection attempt */
292 	if (test_bit(wil_status_dontscan, wil->status)) {
293 		wil_err(wil, "Can't scan now\n");
294 		return -EBUSY;
295 	}
296 
297 	wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
298 	wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
299 
300 	for (i = 0; i < request->n_ssids; i++) {
301 		wil_dbg_misc(wil, "SSID[%d]", i);
302 		print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
303 				     request->ssids[i].ssid,
304 				     request->ssids[i].ssid_len);
305 	}
306 
307 	if (request->n_ssids)
308 		rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
309 				  request->ssids[0].ssid);
310 	else
311 		rc = wmi_set_ssid(wil, 0, NULL);
312 
313 	if (rc) {
314 		wil_err(wil, "set SSID for scan request failed: %d\n", rc);
315 		return rc;
316 	}
317 
318 	wil->scan_request = request;
319 	mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
320 
321 	memset(&cmd, 0, sizeof(cmd));
322 	cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
323 	cmd.cmd.num_channels = 0;
324 	n = min(request->n_channels, 4U);
325 	for (i = 0; i < n; i++) {
326 		int ch = request->channels[i]->hw_value;
327 
328 		if (ch == 0) {
329 			wil_err(wil,
330 				"Scan requested for unknown frequency %dMhz\n",
331 				request->channels[i]->center_freq);
332 			continue;
333 		}
334 		/* 0-based channel indexes */
335 		cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
336 		wil_dbg_misc(wil, "Scan for ch %d  : %d MHz\n", ch,
337 			     request->channels[i]->center_freq);
338 	}
339 
340 	if (request->ie_len)
341 		print_hex_dump_bytes("Scan IE ", DUMP_PREFIX_OFFSET,
342 				     request->ie, request->ie_len);
343 	else
344 		wil_dbg_misc(wil, "Scan has no IE's\n");
345 
346 	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
347 	if (rc)
348 		goto out;
349 
350 	if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
351 		cmd.cmd.discovery_mode = 1;
352 		wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
353 	}
354 
355 	rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
356 			cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
357 
358 out:
359 	if (rc) {
360 		del_timer_sync(&wil->scan_timer);
361 		wil->scan_request = NULL;
362 	}
363 
364 	return rc;
365 }
366 
367 static void wil_print_crypto(struct wil6210_priv *wil,
368 			     struct cfg80211_crypto_settings *c)
369 {
370 	int i, n;
371 
372 	wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n",
373 		     c->wpa_versions, c->cipher_group);
374 	wil_dbg_misc(wil, "Pairwise ciphers [%d] {\n", c->n_ciphers_pairwise);
375 	n = min_t(int, c->n_ciphers_pairwise, ARRAY_SIZE(c->ciphers_pairwise));
376 	for (i = 0; i < n; i++)
377 		wil_dbg_misc(wil, "  [%d] = 0x%08x\n", i,
378 			     c->ciphers_pairwise[i]);
379 	wil_dbg_misc(wil, "}\n");
380 	wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites);
381 	n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites));
382 	for (i = 0; i < n; i++)
383 		wil_dbg_misc(wil, "  [%d] = 0x%08x\n", i,
384 			     c->akm_suites[i]);
385 	wil_dbg_misc(wil, "}\n");
386 	wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n",
387 		     c->control_port, be16_to_cpu(c->control_port_ethertype),
388 		     c->control_port_no_encrypt);
389 }
390 
391 static void wil_print_connect_params(struct wil6210_priv *wil,
392 				     struct cfg80211_connect_params *sme)
393 {
394 	wil_info(wil, "Connecting to:\n");
395 	if (sme->channel) {
396 		wil_info(wil, "  Channel: %d freq %d\n",
397 			 sme->channel->hw_value, sme->channel->center_freq);
398 	}
399 	if (sme->bssid)
400 		wil_info(wil, "  BSSID: %pM\n", sme->bssid);
401 	if (sme->ssid)
402 		print_hex_dump(KERN_INFO, "  SSID: ", DUMP_PREFIX_OFFSET,
403 			       16, 1, sme->ssid, sme->ssid_len, true);
404 	wil_info(wil, "  Privacy: %s\n", sme->privacy ? "secure" : "open");
405 	wil_print_crypto(wil, &sme->crypto);
406 }
407 
408 static int wil_cfg80211_connect(struct wiphy *wiphy,
409 				struct net_device *ndev,
410 				struct cfg80211_connect_params *sme)
411 {
412 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
413 	struct cfg80211_bss *bss;
414 	struct wmi_connect_cmd conn;
415 	const u8 *ssid_eid;
416 	const u8 *rsn_eid;
417 	int ch;
418 	int rc = 0;
419 
420 	wil_print_connect_params(wil, sme);
421 
422 	if (test_bit(wil_status_fwconnecting, wil->status) ||
423 	    test_bit(wil_status_fwconnected, wil->status))
424 		return -EALREADY;
425 
426 	if (sme->ie_len > WMI_MAX_IE_LEN) {
427 		wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len);
428 		return -ERANGE;
429 	}
430 
431 	rsn_eid = sme->ie ?
432 			cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
433 			NULL;
434 	if (sme->privacy && !rsn_eid)
435 		wil_info(wil, "WSC connection\n");
436 
437 	if (sme->pbss) {
438 		wil_err(wil, "connect - PBSS not yet supported\n");
439 		return -EOPNOTSUPP;
440 	}
441 
442 	bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
443 			       sme->ssid, sme->ssid_len,
444 			       IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
445 	if (!bss) {
446 		wil_err(wil, "Unable to find BSS\n");
447 		return -ENOENT;
448 	}
449 
450 	ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
451 	if (!ssid_eid) {
452 		wil_err(wil, "No SSID\n");
453 		rc = -ENOENT;
454 		goto out;
455 	}
456 	wil->privacy = sme->privacy;
457 
458 	if (wil->privacy) {
459 		/* For secure assoc, remove old keys */
460 		rc = wmi_del_cipher_key(wil, 0, bss->bssid,
461 					WMI_KEY_USE_PAIRWISE);
462 		if (rc) {
463 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
464 			goto out;
465 		}
466 		rc = wmi_del_cipher_key(wil, 0, bss->bssid,
467 					WMI_KEY_USE_RX_GROUP);
468 		if (rc) {
469 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
470 			goto out;
471 		}
472 	}
473 
474 	/* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info
475 	 * elements. Send it also in case it's empty, to erase previously set
476 	 * ies in FW.
477 	 */
478 	rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
479 	if (rc)
480 		goto out;
481 
482 	/* WMI_CONNECT_CMD */
483 	memset(&conn, 0, sizeof(conn));
484 	switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
485 	case WLAN_CAPABILITY_DMG_TYPE_AP:
486 		conn.network_type = WMI_NETTYPE_INFRA;
487 		break;
488 	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
489 		conn.network_type = WMI_NETTYPE_P2P;
490 		break;
491 	default:
492 		wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
493 			bss->capability);
494 		goto out;
495 	}
496 	if (wil->privacy) {
497 		if (rsn_eid) { /* regular secure connection */
498 			conn.dot11_auth_mode = WMI_AUTH11_SHARED;
499 			conn.auth_mode = WMI_AUTH_WPA2_PSK;
500 			conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
501 			conn.pairwise_crypto_len = 16;
502 			conn.group_crypto_type = WMI_CRYPT_AES_GCMP;
503 			conn.group_crypto_len = 16;
504 		} else { /* WSC */
505 			conn.dot11_auth_mode = WMI_AUTH11_WSC;
506 			conn.auth_mode = WMI_AUTH_NONE;
507 		}
508 	} else { /* insecure connection */
509 		conn.dot11_auth_mode = WMI_AUTH11_OPEN;
510 		conn.auth_mode = WMI_AUTH_NONE;
511 	}
512 
513 	conn.ssid_len = min_t(u8, ssid_eid[1], 32);
514 	memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
515 
516 	ch = bss->channel->hw_value;
517 	if (ch == 0) {
518 		wil_err(wil, "BSS at unknown frequency %dMhz\n",
519 			bss->channel->center_freq);
520 		rc = -EOPNOTSUPP;
521 		goto out;
522 	}
523 	conn.channel = ch - 1;
524 
525 	ether_addr_copy(conn.bssid, bss->bssid);
526 	ether_addr_copy(conn.dst_mac, bss->bssid);
527 
528 	set_bit(wil_status_fwconnecting, wil->status);
529 
530 	rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
531 	if (rc == 0) {
532 		netif_carrier_on(ndev);
533 		/* Connect can take lots of time */
534 		mod_timer(&wil->connect_timer,
535 			  jiffies + msecs_to_jiffies(2000));
536 	} else {
537 		clear_bit(wil_status_fwconnecting, wil->status);
538 	}
539 
540  out:
541 	cfg80211_put_bss(wiphy, bss);
542 
543 	return rc;
544 }
545 
546 static int wil_cfg80211_disconnect(struct wiphy *wiphy,
547 				   struct net_device *ndev,
548 				   u16 reason_code)
549 {
550 	int rc;
551 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
552 
553 	wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code);
554 
555 	if (!(test_bit(wil_status_fwconnecting, wil->status) ||
556 	      test_bit(wil_status_fwconnected, wil->status))) {
557 		wil_err(wil, "%s: Disconnect was called while disconnected\n",
558 			__func__);
559 		return 0;
560 	}
561 
562 	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
563 		      WMI_DISCONNECT_EVENTID, NULL, 0,
564 		      WIL6210_DISCONNECT_TO_MS);
565 	if (rc)
566 		wil_err(wil, "%s: disconnect error %d\n", __func__, rc);
567 
568 	return rc;
569 }
570 
571 int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
572 			 struct cfg80211_mgmt_tx_params *params,
573 			 u64 *cookie)
574 {
575 	const u8 *buf = params->buf;
576 	size_t len = params->len;
577 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
578 	int rc;
579 	bool tx_status = false;
580 	struct ieee80211_mgmt *mgmt_frame = (void *)buf;
581 	struct wmi_sw_tx_req_cmd *cmd;
582 	struct {
583 		struct wil6210_mbox_hdr_wmi wmi;
584 		struct wmi_sw_tx_complete_event evt;
585 	} __packed evt;
586 
587 	cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
588 	if (!cmd) {
589 		rc = -ENOMEM;
590 		goto out;
591 	}
592 
593 	memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
594 	cmd->len = cpu_to_le16(len);
595 	memcpy(cmd->payload, buf, len);
596 
597 	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
598 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
599 	if (rc == 0)
600 		tx_status = !evt.evt.status;
601 
602 	kfree(cmd);
603  out:
604 	cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
605 				tx_status, GFP_KERNEL);
606 	return rc;
607 }
608 
609 static int wil_cfg80211_set_channel(struct wiphy *wiphy,
610 				    struct cfg80211_chan_def *chandef)
611 {
612 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
613 	struct wireless_dev *wdev = wil->wdev;
614 
615 	wdev->preset_chandef = *chandef;
616 
617 	return 0;
618 }
619 
620 static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
621 					       bool pairwise)
622 {
623 	struct wireless_dev *wdev = wil->wdev;
624 	enum wmi_key_usage rc;
625 
626 	if (pairwise) {
627 		rc = WMI_KEY_USE_PAIRWISE;
628 	} else {
629 		switch (wdev->iftype) {
630 		case NL80211_IFTYPE_STATION:
631 			rc = WMI_KEY_USE_RX_GROUP;
632 			break;
633 		case NL80211_IFTYPE_AP:
634 			rc = WMI_KEY_USE_TX_GROUP;
635 			break;
636 		default:
637 			/* TODO: Rx GTK or Tx GTK? */
638 			wil_err(wil, "Can't determine GTK type\n");
639 			rc = WMI_KEY_USE_RX_GROUP;
640 			break;
641 		}
642 	}
643 	wil_dbg_misc(wil, "%s() -> %s\n", __func__, key_usage_str[rc]);
644 
645 	return rc;
646 }
647 
648 static struct wil_tid_crypto_rx_single *
649 wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
650 		    enum wmi_key_usage key_usage, const u8 *mac_addr)
651 {
652 	int cid = -EINVAL;
653 	int tid = 0;
654 	struct wil_sta_info *s;
655 	struct wil_tid_crypto_rx *c;
656 
657 	if (key_usage == WMI_KEY_USE_TX_GROUP)
658 		return NULL; /* not needed */
659 
660 	/* supplicant provides Rx group key in STA mode with NULL MAC address */
661 	if (mac_addr)
662 		cid = wil_find_cid(wil, mac_addr);
663 	else if (key_usage == WMI_KEY_USE_RX_GROUP)
664 		cid = wil_find_cid_by_idx(wil, 0);
665 	if (cid < 0) {
666 		wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr,
667 			key_usage_str[key_usage], key_index);
668 		return ERR_PTR(cid);
669 	}
670 
671 	s = &wil->sta[cid];
672 	if (key_usage == WMI_KEY_USE_PAIRWISE)
673 		c = &s->tid_crypto_rx[tid];
674 	else
675 		c = &s->group_crypto_rx;
676 
677 	return &c->key_id[key_index];
678 }
679 
680 static int wil_cfg80211_add_key(struct wiphy *wiphy,
681 				struct net_device *ndev,
682 				u8 key_index, bool pairwise,
683 				const u8 *mac_addr,
684 				struct key_params *params)
685 {
686 	int rc;
687 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
688 	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
689 	struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
690 								  key_index,
691 								  key_usage,
692 								  mac_addr);
693 
694 	wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
695 		     mac_addr, key_usage_str[key_usage], key_index,
696 		     params->seq_len, params->seq);
697 
698 	if (IS_ERR(cc)) {
699 		wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
700 			__func__, mac_addr, key_usage_str[key_usage], key_index,
701 			params->seq_len, params->seq);
702 		return -EINVAL;
703 	}
704 
705 	if (cc)
706 		cc->key_set = false;
707 
708 	if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
709 		wil_err(wil,
710 			"Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n",
711 			params->seq_len, __func__, mac_addr,
712 			key_usage_str[key_usage], key_index,
713 			params->seq_len, params->seq);
714 		return -EINVAL;
715 	}
716 
717 	rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
718 				params->key, key_usage);
719 	if ((rc == 0) && cc) {
720 		if (params->seq)
721 			memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
722 		else
723 			memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
724 		cc->key_set = true;
725 	}
726 
727 	return rc;
728 }
729 
730 static int wil_cfg80211_del_key(struct wiphy *wiphy,
731 				struct net_device *ndev,
732 				u8 key_index, bool pairwise,
733 				const u8 *mac_addr)
734 {
735 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
736 	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
737 	struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
738 								  key_index,
739 								  key_usage,
740 								  mac_addr);
741 
742 	wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
743 		     key_usage_str[key_usage], key_index);
744 
745 	if (IS_ERR(cc))
746 		wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
747 			 mac_addr, key_usage_str[key_usage], key_index);
748 
749 	if (!IS_ERR_OR_NULL(cc))
750 		cc->key_set = false;
751 
752 	return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
753 }
754 
755 /* Need to be present or wiphy_new() will WARN */
756 static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
757 					struct net_device *ndev,
758 					u8 key_index, bool unicast,
759 					bool multicast)
760 {
761 	return 0;
762 }
763 
764 static int wil_remain_on_channel(struct wiphy *wiphy,
765 				 struct wireless_dev *wdev,
766 				 struct ieee80211_channel *chan,
767 				 unsigned int duration,
768 				 u64 *cookie)
769 {
770 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
771 	int rc;
772 
773 	/* TODO: handle duration */
774 	wil_info(wil, "%s(%d, %d ms)\n", __func__, chan->center_freq, duration);
775 
776 	rc = wmi_set_channel(wil, chan->hw_value);
777 	if (rc)
778 		return rc;
779 
780 	rc = wmi_rxon(wil, true);
781 
782 	return rc;
783 }
784 
785 static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
786 					struct wireless_dev *wdev,
787 					u64 cookie)
788 {
789 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
790 	int rc;
791 
792 	wil_info(wil, "%s()\n", __func__);
793 
794 	rc = wmi_rxon(wil, false);
795 
796 	return rc;
797 }
798 
799 /**
800  * find a specific IE in a list of IEs
801  * return a pointer to the beginning of IE in the list
802  * or NULL if not found
803  */
804 static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie,
805 				       u16 ie_len)
806 {
807 	struct ieee80211_vendor_ie *vie;
808 	u32 oui;
809 
810 	/* IE tag at offset 0, length at offset 1 */
811 	if (ie_len < 2 || 2 + ie[1] > ie_len)
812 		return NULL;
813 
814 	if (ie[0] != WLAN_EID_VENDOR_SPECIFIC)
815 		return cfg80211_find_ie(ie[0], ies, ies_len);
816 
817 	/* make sure there is room for 3 bytes OUI + 1 byte OUI type */
818 	if (ie[1] < 4)
819 		return NULL;
820 	vie = (struct ieee80211_vendor_ie *)ie;
821 	oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2];
822 	return cfg80211_find_vendor_ie(oui, vie->oui_type, ies,
823 				       ies_len);
824 }
825 
826 /**
827  * merge the IEs in two lists into a single list.
828  * do not include IEs from the second list which exist in the first list.
829  * add only vendor specific IEs from second list to keep
830  * the merged list sorted (since vendor-specific IE has the
831  * highest tag number)
832  * caller must free the allocated memory for merged IEs
833  */
834 static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
835 					 const u8 *ies2, u16 ies2_len,
836 					 u8 **merged_ies, u16 *merged_len)
837 {
838 	u8 *buf, *dpos;
839 	const u8 *spos;
840 
841 	if (ies1_len == 0 && ies2_len == 0) {
842 		*merged_ies = NULL;
843 		*merged_len = 0;
844 		return 0;
845 	}
846 
847 	buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
848 	if (!buf)
849 		return -ENOMEM;
850 	memcpy(buf, ies1, ies1_len);
851 	dpos = buf + ies1_len;
852 	spos = ies2;
853 	while (spos + 1 < ies2 + ies2_len) {
854 		/* IE tag at offset 0, length at offset 1 */
855 		u16 ielen = 2 + spos[1];
856 
857 		if (spos + ielen > ies2 + ies2_len)
858 			break;
859 		if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
860 		    !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
861 			memcpy(dpos, spos, ielen);
862 			dpos += ielen;
863 		}
864 		spos += ielen;
865 	}
866 
867 	*merged_ies = buf;
868 	*merged_len = dpos - buf;
869 	return 0;
870 }
871 
872 static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
873 {
874 	print_hex_dump_bytes("head     ", DUMP_PREFIX_OFFSET,
875 			     b->head, b->head_len);
876 	print_hex_dump_bytes("tail     ", DUMP_PREFIX_OFFSET,
877 			     b->tail, b->tail_len);
878 	print_hex_dump_bytes("BCON IE  ", DUMP_PREFIX_OFFSET,
879 			     b->beacon_ies, b->beacon_ies_len);
880 	print_hex_dump_bytes("PROBE    ", DUMP_PREFIX_OFFSET,
881 			     b->probe_resp, b->probe_resp_len);
882 	print_hex_dump_bytes("PROBE IE ", DUMP_PREFIX_OFFSET,
883 			     b->proberesp_ies, b->proberesp_ies_len);
884 	print_hex_dump_bytes("ASSOC IE ", DUMP_PREFIX_OFFSET,
885 			     b->assocresp_ies, b->assocresp_ies_len);
886 }
887 
888 /* internal functions for device reset and starting AP */
889 static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
890 				 struct cfg80211_beacon_data *bcon)
891 {
892 	int rc;
893 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
894 	u16 len = 0, proberesp_len = 0;
895 	u8 *ies = NULL, *proberesp = NULL;
896 
897 	if (bcon->probe_resp) {
898 		struct ieee80211_mgmt *f =
899 			(struct ieee80211_mgmt *)bcon->probe_resp;
900 		size_t hlen = offsetof(struct ieee80211_mgmt,
901 				       u.probe_resp.variable);
902 		proberesp = f->u.probe_resp.variable;
903 		proberesp_len = bcon->probe_resp_len - hlen;
904 	}
905 	rc = _wil_cfg80211_merge_extra_ies(proberesp,
906 					   proberesp_len,
907 					   bcon->proberesp_ies,
908 					   bcon->proberesp_ies_len,
909 					   &ies, &len);
910 
911 	if (rc)
912 		goto out;
913 
914 	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies);
915 	if (rc)
916 		goto out;
917 
918 	if (bcon->assocresp_ies)
919 		rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP,
920 				bcon->assocresp_ies_len, bcon->assocresp_ies);
921 	else
922 		rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies);
923 #if 0 /* to use beacon IE's, remove this #if 0 */
924 	if (rc)
925 		goto out;
926 
927 	rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail);
928 #endif
929 out:
930 	kfree(ies);
931 	return rc;
932 }
933 
934 static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
935 				  struct net_device *ndev,
936 				  const u8 *ssid, size_t ssid_len, u32 privacy,
937 				  int bi, u8 chan,
938 				  struct cfg80211_beacon_data *bcon,
939 				  u8 hidden_ssid)
940 {
941 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
942 	int rc;
943 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
944 	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
945 
946 	wil_set_recovery_state(wil, fw_recovery_idle);
947 
948 	mutex_lock(&wil->mutex);
949 
950 	__wil_down(wil);
951 	rc = __wil_up(wil);
952 	if (rc)
953 		goto out;
954 
955 	rc = wmi_set_ssid(wil, ssid_len, ssid);
956 	if (rc)
957 		goto out;
958 
959 	rc = _wil_cfg80211_set_ies(wiphy, bcon);
960 	if (rc)
961 		goto out;
962 
963 	wil->privacy = privacy;
964 	wil->channel = chan;
965 	wil->hidden_ssid = hidden_ssid;
966 
967 	netif_carrier_on(ndev);
968 
969 	rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid);
970 	if (rc)
971 		goto err_pcp_start;
972 
973 	rc = wil_bcast_init(wil);
974 	if (rc)
975 		goto err_bcast;
976 
977 	goto out; /* success */
978 
979 err_bcast:
980 	wmi_pcp_stop(wil);
981 err_pcp_start:
982 	netif_carrier_off(ndev);
983 out:
984 	mutex_unlock(&wil->mutex);
985 	return rc;
986 }
987 
988 static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
989 				      struct net_device *ndev,
990 				      struct cfg80211_beacon_data *bcon)
991 {
992 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
993 	int rc;
994 	u32 privacy = 0;
995 
996 	wil_dbg_misc(wil, "%s()\n", __func__);
997 	wil_print_bcon_data(bcon);
998 
999 	if (bcon->tail &&
1000 	    cfg80211_find_ie(WLAN_EID_RSN, bcon->tail,
1001 			     bcon->tail_len))
1002 		privacy = 1;
1003 
1004 	/* in case privacy has changed, need to restart the AP */
1005 	if (wil->privacy != privacy) {
1006 		struct wireless_dev *wdev = ndev->ieee80211_ptr;
1007 
1008 		wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
1009 			     wil->privacy, privacy);
1010 
1011 		rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
1012 					    wdev->ssid_len, privacy,
1013 					    wdev->beacon_interval,
1014 					    wil->channel, bcon,
1015 					    wil->hidden_ssid);
1016 	} else {
1017 		rc = _wil_cfg80211_set_ies(wiphy, bcon);
1018 	}
1019 
1020 	return rc;
1021 }
1022 
1023 static int wil_cfg80211_start_ap(struct wiphy *wiphy,
1024 				 struct net_device *ndev,
1025 				 struct cfg80211_ap_settings *info)
1026 {
1027 	int rc;
1028 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1029 	struct ieee80211_channel *channel = info->chandef.chan;
1030 	struct cfg80211_beacon_data *bcon = &info->beacon;
1031 	struct cfg80211_crypto_settings *crypto = &info->crypto;
1032 	u8 hidden_ssid;
1033 
1034 	wil_dbg_misc(wil, "%s()\n", __func__);
1035 
1036 	if (!channel) {
1037 		wil_err(wil, "AP: No channel???\n");
1038 		return -EINVAL;
1039 	}
1040 
1041 	if (info->pbss) {
1042 		wil_err(wil, "AP: PBSS not yet supported\n");
1043 		return -EOPNOTSUPP;
1044 	}
1045 
1046 	switch (info->hidden_ssid) {
1047 	case NL80211_HIDDEN_SSID_NOT_IN_USE:
1048 		hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
1049 		break;
1050 
1051 	case NL80211_HIDDEN_SSID_ZERO_LEN:
1052 		hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
1053 		break;
1054 
1055 	case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1056 		hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
1057 		break;
1058 
1059 	default:
1060 		wil_err(wil, "AP: Invalid hidden SSID %d\n", info->hidden_ssid);
1061 		return -EOPNOTSUPP;
1062 	}
1063 	wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
1064 		     channel->center_freq, info->privacy ? "secure" : "open");
1065 	wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
1066 		     info->privacy, info->auth_type);
1067 	wil_dbg_misc(wil, "Hidden SSID mode: %d\n",
1068 		     info->hidden_ssid);
1069 	wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
1070 		     info->dtim_period);
1071 	print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
1072 			     info->ssid, info->ssid_len);
1073 	wil_print_bcon_data(bcon);
1074 	wil_print_crypto(wil, crypto);
1075 
1076 	rc = _wil_cfg80211_start_ap(wiphy, ndev,
1077 				    info->ssid, info->ssid_len, info->privacy,
1078 				    info->beacon_interval, channel->hw_value,
1079 				    bcon, hidden_ssid);
1080 
1081 	return rc;
1082 }
1083 
1084 static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
1085 				struct net_device *ndev)
1086 {
1087 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1088 
1089 	wil_dbg_misc(wil, "%s()\n", __func__);
1090 
1091 	netif_carrier_off(ndev);
1092 	wil_set_recovery_state(wil, fw_recovery_idle);
1093 
1094 	mutex_lock(&wil->mutex);
1095 
1096 	wmi_pcp_stop(wil);
1097 
1098 	__wil_down(wil);
1099 
1100 	mutex_unlock(&wil->mutex);
1101 
1102 	return 0;
1103 }
1104 
1105 static int wil_cfg80211_del_station(struct wiphy *wiphy,
1106 				    struct net_device *dev,
1107 				    struct station_del_parameters *params)
1108 {
1109 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1110 
1111 	wil_dbg_misc(wil, "%s(%pM, reason=%d)\n", __func__, params->mac,
1112 		     params->reason_code);
1113 
1114 	mutex_lock(&wil->mutex);
1115 	wil6210_disconnect(wil, params->mac, params->reason_code, false);
1116 	mutex_unlock(&wil->mutex);
1117 
1118 	return 0;
1119 }
1120 
1121 /* probe_client handling */
1122 static void wil_probe_client_handle(struct wil6210_priv *wil,
1123 				    struct wil_probe_client_req *req)
1124 {
1125 	struct net_device *ndev = wil_to_ndev(wil);
1126 	struct wil_sta_info *sta = &wil->sta[req->cid];
1127 	/* assume STA is alive if it is still connected,
1128 	 * else FW will disconnect it
1129 	 */
1130 	bool alive = (sta->status == wil_sta_connected);
1131 
1132 	cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL);
1133 }
1134 
1135 static struct list_head *next_probe_client(struct wil6210_priv *wil)
1136 {
1137 	struct list_head *ret = NULL;
1138 
1139 	mutex_lock(&wil->probe_client_mutex);
1140 
1141 	if (!list_empty(&wil->probe_client_pending)) {
1142 		ret = wil->probe_client_pending.next;
1143 		list_del(ret);
1144 	}
1145 
1146 	mutex_unlock(&wil->probe_client_mutex);
1147 
1148 	return ret;
1149 }
1150 
1151 void wil_probe_client_worker(struct work_struct *work)
1152 {
1153 	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1154 						probe_client_worker);
1155 	struct wil_probe_client_req *req;
1156 	struct list_head *lh;
1157 
1158 	while ((lh = next_probe_client(wil)) != NULL) {
1159 		req = list_entry(lh, struct wil_probe_client_req, list);
1160 
1161 		wil_probe_client_handle(wil, req);
1162 		kfree(req);
1163 	}
1164 }
1165 
1166 void wil_probe_client_flush(struct wil6210_priv *wil)
1167 {
1168 	struct wil_probe_client_req *req, *t;
1169 
1170 	wil_dbg_misc(wil, "%s()\n", __func__);
1171 
1172 	mutex_lock(&wil->probe_client_mutex);
1173 
1174 	list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) {
1175 		list_del(&req->list);
1176 		kfree(req);
1177 	}
1178 
1179 	mutex_unlock(&wil->probe_client_mutex);
1180 }
1181 
1182 static int wil_cfg80211_probe_client(struct wiphy *wiphy,
1183 				     struct net_device *dev,
1184 				     const u8 *peer, u64 *cookie)
1185 {
1186 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1187 	struct wil_probe_client_req *req;
1188 	int cid = wil_find_cid(wil, peer);
1189 
1190 	wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid);
1191 
1192 	if (cid < 0)
1193 		return -ENOLINK;
1194 
1195 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1196 	if (!req)
1197 		return -ENOMEM;
1198 
1199 	req->cid = cid;
1200 	req->cookie = cid;
1201 
1202 	mutex_lock(&wil->probe_client_mutex);
1203 	list_add_tail(&req->list, &wil->probe_client_pending);
1204 	mutex_unlock(&wil->probe_client_mutex);
1205 
1206 	*cookie = req->cookie;
1207 	queue_work(wil->wq_service, &wil->probe_client_worker);
1208 	return 0;
1209 }
1210 
1211 static int wil_cfg80211_change_bss(struct wiphy *wiphy,
1212 				   struct net_device *dev,
1213 				   struct bss_parameters *params)
1214 {
1215 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
1216 
1217 	if (params->ap_isolate >= 0) {
1218 		wil_dbg_misc(wil, "%s(ap_isolate %d => %d)\n", __func__,
1219 			     wil->ap_isolate, params->ap_isolate);
1220 		wil->ap_isolate = params->ap_isolate;
1221 	}
1222 
1223 	return 0;
1224 }
1225 
1226 static struct cfg80211_ops wil_cfg80211_ops = {
1227 	.scan = wil_cfg80211_scan,
1228 	.connect = wil_cfg80211_connect,
1229 	.disconnect = wil_cfg80211_disconnect,
1230 	.change_virtual_intf = wil_cfg80211_change_iface,
1231 	.get_station = wil_cfg80211_get_station,
1232 	.dump_station = wil_cfg80211_dump_station,
1233 	.remain_on_channel = wil_remain_on_channel,
1234 	.cancel_remain_on_channel = wil_cancel_remain_on_channel,
1235 	.mgmt_tx = wil_cfg80211_mgmt_tx,
1236 	.set_monitor_channel = wil_cfg80211_set_channel,
1237 	.add_key = wil_cfg80211_add_key,
1238 	.del_key = wil_cfg80211_del_key,
1239 	.set_default_key = wil_cfg80211_set_default_key,
1240 	/* AP mode */
1241 	.change_beacon = wil_cfg80211_change_beacon,
1242 	.start_ap = wil_cfg80211_start_ap,
1243 	.stop_ap = wil_cfg80211_stop_ap,
1244 	.del_station = wil_cfg80211_del_station,
1245 	.probe_client = wil_cfg80211_probe_client,
1246 	.change_bss = wil_cfg80211_change_bss,
1247 };
1248 
1249 static void wil_wiphy_init(struct wiphy *wiphy)
1250 {
1251 	wiphy->max_scan_ssids = 1;
1252 	wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
1253 	wiphy->max_num_pmkids = 0 /* TODO: */;
1254 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1255 				 BIT(NL80211_IFTYPE_AP) |
1256 				 BIT(NL80211_IFTYPE_MONITOR);
1257 	/* TODO: enable P2P when integrated with supplicant:
1258 	 * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)
1259 	 */
1260 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
1261 			WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
1262 	dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
1263 		__func__, wiphy->flags);
1264 	wiphy->probe_resp_offload =
1265 		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
1266 		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
1267 		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
1268 
1269 	wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz;
1270 
1271 	/* TODO: figure this out */
1272 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
1273 
1274 	wiphy->cipher_suites = wil_cipher_suites;
1275 	wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
1276 	wiphy->mgmt_stypes = wil_mgmt_stypes;
1277 	wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
1278 }
1279 
1280 struct wireless_dev *wil_cfg80211_init(struct device *dev)
1281 {
1282 	int rc = 0;
1283 	struct wireless_dev *wdev;
1284 
1285 	dev_dbg(dev, "%s()\n", __func__);
1286 
1287 	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
1288 	if (!wdev)
1289 		return ERR_PTR(-ENOMEM);
1290 
1291 	wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
1292 				sizeof(struct wil6210_priv));
1293 	if (!wdev->wiphy) {
1294 		rc = -ENOMEM;
1295 		goto out;
1296 	}
1297 
1298 	set_wiphy_dev(wdev->wiphy, dev);
1299 	wil_wiphy_init(wdev->wiphy);
1300 
1301 	rc = wiphy_register(wdev->wiphy);
1302 	if (rc < 0)
1303 		goto out_failed_reg;
1304 
1305 	return wdev;
1306 
1307 out_failed_reg:
1308 	wiphy_free(wdev->wiphy);
1309 out:
1310 	kfree(wdev);
1311 
1312 	return ERR_PTR(rc);
1313 }
1314 
1315 void wil_wdev_free(struct wil6210_priv *wil)
1316 {
1317 	struct wireless_dev *wdev = wil_to_wdev(wil);
1318 
1319 	dev_dbg(wil_to_dev(wil), "%s()\n", __func__);
1320 
1321 	if (!wdev)
1322 		return;
1323 
1324 	wiphy_unregister(wdev->wiphy);
1325 	wiphy_free(wdev->wiphy);
1326 	kfree(wdev);
1327 }
1328