Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   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/moduleparam.h>
  18#include <linux/etherdevice.h>
  19#include <linux/if_arp.h>
  20
  21#include "wil6210.h"
  22#include "txrx.h"
  23#include "wmi.h"
  24#include "trace.h"
  25
  26static uint max_assoc_sta = WIL6210_MAX_CID;
  27module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR);
  28MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
  29
  30int agg_wsize; /* = 0; */
  31module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
  32MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
  33		 " 0 - use default; < 0 - don't auto-establish");
  34
  35/**
  36 * WMI event receiving - theory of operations
  37 *
  38 * When firmware about to report WMI event, it fills memory area
  39 * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
  40 * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
  41 *
  42 * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
  43 * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
  44 * and handles events within the @wmi_event_worker. Every event get detached
  45 * from list, processed and deleted.
  46 *
  47 * Purpose for this mechanism is to release IRQ thread; otherwise,
  48 * if WMI event handling involves another WMI command flow, this 2-nd flow
  49 * won't be completed because of blocked IRQ thread.
  50 */
  51
  52/**
  53 * Addressing - theory of operations
  54 *
  55 * There are several buses present on the WIL6210 card.
  56 * Same memory areas are visible at different address on
  57 * the different busses. There are 3 main bus masters:
  58 *  - MAC CPU (ucode)
  59 *  - User CPU (firmware)
  60 *  - AHB (host)
  61 *
  62 * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
  63 * AHB addresses starting from 0x880000
  64 *
  65 * Internally, firmware uses addresses that allows faster access but
  66 * are invisible from the host. To read from these addresses, alternative
  67 * AHB address must be used.
  68 *
  69 * Memory mapping
  70 * Linker address         PCI/Host address
  71 *                        0x880000 .. 0xa80000  2Mb BAR0
  72 * 0x800000 .. 0x807000   0x900000 .. 0x907000  28k DCCM
  73 * 0x840000 .. 0x857000   0x908000 .. 0x91f000  92k PERIPH
  74 */
  75
  76/**
  77 * @fw_mapping provides memory remapping table
  78 *
  79 * array size should be in sync with the declaration in the wil6210.h
  80 */
  81const struct fw_map fw_mapping[] = {
  82	{0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM      256k */
  83	{0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM       32k */
  84	{0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
  85	{0x880000, 0x88a000, 0x880000, "rgf"},     /* various RGF       40k */
  86	{0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table          4k */
  87	{0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf       4k */
  88	{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf  512b */
  89	{0x8c0000, 0x949000, 0x8c0000, "upper"},   /* upper area       548k */
  90	/*
  91	 * 920000..930000 ucode code RAM
  92	 * 930000..932000 ucode data RAM
  93	 * 932000..949000 back-door debug data
  94	 */
  95};
  96
  97/**
  98 * return AHB address for given firmware/ucode internal (linker) address
  99 * @x - internal address
 100 * If address have no valid AHB mapping, return 0
 101 */
 102static u32 wmi_addr_remap(u32 x)
 103{
 104	uint i;
 105
 106	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
 107		if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))
 108			return x + fw_mapping[i].host - fw_mapping[i].from;
 109	}
 110
 111	return 0;
 112}
 113
 114/**
 115 * Check address validity for WMI buffer; remap if needed
 116 * @ptr - internal (linker) fw/ucode address
 117 *
 118 * Valid buffer should be DWORD aligned
 119 *
 120 * return address for accessing buffer from the host;
 121 * if buffer is not valid, return NULL.
 122 */
 123void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
 124{
 125	u32 off;
 126	u32 ptr = le32_to_cpu(ptr_);
 127
 128	if (ptr % 4)
 129		return NULL;
 130
 131	ptr = wmi_addr_remap(ptr);
 132	if (ptr < WIL6210_FW_HOST_OFF)
 133		return NULL;
 134
 135	off = HOSTADDR(ptr);
 136	if (off > WIL6210_MEM_SIZE - 4)
 137		return NULL;
 138
 139	return wil->csr + off;
 140}
 141
 142/**
 143 * Check address validity
 144 */
 145void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
 146{
 147	u32 off;
 148
 149	if (ptr % 4)
 150		return NULL;
 151
 152	if (ptr < WIL6210_FW_HOST_OFF)
 153		return NULL;
 154
 155	off = HOSTADDR(ptr);
 156	if (off > WIL6210_MEM_SIZE - 4)
 157		return NULL;
 158
 159	return wil->csr + off;
 160}
 161
 162int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
 163		 struct wil6210_mbox_hdr *hdr)
 164{
 165	void __iomem *src = wmi_buffer(wil, ptr);
 166
 167	if (!src)
 168		return -EINVAL;
 169
 170	wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
 171
 172	return 0;
 173}
 174
 175static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 176{
 177	struct {
 178		struct wil6210_mbox_hdr hdr;
 179		struct wil6210_mbox_hdr_wmi wmi;
 180	} __packed cmd = {
 181		.hdr = {
 182			.type = WIL_MBOX_HDR_TYPE_WMI,
 183			.flags = 0,
 184			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
 185		},
 186		.wmi = {
 187			.mid = 0,
 188			.id = cpu_to_le16(cmdid),
 189		},
 190	};
 191	struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
 192	struct wil6210_mbox_ring_desc d_head;
 193	u32 next_head;
 194	void __iomem *dst;
 195	void __iomem *head = wmi_addr(wil, r->head);
 196	uint retry;
 197
 198	if (sizeof(cmd) + len > r->entry_size) {
 199		wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
 200			(int)(sizeof(cmd) + len), r->entry_size);
 201		return -ERANGE;
 202	}
 203
 204	might_sleep();
 205
 206	if (!test_bit(wil_status_fwready, wil->status)) {
 207		wil_err(wil, "WMI: cannot send command while FW not ready\n");
 208		return -EAGAIN;
 209	}
 210
 211	if (!head) {
 212		wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
 213		return -EINVAL;
 214	}
 215	/* read Tx head till it is not busy */
 216	for (retry = 5; retry > 0; retry--) {
 217		wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
 218		if (d_head.sync == 0)
 219			break;
 220		msleep(20);
 221	}
 222	if (d_head.sync != 0) {
 223		wil_err(wil, "WMI head busy\n");
 224		return -EBUSY;
 225	}
 226	/* next head */
 227	next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
 228	wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
 229	/* wait till FW finish with previous command */
 230	for (retry = 5; retry > 0; retry--) {
 231		if (!test_bit(wil_status_fwready, wil->status)) {
 232			wil_err(wil, "WMI: cannot send command while FW not ready\n");
 233			return -EAGAIN;
 234		}
 235		r->tail = wil_r(wil, RGF_MBOX +
 236				offsetof(struct wil6210_mbox_ctl, tx.tail));
 237		if (next_head != r->tail)
 238			break;
 239		msleep(20);
 240	}
 241	if (next_head == r->tail) {
 242		wil_err(wil, "WMI ring full\n");
 243		return -EBUSY;
 244	}
 245	dst = wmi_buffer(wil, d_head.addr);
 246	if (!dst) {
 247		wil_err(wil, "invalid WMI buffer: 0x%08x\n",
 248			le32_to_cpu(d_head.addr));
 249		return -EINVAL;
 250	}
 251	cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
 252	/* set command */
 253	wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
 254	wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
 255			 sizeof(cmd), true);
 256	wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 257			 len, true);
 258	wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
 259	wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
 260	/* mark entry as full */
 261	wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
 262	/* advance next ptr */
 263	wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
 264	      r->head = next_head);
 265
 266	trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
 267
 268	/* interrupt to FW */
 269	wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
 270	      SW_INT_MBOX);
 271
 272	return 0;
 273}
 274
 275int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 276{
 277	int rc;
 278
 279	mutex_lock(&wil->wmi_mutex);
 280	rc = __wmi_send(wil, cmdid, buf, len);
 281	mutex_unlock(&wil->wmi_mutex);
 282
 283	return rc;
 284}
 285
 286/*=== Event handlers ===*/
 287static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 288{
 289	struct wireless_dev *wdev = wil->wdev;
 290	struct wmi_ready_event *evt = d;
 291
 292	wil->fw_version = le32_to_cpu(evt->sw_version);
 293	wil->n_mids = evt->numof_additional_mids;
 294
 295	wil_info(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version,
 296		 evt->mac, wil->n_mids);
 297	/* ignore MAC address, we already have it from the boot loader */
 298	snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
 299		 "%d", wil->fw_version);
 300
 301	wil_set_recovery_state(wil, fw_recovery_idle);
 302	set_bit(wil_status_fwready, wil->status);
 303	/* let the reset sequence continue */
 304	complete(&wil->wmi_ready);
 305}
 306
 307static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 308{
 309	struct wmi_rx_mgmt_packet_event *data = d;
 310	struct wiphy *wiphy = wil_to_wiphy(wil);
 311	struct ieee80211_mgmt *rx_mgmt_frame =
 312			(struct ieee80211_mgmt *)data->payload;
 313	int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
 314	int ch_no;
 315	u32 freq;
 316	struct ieee80211_channel *channel;
 317	s32 signal;
 318	__le16 fc;
 319	u32 d_len;
 320	u16 d_status;
 321
 322	if (flen < 0) {
 323		wil_err(wil, "MGMT Rx: short event, len %d\n", len);
 324		return;
 325	}
 326
 327	d_len = le32_to_cpu(data->info.len);
 328	if (d_len != flen) {
 329		wil_err(wil,
 330			"MGMT Rx: length mismatch, d_len %d should be %d\n",
 331			d_len, flen);
 332		return;
 333	}
 334
 335	ch_no = data->info.channel + 1;
 336	freq = ieee80211_channel_to_frequency(ch_no, IEEE80211_BAND_60GHZ);
 337	channel = ieee80211_get_channel(wiphy, freq);
 338	signal = data->info.sqi;
 339	d_status = le16_to_cpu(data->info.status);
 340	fc = rx_mgmt_frame->frame_control;
 341
 342	wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d SNR %d SQI %d%%\n",
 343		    data->info.channel, data->info.mcs, data->info.snr,
 344		    data->info.sqi);
 345	wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
 346		    le16_to_cpu(fc));
 347	wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
 348		    data->info.qid, data->info.mid, data->info.cid);
 349	wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
 350			 d_len, true);
 351
 352	if (!channel) {
 353		wil_err(wil, "Frame on unsupported channel\n");
 354		return;
 355	}
 356
 357	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
 358		struct cfg80211_bss *bss;
 359		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
 360		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
 361		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
 362		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
 363		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
 364						 u.beacon.variable);
 365		wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
 366		wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
 367		wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
 368		wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
 369				 ie_len, true);
 370
 371		bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
 372						d_len, signal, GFP_KERNEL);
 373		if (bss) {
 374			wil_dbg_wmi(wil, "Added BSS %pM\n",
 375				    rx_mgmt_frame->bssid);
 376			cfg80211_put_bss(wiphy, bss);
 377		} else {
 378			wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
 379		}
 380	} else {
 381		cfg80211_rx_mgmt(wil->wdev, freq, signal,
 382				 (void *)rx_mgmt_frame, d_len, 0);
 383	}
 384}
 385
 386static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 387{
 388	struct wmi_tx_mgmt_packet_event *data = d;
 389	struct ieee80211_mgmt *mgmt_frame =
 390			(struct ieee80211_mgmt *)data->payload;
 391	int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
 392
 393	wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
 394			 flen, true);
 395}
 396
 397static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
 398				  void *d, int len)
 399{
 400	if (wil->scan_request) {
 401		struct wmi_scan_complete_event *data = d;
 402		bool aborted = (data->status != WMI_SCAN_SUCCESS);
 403
 404		wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
 405		wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
 406			     wil->scan_request, aborted);
 407
 408		del_timer_sync(&wil->scan_timer);
 409		cfg80211_scan_done(wil->scan_request, aborted);
 410		wil->scan_request = NULL;
 411	} else {
 412		wil_err(wil, "SCAN_COMPLETE while not scanning\n");
 413	}
 414}
 415
 416static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 417{
 418	struct net_device *ndev = wil_to_ndev(wil);
 419	struct wireless_dev *wdev = wil->wdev;
 420	struct wmi_connect_event *evt = d;
 421	int ch; /* channel number */
 422	struct station_info sinfo;
 423	u8 *assoc_req_ie, *assoc_resp_ie;
 424	size_t assoc_req_ielen, assoc_resp_ielen;
 425	/* capinfo(u16) + listen_interval(u16) + IEs */
 426	const size_t assoc_req_ie_offset = sizeof(u16) * 2;
 427	/* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
 428	const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
 429	int rc;
 430
 431	if (len < sizeof(*evt)) {
 432		wil_err(wil, "Connect event too short : %d bytes\n", len);
 433		return;
 434	}
 435	if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
 436		   evt->assoc_resp_len) {
 437		wil_err(wil,
 438			"Connect event corrupted : %d != %d + %d + %d + %d\n",
 439			len, (int)sizeof(*evt), evt->beacon_ie_len,
 440			evt->assoc_req_len, evt->assoc_resp_len);
 441		return;
 442	}
 443	if (evt->cid >= WIL6210_MAX_CID) {
 444		wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
 445		return;
 446	}
 447
 448	ch = evt->channel + 1;
 449	wil_info(wil, "Connect %pM channel [%d] cid %d\n",
 450		 evt->bssid, ch, evt->cid);
 451	wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
 452			 evt->assoc_info, len - sizeof(*evt), true);
 453
 454	/* figure out IE's */
 455	assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
 456					assoc_req_ie_offset];
 457	assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
 458	if (evt->assoc_req_len <= assoc_req_ie_offset) {
 459		assoc_req_ie = NULL;
 460		assoc_req_ielen = 0;
 461	}
 462
 463	assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
 464					 evt->assoc_req_len +
 465					 assoc_resp_ie_offset];
 466	assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
 467	if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
 468		assoc_resp_ie = NULL;
 469		assoc_resp_ielen = 0;
 470	}
 471
 472	mutex_lock(&wil->mutex);
 473	if (test_bit(wil_status_resetting, wil->status) ||
 474	    !test_bit(wil_status_fwready, wil->status)) {
 475		wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
 476			evt->cid);
 477		mutex_unlock(&wil->mutex);
 478		/* no need for cleanup, wil_reset will do that */
 479		return;
 480	}
 481
 482	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 483	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 484		if (!test_bit(wil_status_fwconnecting, wil->status)) {
 485			wil_err(wil, "Not in connecting state\n");
 486			mutex_unlock(&wil->mutex);
 487			return;
 488		}
 489		del_timer_sync(&wil->connect_timer);
 490	}
 491
 492	/* FIXME FW can transmit only ucast frames to peer */
 493	/* FIXME real ring_id instead of hard coded 0 */
 494	ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
 495	wil->sta[evt->cid].status = wil_sta_conn_pending;
 496
 497	rc = wil_tx_init(wil, evt->cid);
 498	if (rc) {
 499		wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n",
 500			__func__, evt->cid, rc);
 501		wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
 502				   WLAN_REASON_UNSPECIFIED, false);
 503	} else {
 504		wil_info(wil, "%s: successful connection to CID %d\n",
 505			 __func__, evt->cid);
 506	}
 507
 508	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
 509	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 510		if (rc) {
 511			netif_tx_stop_all_queues(ndev);
 512			netif_carrier_off(ndev);
 513			wil_err(wil,
 514				"%s: cfg80211_connect_result with failure\n",
 515				__func__);
 516			cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
 517						NULL, 0,
 518						WLAN_STATUS_UNSPECIFIED_FAILURE,
 519						GFP_KERNEL);
 520			goto out;
 521		} else {
 522			cfg80211_connect_result(ndev, evt->bssid,
 523						assoc_req_ie, assoc_req_ielen,
 524						assoc_resp_ie, assoc_resp_ielen,
 525						WLAN_STATUS_SUCCESS,
 526						GFP_KERNEL);
 527		}
 528	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 529		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 530		if (rc)
 531			goto out;
 532
 533		memset(&sinfo, 0, sizeof(sinfo));
 534
 535		sinfo.generation = wil->sinfo_gen++;
 536
 537		if (assoc_req_ie) {
 538			sinfo.assoc_req_ies = assoc_req_ie;
 539			sinfo.assoc_req_ies_len = assoc_req_ielen;
 540		}
 541
 542		cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
 543	} else {
 544		wil_err(wil, "%s: unhandled iftype %d for CID %d\n",
 545			__func__, wdev->iftype, evt->cid);
 546		goto out;
 547	}
 548
 549	wil->sta[evt->cid].status = wil_sta_connected;
 550	set_bit(wil_status_fwconnected, wil->status);
 551	netif_tx_wake_all_queues(ndev);
 552
 553out:
 554	if (rc)
 555		wil->sta[evt->cid].status = wil_sta_unused;
 556	clear_bit(wil_status_fwconnecting, wil->status);
 557	mutex_unlock(&wil->mutex);
 558}
 559
 560static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
 561			       void *d, int len)
 562{
 563	struct wmi_disconnect_event *evt = d;
 564	u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
 565
 566	wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
 567		 evt->bssid, reason_code, evt->disconnect_reason);
 568
 569	wil->sinfo_gen++;
 570
 571	mutex_lock(&wil->mutex);
 572	wil6210_disconnect(wil, evt->bssid, reason_code, true);
 573	mutex_unlock(&wil->mutex);
 574}
 575
 576/*
 577 * Firmware reports EAPOL frame using WME event.
 578 * Reconstruct Ethernet frame and deliver it via normal Rx
 579 */
 580static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 581			     void *d, int len)
 582{
 583	struct net_device *ndev = wil_to_ndev(wil);
 584	struct wmi_eapol_rx_event *evt = d;
 585	u16 eapol_len = le16_to_cpu(evt->eapol_len);
 586	int sz = eapol_len + ETH_HLEN;
 587	struct sk_buff *skb;
 588	struct ethhdr *eth;
 589	int cid;
 590	struct wil_net_stats *stats = NULL;
 591
 592	wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
 593		    evt->src_mac);
 594
 595	cid = wil_find_cid(wil, evt->src_mac);
 596	if (cid >= 0)
 597		stats = &wil->sta[cid].stats;
 598
 599	if (eapol_len > 196) { /* TODO: revisit size limit */
 600		wil_err(wil, "EAPOL too large\n");
 601		return;
 602	}
 603
 604	skb = alloc_skb(sz, GFP_KERNEL);
 605	if (!skb) {
 606		wil_err(wil, "Failed to allocate skb\n");
 607		return;
 608	}
 609
 610	eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
 611	ether_addr_copy(eth->h_dest, ndev->dev_addr);
 612	ether_addr_copy(eth->h_source, evt->src_mac);
 613	eth->h_proto = cpu_to_be16(ETH_P_PAE);
 614	memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
 615	skb->protocol = eth_type_trans(skb, ndev);
 616	if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
 617		ndev->stats.rx_packets++;
 618		ndev->stats.rx_bytes += sz;
 619		if (stats) {
 620			stats->rx_packets++;
 621			stats->rx_bytes += sz;
 622		}
 623	} else {
 624		ndev->stats.rx_dropped++;
 625		if (stats)
 626			stats->rx_dropped++;
 627	}
 628}
 629
 630static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 631{
 632	struct wmi_vring_en_event *evt = d;
 633	u8 vri = evt->vring_index;
 634
 635	wil_dbg_wmi(wil, "Enable vring %d\n", vri);
 636
 637	if (vri >= ARRAY_SIZE(wil->vring_tx)) {
 638		wil_err(wil, "Enable for invalid vring %d\n", vri);
 639		return;
 640	}
 641	wil->vring_tx_data[vri].dot1x_open = true;
 642	if (vri == wil->bcast_vring) /* no BA for bcast */
 643		return;
 644	if (agg_wsize >= 0)
 645		wil_addba_tx_request(wil, vri, agg_wsize);
 646}
 647
 648static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
 649			      int len)
 650{
 651	struct wmi_vring_ba_status_event *evt = d;
 652	struct vring_tx_data *txdata;
 653
 654	wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
 655		    evt->ringid,
 656		    evt->status == WMI_BA_AGREED ? "OK" : "N/A",
 657		    evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
 658		    evt->amsdu ? "+" : "-");
 659
 660	if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
 661		wil_err(wil, "invalid ring id %d\n", evt->ringid);
 662		return;
 663	}
 664
 665	if (evt->status != WMI_BA_AGREED) {
 666		evt->ba_timeout = 0;
 667		evt->agg_wsize = 0;
 668		evt->amsdu = 0;
 669	}
 670
 671	txdata = &wil->vring_tx_data[evt->ringid];
 672
 673	txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
 674	txdata->agg_wsize = evt->agg_wsize;
 675	txdata->agg_amsdu = evt->amsdu;
 676	txdata->addba_in_progress = false;
 677}
 678
 679static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
 680				 int len)
 681{
 682	struct wmi_rcp_addba_req_event *evt = d;
 683
 684	wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
 685			     evt->ba_param_set, evt->ba_timeout,
 686			     evt->ba_seq_ctrl);
 687}
 688
 689static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
 690__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 691{
 692	struct wmi_delba_event *evt = d;
 693	u8 cid, tid;
 694	u16 reason = __le16_to_cpu(evt->reason);
 695	struct wil_sta_info *sta;
 696	struct wil_tid_ampdu_rx *r;
 697
 698	might_sleep();
 699	parse_cidxtid(evt->cidxtid, &cid, &tid);
 700	wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
 701		    cid, tid,
 702		    evt->from_initiator ? "originator" : "recipient",
 703		    reason);
 704	if (!evt->from_initiator) {
 705		int i;
 706		/* find Tx vring it belongs to */
 707		for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
 708			if ((wil->vring2cid_tid[i][0] == cid) &&
 709			    (wil->vring2cid_tid[i][1] == tid)) {
 710				struct vring_tx_data *txdata =
 711					&wil->vring_tx_data[i];
 712
 713				wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
 714				txdata->agg_timeout = 0;
 715				txdata->agg_wsize = 0;
 716				txdata->addba_in_progress = false;
 717
 718				break; /* max. 1 matching ring */
 719			}
 720		}
 721		if (i >= ARRAY_SIZE(wil->vring2cid_tid))
 722			wil_err(wil, "DELBA: unable to find Tx vring\n");
 723		return;
 724	}
 725
 726	sta = &wil->sta[cid];
 727
 728	spin_lock_bh(&sta->tid_rx_lock);
 729
 730	r = sta->tid_rx[tid];
 731	sta->tid_rx[tid] = NULL;
 732	wil_tid_ampdu_rx_free(wil, r);
 733
 734	spin_unlock_bh(&sta->tid_rx_lock);
 735}
 736
 737/**
 738 * Some events are ignored for purpose; and need not be interpreted as
 739 * "unhandled events"
 740 */
 741static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
 742{
 743	wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
 744}
 745
 746static const struct {
 747	int eventid;
 748	void (*handler)(struct wil6210_priv *wil, int eventid,
 749			void *data, int data_len);
 750} wmi_evt_handlers[] = {
 751	{WMI_READY_EVENTID,		wmi_evt_ready},
 752	{WMI_FW_READY_EVENTID,			wmi_evt_ignore},
 753	{WMI_RX_MGMT_PACKET_EVENTID,	wmi_evt_rx_mgmt},
 754	{WMI_TX_MGMT_PACKET_EVENTID,		wmi_evt_tx_mgmt},
 755	{WMI_SCAN_COMPLETE_EVENTID,	wmi_evt_scan_complete},
 756	{WMI_CONNECT_EVENTID,		wmi_evt_connect},
 757	{WMI_DISCONNECT_EVENTID,	wmi_evt_disconnect},
 758	{WMI_EAPOL_RX_EVENTID,		wmi_evt_eapol_rx},
 759	{WMI_BA_STATUS_EVENTID,		wmi_evt_ba_status},
 760	{WMI_RCP_ADDBA_REQ_EVENTID,	wmi_evt_addba_rx_req},
 761	{WMI_DELBA_EVENTID,		wmi_evt_delba},
 762	{WMI_VRING_EN_EVENTID,		wmi_evt_vring_en},
 763	{WMI_DATA_PORT_OPEN_EVENTID,		wmi_evt_ignore},
 764};
 765
 766/*
 767 * Run in IRQ context
 768 * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
 769 * that will be eventually handled by the @wmi_event_worker in the thread
 770 * context of thread "wil6210_wmi"
 771 */
 772void wmi_recv_cmd(struct wil6210_priv *wil)
 773{
 774	struct wil6210_mbox_ring_desc d_tail;
 775	struct wil6210_mbox_hdr hdr;
 776	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
 777	struct pending_wmi_event *evt;
 778	u8 *cmd;
 779	void __iomem *src;
 780	ulong flags;
 781	unsigned n;
 782	unsigned int num_immed_reply = 0;
 783
 784	if (!test_bit(wil_status_mbox_ready, wil->status)) {
 785		wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
 786		return;
 787	}
 788
 789	for (n = 0;; n++) {
 790		u16 len;
 791		bool q;
 792		bool immed_reply = false;
 793
 794		r->head = wil_r(wil, RGF_MBOX +
 795				offsetof(struct wil6210_mbox_ctl, rx.head));
 796		if (r->tail == r->head)
 797			break;
 798
 799		wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
 800			    r->head, r->tail);
 801		/* read cmd descriptor from tail */
 802		wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
 803				     sizeof(struct wil6210_mbox_ring_desc));
 804		if (d_tail.sync == 0) {
 805			wil_err(wil, "Mbox evt not owned by FW?\n");
 806			break;
 807		}
 808
 809		/* read cmd header from descriptor */
 810		if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
 811			wil_err(wil, "Mbox evt at 0x%08x?\n",
 812				le32_to_cpu(d_tail.addr));
 813			break;
 814		}
 815		len = le16_to_cpu(hdr.len);
 816		wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
 817			    le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
 818			    hdr.flags);
 819
 820		/* read cmd buffer from descriptor */
 821		src = wmi_buffer(wil, d_tail.addr) +
 822		      sizeof(struct wil6210_mbox_hdr);
 823		evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
 824					     event.wmi) + len, 4),
 825			      GFP_KERNEL);
 826		if (!evt)
 827			break;
 828
 829		evt->event.hdr = hdr;
 830		cmd = (void *)&evt->event.wmi;
 831		wil_memcpy_fromio_32(cmd, src, len);
 832		/* mark entry as empty */
 833		wil_w(wil, r->tail +
 834		      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
 835		/* indicate */
 836		if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
 837		    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
 838			struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
 839			u16 id = le16_to_cpu(wmi->id);
 840			u32 tstamp = le32_to_cpu(wmi->timestamp);
 841			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 842			if (wil->reply_id && wil->reply_id == id) {
 843				if (wil->reply_buf) {
 844					memcpy(wil->reply_buf, wmi,
 845					       min(len, wil->reply_size));
 846					immed_reply = true;
 847				}
 848			}
 849			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 850
 851			wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
 852				    id, wmi->mid, tstamp);
 853			trace_wil6210_wmi_event(wmi, &wmi[1],
 854						len - sizeof(*wmi));
 855		}
 856		wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
 857				 &evt->event.hdr, sizeof(hdr) + len, true);
 858
 859		/* advance tail */
 860		r->tail = r->base + ((r->tail - r->base +
 861			  sizeof(struct wil6210_mbox_ring_desc)) % r->size);
 862		wil_w(wil, RGF_MBOX +
 863		      offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
 864
 865		if (immed_reply) {
 866			wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
 867				    __func__, wil->reply_id);
 868			kfree(evt);
 869			num_immed_reply++;
 870			complete(&wil->wmi_call);
 871		} else {
 872			/* add to the pending list */
 873			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
 874			list_add_tail(&evt->list, &wil->pending_wmi_ev);
 875			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 876			q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
 877			wil_dbg_wmi(wil, "queue_work -> %d\n", q);
 878		}
 879	}
 880	/* normally, 1 event per IRQ should be processed */
 881	wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__,
 882		    n - num_immed_reply, num_immed_reply);
 883}
 884
 885int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 886	     u16 reply_id, void *reply, u8 reply_size, int to_msec)
 887{
 888	int rc;
 889	unsigned long remain;
 890
 891	mutex_lock(&wil->wmi_mutex);
 892
 893	spin_lock(&wil->wmi_ev_lock);
 894	wil->reply_id = reply_id;
 895	wil->reply_buf = reply;
 896	wil->reply_size = reply_size;
 897	spin_unlock(&wil->wmi_ev_lock);
 898
 899	rc = __wmi_send(wil, cmdid, buf, len);
 900	if (rc)
 901		goto out;
 902
 903	remain = wait_for_completion_timeout(&wil->wmi_call,
 904					     msecs_to_jiffies(to_msec));
 905	if (0 == remain) {
 906		wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
 907			cmdid, reply_id, to_msec);
 908		rc = -ETIME;
 909	} else {
 910		wil_dbg_wmi(wil,
 911			    "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
 912			    cmdid, reply_id,
 913			    to_msec - jiffies_to_msecs(remain));
 914	}
 915
 916out:
 917	spin_lock(&wil->wmi_ev_lock);
 918	wil->reply_id = 0;
 919	wil->reply_buf = NULL;
 920	wil->reply_size = 0;
 921	spin_unlock(&wil->wmi_ev_lock);
 922
 923	mutex_unlock(&wil->wmi_mutex);
 924
 925	return rc;
 926}
 927
 928int wmi_echo(struct wil6210_priv *wil)
 929{
 930	struct wmi_echo_cmd cmd = {
 931		.value = cpu_to_le32(0x12345678),
 932	};
 933
 934	return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
 935			WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
 936}
 937
 938int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 939{
 940	struct wmi_set_mac_address_cmd cmd;
 941
 942	ether_addr_copy(cmd.mac, addr);
 943
 944	wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
 945
 946	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
 947}
 948
 949int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 950		  u8 chan, u8 hidden_ssid)
 951{
 952	int rc;
 953
 954	struct wmi_pcp_start_cmd cmd = {
 955		.bcon_interval = cpu_to_le16(bi),
 956		.network_type = wmi_nettype,
 957		.disable_sec_offload = 1,
 958		.channel = chan - 1,
 959		.pcp_max_assoc_sta = max_assoc_sta,
 960		.hidden_ssid = hidden_ssid,
 961	};
 962	struct {
 963		struct wil6210_mbox_hdr_wmi wmi;
 964		struct wmi_pcp_started_event evt;
 965	} __packed reply;
 966
 967	if (!wil->privacy)
 968		cmd.disable_sec = 1;
 969
 970	if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
 971	    (cmd.pcp_max_assoc_sta <= 0)) {
 972		wil_info(wil,
 973			 "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
 974			 max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
 975		cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
 976	}
 977
 978	/*
 979	 * Processing time may be huge, in case of secure AP it takes about
 980	 * 3500ms for FW to start AP
 981	 */
 982	rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
 983		      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
 984	if (rc)
 985		return rc;
 986
 987	if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
 988		rc = -EINVAL;
 989
 990	return rc;
 991}
 992
 993int wmi_pcp_stop(struct wil6210_priv *wil)
 994{
 995	return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
 996			WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
 997}
 998
 999int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
1000{
1001	struct wmi_set_ssid_cmd cmd = {
1002		.ssid_len = cpu_to_le32(ssid_len),
1003	};
1004
1005	if (ssid_len > sizeof(cmd.ssid))
1006		return -EINVAL;
1007
1008	memcpy(cmd.ssid, ssid, ssid_len);
1009
1010	return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
1011}
1012
1013int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
1014{
1015	int rc;
1016	struct {
1017		struct wil6210_mbox_hdr_wmi wmi;
1018		struct wmi_set_ssid_cmd cmd;
1019	} __packed reply;
1020	int len; /* reply.cmd.ssid_len in CPU order */
1021
1022	rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
1023		      &reply, sizeof(reply), 20);
1024	if (rc)
1025		return rc;
1026
1027	len = le32_to_cpu(reply.cmd.ssid_len);
1028	if (len > sizeof(reply.cmd.ssid))
1029		return -EINVAL;
1030
1031	*ssid_len = len;
1032	memcpy(ssid, reply.cmd.ssid, len);
1033
1034	return 0;
1035}
1036
1037int wmi_set_channel(struct wil6210_priv *wil, int channel)
1038{
1039	struct wmi_set_pcp_channel_cmd cmd = {
1040		.channel = channel - 1,
1041	};
1042
1043	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
1044}
1045
1046int wmi_get_channel(struct wil6210_priv *wil, int *channel)
1047{
1048	int rc;
1049	struct {
1050		struct wil6210_mbox_hdr_wmi wmi;
1051		struct wmi_set_pcp_channel_cmd cmd;
1052	} __packed reply;
1053
1054	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
1055		      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
1056	if (rc)
1057		return rc;
1058
1059	if (reply.cmd.channel > 3)
1060		return -EINVAL;
1061
1062	*channel = reply.cmd.channel + 1;
1063
1064	return 0;
1065}
1066
1067int wmi_p2p_cfg(struct wil6210_priv *wil, int channel)
1068{
1069	struct wmi_p2p_cfg_cmd cmd = {
1070		.discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD,
1071		.channel = channel - 1,
1072	};
1073
1074	return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd));
1075}
1076
1077int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
1078		       const void *mac_addr, int key_usage)
1079{
1080	struct wmi_delete_cipher_key_cmd cmd = {
1081		.key_index = key_index,
1082	};
1083
1084	if (mac_addr)
1085		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1086
1087	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1088}
1089
1090int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
1091		       const void *mac_addr, int key_len, const void *key,
1092		       int key_usage)
1093{
1094	struct wmi_add_cipher_key_cmd cmd = {
1095		.key_index = key_index,
1096		.key_usage = key_usage,
1097		.key_len = key_len,
1098	};
1099
1100	if (!key || (key_len > sizeof(cmd.key)))
1101		return -EINVAL;
1102
1103	memcpy(cmd.key, key, key_len);
1104	if (mac_addr)
1105		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
1106
1107	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
1108}
1109
1110int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
1111{
1112	static const char *const names[] = {
1113		[WMI_FRAME_BEACON]	= "BEACON",
1114		[WMI_FRAME_PROBE_REQ]	= "PROBE_REQ",
1115		[WMI_FRAME_PROBE_RESP]	= "WMI_FRAME_PROBE_RESP",
1116		[WMI_FRAME_ASSOC_REQ]	= "WMI_FRAME_ASSOC_REQ",
1117		[WMI_FRAME_ASSOC_RESP]	= "WMI_FRAME_ASSOC_RESP",
1118	};
1119	int rc;
1120	u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
1121	struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
1122
1123	if (!cmd) {
1124		rc = -ENOMEM;
1125		goto out;
1126	}
1127	if (!ie)
1128		ie_len = 0;
1129
1130	cmd->mgmt_frm_type = type;
1131	/* BUG: FW API define ieLen as u8. Will fix FW */
1132	cmd->ie_len = cpu_to_le16(ie_len);
1133	memcpy(cmd->ie_info, ie, ie_len);
1134	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
1135	kfree(cmd);
1136out:
1137	if (rc) {
1138		const char *name = type < ARRAY_SIZE(names) ?
1139				   names[type] : "??";
1140		wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
1141	}
1142
1143	return rc;
1144}
1145
1146/**
1147 * wmi_rxon - turn radio on/off
1148 * @on:		turn on if true, off otherwise
1149 *
1150 * Only switch radio. Channel should be set separately.
1151 * No timeout for rxon - radio turned on forever unless some other call
1152 * turns it off
1153 */
1154int wmi_rxon(struct wil6210_priv *wil, bool on)
1155{
1156	int rc;
1157	struct {
1158		struct wil6210_mbox_hdr_wmi wmi;
1159		struct wmi_listen_started_event evt;
1160	} __packed reply;
1161
1162	wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off");
1163
1164	if (on) {
1165		rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
1166			      WMI_LISTEN_STARTED_EVENTID,
1167			      &reply, sizeof(reply), 100);
1168		if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
1169			rc = -EINVAL;
1170	} else {
1171		rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
1172			      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
1173	}
1174
1175	return rc;
1176}
1177
1178int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
1179{
1180	struct wireless_dev *wdev = wil->wdev;
1181	struct net_device *ndev = wil_to_ndev(wil);
1182	struct wmi_cfg_rx_chain_cmd cmd = {
1183		.action = WMI_RX_CHAIN_ADD,
1184		.rx_sw_ring = {
1185			.max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
1186			.ring_mem_base = cpu_to_le64(vring->pa),
1187			.ring_size = cpu_to_le16(vring->size),
1188		},
1189		.mid = 0, /* TODO - what is it? */
1190		.decap_trans_type = WMI_DECAP_TYPE_802_3,
1191		.reorder_type = WMI_RX_SW_REORDER,
1192		.host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
1193	};
1194	struct {
1195		struct wil6210_mbox_hdr_wmi wmi;
1196		struct wmi_cfg_rx_chain_done_event evt;
1197	} __packed evt;
1198	int rc;
1199
1200	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
1201		struct ieee80211_channel *ch = wdev->preset_chandef.chan;
1202
1203		cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
1204		if (ch)
1205			cmd.sniffer_cfg.channel = ch->hw_value - 1;
1206		cmd.sniffer_cfg.phy_info_mode =
1207			cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
1208		cmd.sniffer_cfg.phy_support =
1209			cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
1210				    ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
1211	} else {
1212		/* Initialize offload (in non-sniffer mode).
1213		 * Linux IP stack always calculates IP checksum
1214		 * HW always calculate TCP/UDP checksum
1215		 */
1216		cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
1217	}
1218
1219	if (rx_align_2)
1220		cmd.l2_802_3_offload_ctrl |=
1221				L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
1222
1223	/* typical time for secure PCP is 840ms */
1224	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
1225		      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
1226	if (rc)
1227		return rc;
1228
1229	vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
1230
1231	wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
1232		     le32_to_cpu(evt.evt.status), vring->hwtail);
1233
1234	if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
1235		rc = -EINVAL;
1236
1237	return rc;
1238}
1239
1240int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
1241{
1242	int rc;
1243	struct wmi_temp_sense_cmd cmd = {
1244		.measure_baseband_en = cpu_to_le32(!!t_bb),
1245		.measure_rf_en = cpu_to_le32(!!t_rf),
1246		.measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
1247	};
1248	struct {
1249		struct wil6210_mbox_hdr_wmi wmi;
1250		struct wmi_temp_sense_done_event evt;
1251	} __packed reply;
1252
1253	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
1254		      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
1255	if (rc)
1256		return rc;
1257
1258	if (t_bb)
1259		*t_bb = le32_to_cpu(reply.evt.baseband_t1000);
1260	if (t_rf)
1261		*t_rf = le32_to_cpu(reply.evt.rf_t1000);
1262
1263	return 0;
1264}
1265
1266int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
1267		       bool full_disconnect)
1268{
1269	int rc;
1270	u16 reason_code;
1271	struct wmi_disconnect_sta_cmd cmd = {
1272		.disconnect_reason = cpu_to_le16(reason),
1273	};
1274	struct {
1275		struct wil6210_mbox_hdr_wmi wmi;
1276		struct wmi_disconnect_event evt;
1277	} __packed reply;
1278
1279	ether_addr_copy(cmd.dst_mac, mac);
1280
1281	wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason);
1282
1283	rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd),
1284		      WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000);
1285	/* failure to disconnect in reasonable time treated as FW error */
1286	if (rc) {
1287		wil_fw_error_recovery(wil);
1288		return rc;
1289	}
1290
1291	if (full_disconnect) {
1292		/* call event handler manually after processing wmi_call,
1293		 * to avoid deadlock - disconnect event handler acquires
1294		 * wil->mutex while it is already held here
1295		 */
1296		reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
1297
1298		wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
1299			    reply.evt.bssid, reason_code,
1300			    reply.evt.disconnect_reason);
1301
1302		wil->sinfo_gen++;
1303		wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
1304	}
1305	return 0;
1306}
1307
1308int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
1309{
1310	struct wmi_vring_ba_en_cmd cmd = {
1311		.ringid = ringid,
1312		.agg_max_wsize = size,
1313		.ba_timeout = cpu_to_le16(timeout),
1314		.amsdu = 0,
1315	};
1316
1317	wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__,
1318		    ringid, size, timeout);
1319
1320	return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
1321}
1322
1323int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
1324{
1325	struct wmi_vring_ba_dis_cmd cmd = {
1326		.ringid = ringid,
1327		.reason = cpu_to_le16(reason),
1328	};
1329
1330	wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__,
1331		    ringid, reason);
1332
1333	return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
1334}
1335
1336int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
1337{
1338	struct wmi_rcp_delba_cmd cmd = {
1339		.cidxtid = cidxtid,
1340		.reason = cpu_to_le16(reason),
1341	};
1342
1343	wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__,
1344		    cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason);
1345
1346	return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
1347}
1348
1349int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
1350		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
1351{
1352	int rc;
1353	struct wmi_rcp_addba_resp_cmd cmd = {
1354		.cidxtid = mk_cidxtid(cid, tid),
1355		.dialog_token = token,
1356		.status_code = cpu_to_le16(status),
1357		/* bit 0: A-MSDU supported
1358		 * bit 1: policy (should be 0 for us)
1359		 * bits 2..5: TID
1360		 * bits 6..15: buffer size
1361		 */
1362		.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
1363					    (agg_wsize << 6)),
1364		.ba_timeout = cpu_to_le16(timeout),
1365	};
1366	struct {
1367		struct wil6210_mbox_hdr_wmi wmi;
1368		struct wmi_rcp_addba_resp_sent_event evt;
1369	} __packed reply;
1370
1371	wil_dbg_wmi(wil,
1372		    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
1373		    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
1374
1375	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
1376		      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
1377		      100);
1378	if (rc)
1379		return rc;
1380
1381	if (reply.evt.status) {
1382		wil_err(wil, "ADDBA response failed with status %d\n",
1383			le16_to_cpu(reply.evt.status));
1384		rc = -EINVAL;
1385	}
1386
1387	return rc;
1388}
1389
1390void wmi_event_flush(struct wil6210_priv *wil)
1391{
1392	struct pending_wmi_event *evt, *t;
1393
1394	wil_dbg_wmi(wil, "%s()\n", __func__);
1395
1396	list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
1397		list_del(&evt->list);
1398		kfree(evt);
1399	}
1400}
1401
1402static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
1403				 void *d, int len)
1404{
1405	uint i;
1406
1407	for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
1408		if (wmi_evt_handlers[i].eventid == id) {
1409			wmi_evt_handlers[i].handler(wil, id, d, len);
1410			return true;
1411		}
1412	}
1413
1414	return false;
1415}
1416
1417static void wmi_event_handle(struct wil6210_priv *wil,
1418			     struct wil6210_mbox_hdr *hdr)
1419{
1420	u16 len = le16_to_cpu(hdr->len);
1421
1422	if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
1423	    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
1424		struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
1425		void *evt_data = (void *)(&wmi[1]);
1426		u16 id = le16_to_cpu(wmi->id);
1427
1428		wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
1429			    id, wil->reply_id);
1430		/* check if someone waits for this event */
1431		if (wil->reply_id && wil->reply_id == id) {
1432			WARN_ON(wil->reply_buf);
1433			wmi_evt_call_handler(wil, id, evt_data,
1434					     len - sizeof(*wmi));
1435			wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
1436				    __func__, id);
1437			complete(&wil->wmi_call);
1438			return;
1439		}
1440		/* unsolicited event */
1441		/* search for handler */
1442		if (!wmi_evt_call_handler(wil, id, evt_data,
1443					  len - sizeof(*wmi))) {
1444			wil_info(wil, "Unhandled event 0x%04x\n", id);
1445		}
1446	} else {
1447		wil_err(wil, "Unknown event type\n");
1448		print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
1449			       hdr, sizeof(*hdr) + len, true);
1450	}
1451}
1452
1453/*
1454 * Retrieve next WMI event from the pending list
1455 */
1456static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
1457{
1458	ulong flags;
1459	struct list_head *ret = NULL;
1460
1461	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
1462
1463	if (!list_empty(&wil->pending_wmi_ev)) {
1464		ret = wil->pending_wmi_ev.next;
1465		list_del(ret);
1466	}
1467
1468	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
1469
1470	return ret;
1471}
1472
1473/*
1474 * Handler for the WMI events
1475 */
1476void wmi_event_worker(struct work_struct *work)
1477{
1478	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
1479						 wmi_event_worker);
1480	struct pending_wmi_event *evt;
1481	struct list_head *lh;
1482
1483	wil_dbg_wmi(wil, "Start %s\n", __func__);
1484	while ((lh = next_wmi_ev(wil)) != NULL) {
1485		evt = list_entry(lh, struct pending_wmi_event, list);
1486		wmi_event_handle(wil, &evt->event.hdr);
1487		kfree(evt);
1488	}
1489	wil_dbg_wmi(wil, "Finished %s\n", __func__);
1490}