Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
   1/*
   2 * Intel Wireless Multicomm 3200 WiFi driver
   3 *
   4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
   5 *
   6 * Redistribution and use in source and binary forms, with or without
   7 * modification, are permitted provided that the following conditions
   8 * are met:
   9 *
  10 *   * Redistributions of source code must retain the above copyright
  11 *     notice, this list of conditions and the following disclaimer.
  12 *   * Redistributions in binary form must reproduce the above copyright
  13 *     notice, this list of conditions and the following disclaimer in
  14 *     the documentation and/or other materials provided with the
  15 *     distribution.
  16 *   * Neither the name of Intel Corporation nor the names of its
  17 *     contributors may be used to endorse or promote products derived
  18 *     from this software without specific prior written permission.
  19 *
  20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31 *
  32 *
  33 * Intel Corporation <ilw@linux.intel.com>
  34 * Samuel Ortiz <samuel.ortiz@intel.com>
  35 * Zhu Yi <yi.zhu@intel.com>
  36 *
  37 */
  38
  39#include <linux/kernel.h>
  40#include <linux/netdevice.h>
  41#include <linux/sched.h>
  42#include <linux/etherdevice.h>
  43#include <linux/wireless.h>
  44#include <linux/ieee80211.h>
  45#include <linux/if_arp.h>
  46#include <linux/list.h>
  47#include <linux/slab.h>
  48#include <net/iw_handler.h>
  49
  50#include "iwm.h"
  51#include "debug.h"
  52#include "hal.h"
  53#include "umac.h"
  54#include "lmac.h"
  55#include "commands.h"
  56#include "rx.h"
  57#include "cfg80211.h"
  58#include "eeprom.h"
  59
  60static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr)
  61{
  62	if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) ||
  63	    (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL))
  64		return -EINVAL;
  65
  66	return 0;
  67}
  68
  69static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr)
  70{
  71	return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr),
  72		     16);
  73}
  74
  75/*
  76 * Notification handlers:
  77 *
  78 * For every possible notification we can receive from the
  79 * target, we have a handler.
  80 * When we get a target notification, and there is no one
  81 * waiting for it, it's just processed through the rx code
  82 * path:
  83 *
  84 * iwm_rx_handle()
  85 *  -> iwm_rx_handle_umac()
  86 *      -> iwm_rx_handle_wifi()
  87 *          -> iwm_rx_handle_resp()
  88 *              -> iwm_ntf_*()
  89 *
  90 *      OR
  91 *
  92 *      -> iwm_rx_handle_non_wifi()
  93 *
  94 * If there are processes waiting for this notification, then
  95 * iwm_rx_handle_wifi() just wakes those processes up and they
  96 * grab the pending notification.
  97 */
  98static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
  99			 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 100{
 101	struct iwm_umac_notif_error *error;
 102	struct iwm_fw_error_hdr *fw_err;
 103
 104	error = (struct iwm_umac_notif_error *)buf;
 105	fw_err = &error->err;
 106
 107	memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
 108
 109	IWM_ERR(iwm, "%cMAC FW ERROR:\n",
 110	 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
 111	IWM_ERR(iwm, "\tCategory:    %d\n", le32_to_cpu(fw_err->category));
 112	IWM_ERR(iwm, "\tStatus:      0x%x\n", le32_to_cpu(fw_err->status));
 113	IWM_ERR(iwm, "\tPC:          0x%x\n", le32_to_cpu(fw_err->pc));
 114	IWM_ERR(iwm, "\tblink1:      %d\n", le32_to_cpu(fw_err->blink1));
 115	IWM_ERR(iwm, "\tblink2:      %d\n", le32_to_cpu(fw_err->blink2));
 116	IWM_ERR(iwm, "\tilink1:      %d\n", le32_to_cpu(fw_err->ilink1));
 117	IWM_ERR(iwm, "\tilink2:      %d\n", le32_to_cpu(fw_err->ilink2));
 118	IWM_ERR(iwm, "\tData1:       0x%x\n", le32_to_cpu(fw_err->data1));
 119	IWM_ERR(iwm, "\tData2:       0x%x\n", le32_to_cpu(fw_err->data2));
 120	IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num));
 121	IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status));
 122	IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
 123	IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
 124
 125	iwm_resetting(iwm);
 126
 127	return 0;
 128}
 129
 130static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf,
 131			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 132{
 133	struct iwm_umac_notif_alive *alive_resp =
 134			(struct iwm_umac_notif_alive *)(buf);
 135	u16 status = le16_to_cpu(alive_resp->status);
 136
 137	if (status == UMAC_NTFY_ALIVE_STATUS_ERR) {
 138		IWM_ERR(iwm, "Receive error UMAC_ALIVE\n");
 139		return -EIO;
 140	}
 141
 142	iwm_tx_credit_init_pools(iwm, alive_resp);
 143
 144	return 0;
 145}
 146
 147static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
 148				 unsigned long buf_size,
 149				 struct iwm_wifi_cmd *cmd)
 150{
 151	struct wiphy *wiphy = iwm_to_wiphy(iwm);
 152	struct iwm_umac_notif_init_complete *init_complete =
 153			(struct iwm_umac_notif_init_complete *)(buf);
 154	u16 status = le16_to_cpu(init_complete->status);
 155	bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR);
 156
 157	if (blocked)
 158		IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
 159	else
 160		IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
 161
 162	wiphy_rfkill_set_hw_state(wiphy, blocked);
 163
 164	return 0;
 165}
 166
 167static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf,
 168				    unsigned long buf_size,
 169				    struct iwm_wifi_cmd *cmd)
 170{
 171	int pool_nr, total_freed_pages;
 172	unsigned long pool_map;
 173	int i, id;
 174	struct iwm_umac_notif_page_dealloc *dealloc =
 175			(struct iwm_umac_notif_page_dealloc *)buf;
 176
 177	pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT);
 178	pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK);
 179
 180	IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, "
 181		   "update map 0x%lx\n", pool_nr, pool_map);
 182
 183	spin_lock(&iwm->tx_credit.lock);
 184
 185	for (i = 0; i < pool_nr; i++) {
 186		id = GET_VAL32(dealloc->grp_info[i],
 187			       UMAC_DEALLOC_NTFY_GROUP_NUM);
 188		if (test_bit(id, &pool_map)) {
 189			total_freed_pages = GET_VAL32(dealloc->grp_info[i],
 190					      UMAC_DEALLOC_NTFY_PAGE_CNT);
 191			iwm_tx_credit_inc(iwm, id, total_freed_pages);
 192		}
 193	}
 194
 195	spin_unlock(&iwm->tx_credit.lock);
 196
 197	return 0;
 198}
 199
 200static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf,
 201			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 202{
 203	IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n");
 204
 205	return 0;
 206}
 207
 208static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf,
 209				unsigned long buf_size,
 210				struct iwm_wifi_cmd *cmd)
 211{
 212	IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]);
 213
 214	return 0;
 215}
 216
 217static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
 218		      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 219{
 220	struct iwm_lmac_tx_resp *tx_resp;
 221	struct iwm_umac_wifi_in_hdr *hdr;
 222
 223	tx_resp = (struct iwm_lmac_tx_resp *)
 224		(buf + sizeof(struct iwm_umac_wifi_in_hdr));
 225	hdr = (struct iwm_umac_wifi_in_hdr *)buf;
 226
 227	IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
 228
 229	IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n",
 230		   le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
 231	IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
 232	IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n",
 233		   le16_to_cpu(tx_resp->retry_cnt));
 234	IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
 235	IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n",
 236		   le16_to_cpu(tx_resp->byte_cnt));
 237	IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
 238
 239	return 0;
 240}
 241
 242
 243static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf,
 244			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 245{
 246	u8 opcode;
 247	u8 *calib_buf;
 248	struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *)
 249				(buf + sizeof(struct iwm_umac_wifi_in_hdr));
 250
 251	opcode = hdr->opcode;
 252
 253	BUG_ON(opcode >= CALIBRATION_CMD_NUM ||
 254	       opcode < PHY_CALIBRATE_OPCODES_NUM);
 255
 256	IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n",
 257		    opcode);
 258
 259	buf_size -= sizeof(struct iwm_umac_wifi_in_hdr);
 260	calib_buf = iwm->calib_res[opcode].buf;
 261
 262	if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) {
 263		kfree(calib_buf);
 264		calib_buf = kzalloc(buf_size, GFP_KERNEL);
 265		if (!calib_buf) {
 266			IWM_ERR(iwm, "Memory allocation failed: calib_res\n");
 267			return -ENOMEM;
 268		}
 269		iwm->calib_res[opcode].buf = calib_buf;
 270		iwm->calib_res[opcode].size = buf_size;
 271	}
 272
 273	memcpy(calib_buf, hdr, buf_size);
 274	set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map);
 275
 276	return 0;
 277}
 278
 279static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf,
 280				  unsigned long buf_size,
 281				  struct iwm_wifi_cmd *cmd)
 282{
 283	IWM_DBG_NTF(iwm, DBG, "Calibration completed\n");
 284
 285	return 0;
 286}
 287
 288static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf,
 289			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 290{
 291	struct iwm_lmac_cal_cfg_resp *cal_resp;
 292
 293	cal_resp = (struct iwm_lmac_cal_cfg_resp *)
 294			(buf + sizeof(struct iwm_umac_wifi_in_hdr));
 295
 296	IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n",
 297		    le32_to_cpu(cal_resp->status));
 298
 299	return 0;
 300}
 301
 302static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf,
 303			       unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 304{
 305	struct iwm_umac_notif_wifi_status *status =
 306		(struct iwm_umac_notif_wifi_status *)buf;
 307
 308	iwm->core_enabled |= le16_to_cpu(status->status);
 309
 310	return 0;
 311}
 312
 313static struct iwm_rx_ticket_node *
 314iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
 315{
 316	struct iwm_rx_ticket_node *ticket_node;
 317
 318	ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL);
 319	if (!ticket_node) {
 320		IWM_ERR(iwm, "Couldn't allocate ticket node\n");
 321		return ERR_PTR(-ENOMEM);
 322	}
 323
 324	ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket),
 325				      GFP_KERNEL);
 326	if (!ticket_node->ticket) {
 327		IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
 328		kfree(ticket_node);
 329		return ERR_PTR(-ENOMEM);
 330	}
 331
 332	INIT_LIST_HEAD(&ticket_node->node);
 333
 334	return ticket_node;
 335}
 336
 337static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
 338{
 339	kfree(ticket_node->ticket);
 340	kfree(ticket_node);
 341}
 342
 343static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
 344{
 345	u8 id_hash = IWM_RX_ID_GET_HASH(id);
 346	struct iwm_rx_packet *packet;
 347
 348	spin_lock(&iwm->packet_lock[id_hash]);
 349	list_for_each_entry(packet, &iwm->rx_packets[id_hash], node)
 350		if (packet->id == id) {
 351			list_del(&packet->node);
 352			spin_unlock(&iwm->packet_lock[id_hash]);
 353			return packet;
 354		}
 355
 356	spin_unlock(&iwm->packet_lock[id_hash]);
 357	return NULL;
 358}
 359
 360static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf,
 361						 u32 size, u16 id)
 362{
 363	struct iwm_rx_packet *packet;
 364
 365	packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL);
 366	if (!packet) {
 367		IWM_ERR(iwm, "Couldn't allocate packet\n");
 368		return ERR_PTR(-ENOMEM);
 369	}
 370
 371	packet->skb = dev_alloc_skb(size);
 372	if (!packet->skb) {
 373		IWM_ERR(iwm, "Couldn't allocate packet SKB\n");
 374		kfree(packet);
 375		return ERR_PTR(-ENOMEM);
 376	}
 377
 378	packet->pkt_size = size;
 379
 380	skb_put(packet->skb, size);
 381	memcpy(packet->skb->data, buf, size);
 382	INIT_LIST_HEAD(&packet->node);
 383	packet->id = id;
 384
 385	return packet;
 386}
 387
 388void iwm_rx_free(struct iwm_priv *iwm)
 389{
 390	struct iwm_rx_ticket_node *ticket, *nt;
 391	struct iwm_rx_packet *packet, *np;
 392	int i;
 393
 394	spin_lock(&iwm->ticket_lock);
 395	list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
 396		list_del(&ticket->node);
 397		iwm_rx_ticket_node_free(ticket);
 398	}
 399	spin_unlock(&iwm->ticket_lock);
 400
 401	for (i = 0; i < IWM_RX_ID_HASH; i++) {
 402		spin_lock(&iwm->packet_lock[i]);
 403		list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
 404					 node) {
 405			list_del(&packet->node);
 406			kfree_skb(packet->skb);
 407			kfree(packet);
 408		}
 409		spin_unlock(&iwm->packet_lock[i]);
 410	}
 411}
 412
 413static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
 414			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 415{
 416	struct iwm_umac_notif_rx_ticket *ntf_rx_ticket =
 417		(struct iwm_umac_notif_rx_ticket *)buf;
 418	struct iwm_rx_ticket *ticket =
 419		(struct iwm_rx_ticket *)ntf_rx_ticket->tickets;
 420	int i, schedule_rx = 0;
 421
 422	for (i = 0; i < ntf_rx_ticket->num_tickets; i++) {
 423		struct iwm_rx_ticket_node *ticket_node;
 424
 425		switch (le16_to_cpu(ticket->action)) {
 426		case IWM_RX_TICKET_RELEASE:
 427		case IWM_RX_TICKET_DROP:
 428			/* We can push the packet to the stack */
 429			ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket);
 430			if (IS_ERR(ticket_node))
 431				return PTR_ERR(ticket_node);
 432
 433			IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
 434				   __le16_to_cpu(ticket->action) ==
 435							IWM_RX_TICKET_RELEASE ?
 436				   "RELEASE" : "DROP",
 437				   ticket->id);
 438			spin_lock(&iwm->ticket_lock);
 439			list_add_tail(&ticket_node->node, &iwm->rx_tickets);
 440			spin_unlock(&iwm->ticket_lock);
 441
 442			/*
 443			 * We received an Rx ticket, most likely there's
 444			 * a packet pending for it, it's not worth going
 445			 * through the packet hash list to double check.
 446			 * Let's just fire the rx worker..
 447			 */
 448			schedule_rx = 1;
 449
 450			break;
 451
 452		default:
 453			IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n",
 454				ticket->action);
 455		}
 456
 457		ticket++;
 458	}
 459
 460	if (schedule_rx)
 461		queue_work(iwm->rx_wq, &iwm->rx_worker);
 462
 463	return 0;
 464}
 465
 466static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
 467			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 468{
 469	struct iwm_umac_wifi_in_hdr *wifi_hdr;
 470	struct iwm_rx_packet *packet;
 471	u16 id, buf_offset;
 472	u32 packet_size;
 473	u8 id_hash;
 474
 475	IWM_DBG_RX(iwm, DBG, "\n");
 476
 477	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
 478	id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
 479	buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
 480	packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
 481
 482	IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
 483		   wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
 484	IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
 485	IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
 486
 487	packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id);
 488	if (IS_ERR(packet))
 489		return PTR_ERR(packet);
 490
 491	id_hash = IWM_RX_ID_GET_HASH(id);
 492	spin_lock(&iwm->packet_lock[id_hash]);
 493	list_add_tail(&packet->node, &iwm->rx_packets[id_hash]);
 494	spin_unlock(&iwm->packet_lock[id_hash]);
 495
 496	/* We might (unlikely) have received the packet _after_ the ticket */
 497	queue_work(iwm->rx_wq, &iwm->rx_worker);
 498
 499	return 0;
 500}
 501
 502/* MLME handlers */
 503static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
 504				unsigned long buf_size,
 505				struct iwm_wifi_cmd *cmd)
 506{
 507	struct iwm_umac_notif_assoc_start *start;
 508
 509	start = (struct iwm_umac_notif_assoc_start *)buf;
 510
 511	IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
 512		     start->bssid, le32_to_cpu(start->roam_reason));
 513
 514	wake_up_interruptible(&iwm->mlme_queue);
 515
 516	return 0;
 517}
 518
 519static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm)
 520{
 521	if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
 522	     iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
 523	    (iwm->umac_profile->sec.ucast_cipher ==
 524	     iwm->umac_profile->sec.mcast_cipher) &&
 525	    (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN))
 526	       return 1;
 527
 528       return 0;
 529}
 530
 531static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
 532				   unsigned long buf_size,
 533				   struct iwm_wifi_cmd *cmd)
 534{
 535	struct wiphy *wiphy = iwm_to_wiphy(iwm);
 536	struct ieee80211_channel *chan;
 537	struct iwm_umac_notif_assoc_complete *complete =
 538		(struct iwm_umac_notif_assoc_complete *)buf;
 539
 540	IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
 541		     complete->bssid, complete->status);
 542
 543	switch (le32_to_cpu(complete->status)) {
 544	case UMAC_ASSOC_COMPLETE_SUCCESS:
 545		chan = ieee80211_get_channel(wiphy,
 546			ieee80211_channel_to_frequency(complete->channel,
 547				complete->band == UMAC_BAND_2GHZ ?
 548					IEEE80211_BAND_2GHZ :
 549					IEEE80211_BAND_5GHZ));
 550		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
 551			/* Associated to a unallowed channel, disassociate. */
 552			__iwm_invalidate_mlme_profile(iwm);
 553			IWM_WARN(iwm, "Couldn't associate with %pM due to "
 554				 "channel %d is disabled. Check your local "
 555				 "regulatory setting.\n",
 556				 complete->bssid, complete->channel);
 557			goto failure;
 558		}
 559
 560		set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
 561		memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
 562		iwm->channel = complete->channel;
 563
 564		/* Internal roaming state, avoid notifying SME. */
 565		if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
 566		    && iwm->conf.mode == UMAC_MODE_BSS) {
 567			cancel_delayed_work(&iwm->disconnect);
 568			cfg80211_roamed(iwm_to_ndev(iwm), NULL,
 569					complete->bssid,
 570					iwm->req_ie, iwm->req_ie_len,
 571					iwm->resp_ie, iwm->resp_ie_len,
 572					GFP_KERNEL);
 573			break;
 574		}
 575
 576		iwm_link_on(iwm);
 577
 578		if (iwm->conf.mode == UMAC_MODE_IBSS)
 579			goto ibss;
 580
 581		if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
 582			cfg80211_connect_result(iwm_to_ndev(iwm),
 583						complete->bssid,
 584						iwm->req_ie, iwm->req_ie_len,
 585						iwm->resp_ie, iwm->resp_ie_len,
 586						WLAN_STATUS_SUCCESS,
 587						GFP_KERNEL);
 588		else
 589			cfg80211_roamed(iwm_to_ndev(iwm), NULL,
 590					complete->bssid,
 591					iwm->req_ie, iwm->req_ie_len,
 592					iwm->resp_ie, iwm->resp_ie_len,
 593					GFP_KERNEL);
 594		break;
 595	case UMAC_ASSOC_COMPLETE_FAILURE:
 596 failure:
 597		clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
 598		memset(iwm->bssid, 0, ETH_ALEN);
 599		iwm->channel = 0;
 600
 601		/* Internal roaming state, avoid notifying SME. */
 602		if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
 603		    && iwm->conf.mode == UMAC_MODE_BSS) {
 604			cancel_delayed_work(&iwm->disconnect);
 605			break;
 606		}
 607
 608		iwm_link_off(iwm);
 609
 610		if (iwm->conf.mode == UMAC_MODE_IBSS)
 611			goto ibss;
 612
 613		if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
 614			if (!iwm_is_open_wep_profile(iwm)) {
 615				cfg80211_connect_result(iwm_to_ndev(iwm),
 616					       complete->bssid,
 617					       NULL, 0, NULL, 0,
 618					       WLAN_STATUS_UNSPECIFIED_FAILURE,
 619					       GFP_KERNEL);
 620			} else {
 621				/* Let's try shared WEP auth */
 622				IWM_ERR(iwm, "Trying WEP shared auth\n");
 623				schedule_work(&iwm->auth_retry_worker);
 624			}
 625		else
 626			cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
 627					      GFP_KERNEL);
 628		break;
 629	default:
 630		break;
 631	}
 632
 633	clear_bit(IWM_STATUS_RESETTING, &iwm->status);
 634	return 0;
 635
 636 ibss:
 637	cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
 638	clear_bit(IWM_STATUS_RESETTING, &iwm->status);
 639	return 0;
 640}
 641
 642static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
 643				       unsigned long buf_size,
 644				       struct iwm_wifi_cmd *cmd)
 645{
 646	struct iwm_umac_notif_profile_invalidate *invalid;
 647	u32 reason;
 648
 649	invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
 650	reason = le32_to_cpu(invalid->reason);
 651
 652	IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason);
 653
 654	if (reason != UMAC_PROFILE_INVALID_REQUEST &&
 655	    test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status))
 656		cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL,
 657					0, WLAN_STATUS_UNSPECIFIED_FAILURE,
 658					GFP_KERNEL);
 659
 660	clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
 661	clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
 662
 663	iwm->umac_profile_active = 0;
 664	memset(iwm->bssid, 0, ETH_ALEN);
 665	iwm->channel = 0;
 666
 667	iwm_link_off(iwm);
 668
 669	wake_up_interruptible(&iwm->mlme_queue);
 670
 671	return 0;
 672}
 673
 674#define IWM_DISCONNECT_INTERVAL	(5 * HZ)
 675
 676static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf,
 677					  unsigned long buf_size,
 678					  struct iwm_wifi_cmd *cmd)
 679{
 680	IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
 681
 682	schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL);
 683
 684	return 0;
 685}
 686
 687static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
 688				  unsigned long buf_size,
 689				  struct iwm_wifi_cmd *cmd)
 690{
 691	int ret;
 692	struct iwm_umac_notif_scan_complete *scan_complete =
 693		(struct iwm_umac_notif_scan_complete *)buf;
 694	u32 result = le32_to_cpu(scan_complete->result);
 695
 696	IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n",
 697		     le32_to_cpu(scan_complete->type),
 698		     le32_to_cpu(scan_complete->result),
 699		     scan_complete->seq_num);
 700
 701	if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) {
 702		IWM_ERR(iwm, "Scan complete while device not scanning\n");
 703		return -EIO;
 704	}
 705	if (!iwm->scan_request)
 706		return 0;
 707
 708	ret = iwm_cfg80211_inform_bss(iwm);
 709
 710	cfg80211_scan_done(iwm->scan_request,
 711			   (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret);
 712	iwm->scan_request = NULL;
 713
 714	return ret;
 715}
 716
 717static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
 718				     unsigned long buf_size,
 719				     struct iwm_wifi_cmd *cmd)
 720{
 721	struct iwm_umac_notif_sta_info *umac_sta =
 722			(struct iwm_umac_notif_sta_info *)buf;
 723	struct iwm_sta_info *sta;
 724	int i;
 725
 726	switch (le32_to_cpu(umac_sta->opcode)) {
 727	case UMAC_OPCODE_ADD_MODIFY:
 728		sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
 729
 730		IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, "
 731			     "addr = %pM, qos = %d\n",
 732			     sta->valid ? "Modify" : "Add",
 733			     GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
 734			     GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
 735			     umac_sta->mac_addr,
 736			     umac_sta->flags & UMAC_STA_FLAG_QOS);
 737
 738		sta->valid = 1;
 739		sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS;
 740		sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR);
 741		memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN);
 742		break;
 743	case UMAC_OPCODE_REMOVE:
 744		IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, "
 745			     "addr = %pM\n",
 746			     GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
 747			     GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
 748			     umac_sta->mac_addr);
 749
 750		sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
 751
 752		if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN))
 753			sta->valid = 0;
 754
 755		break;
 756	case UMAC_OPCODE_CLEAR_ALL:
 757		for (i = 0; i < IWM_STA_TABLE_NUM; i++)
 758			iwm->sta_table[i].valid = 0;
 759
 760		break;
 761	default:
 762		break;
 763	}
 764
 765	return 0;
 766}
 767
 768static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf,
 769				unsigned long buf_size,
 770				struct iwm_wifi_cmd *cmd)
 771{
 772	struct wiphy *wiphy = iwm_to_wiphy(iwm);
 773
 774	IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n");
 775
 776	wiphy_rfkill_set_hw_state(wiphy, true);
 777
 778	return 0;
 779}
 780
 781static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
 782				     unsigned long buf_size,
 783				     struct iwm_wifi_cmd *cmd)
 784{
 785	struct wiphy *wiphy = iwm_to_wiphy(iwm);
 786	struct ieee80211_mgmt *mgmt;
 787	struct iwm_umac_notif_bss_info *umac_bss =
 788			(struct iwm_umac_notif_bss_info *)buf;
 789	struct ieee80211_channel *channel;
 790	struct ieee80211_supported_band *band;
 791	struct iwm_bss_info *bss;
 792	s32 signal;
 793	int freq;
 794	u16 frame_len = le16_to_cpu(umac_bss->frame_len);
 795	size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len;
 796
 797	mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
 798
 799	IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid);
 800	IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type));
 801	IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n",
 802		     le32_to_cpu(umac_bss->timestamp));
 803	IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n",
 804		     le16_to_cpu(umac_bss->table_idx));
 805	IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band);
 806	IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel);
 807	IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
 808	IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
 809
 810	list_for_each_entry(bss, &iwm->bss_list, node)
 811		if (bss->bss->table_idx == umac_bss->table_idx)
 812			break;
 813
 814	if (&bss->node != &iwm->bss_list) {
 815		/* Remove the old BSS entry, we will add it back later. */
 816		list_del(&bss->node);
 817		kfree(bss->bss);
 818	} else {
 819		/* New BSS entry */
 820
 821		bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL);
 822		if (!bss) {
 823			IWM_ERR(iwm, "Couldn't allocate bss_info\n");
 824			return -ENOMEM;
 825		}
 826	}
 827
 828	bss->bss = kzalloc(bss_len, GFP_KERNEL);
 829	if (!bss->bss) {
 830		kfree(bss);
 831		IWM_ERR(iwm, "Couldn't allocate bss\n");
 832		return -ENOMEM;
 833	}
 834
 835	INIT_LIST_HEAD(&bss->node);
 836	memcpy(bss->bss, umac_bss, bss_len);
 837
 838	if (umac_bss->band == UMAC_BAND_2GHZ)
 839		band = wiphy->bands[IEEE80211_BAND_2GHZ];
 840	else if (umac_bss->band == UMAC_BAND_5GHZ)
 841		band = wiphy->bands[IEEE80211_BAND_5GHZ];
 842	else {
 843		IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
 844		goto err;
 845	}
 846
 847	freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
 848	channel = ieee80211_get_channel(wiphy, freq);
 849	signal = umac_bss->rssi * 100;
 850
 851	bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel,
 852						 mgmt, frame_len,
 853						 signal, GFP_KERNEL);
 854	if (!bss->cfg_bss)
 855		goto err;
 856
 857	list_add_tail(&bss->node, &iwm->bss_list);
 858
 859	return 0;
 860 err:
 861	kfree(bss->bss);
 862	kfree(bss);
 863
 864	return -EINVAL;
 865}
 866
 867static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
 868			       unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 869{
 870	struct iwm_umac_notif_bss_removed *bss_rm =
 871		(struct iwm_umac_notif_bss_removed *)buf;
 872	struct iwm_bss_info *bss, *next;
 873	u16 table_idx;
 874	int i;
 875
 876	for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
 877		table_idx = le16_to_cpu(bss_rm->entries[i]) &
 878			    IWM_BSS_REMOVE_INDEX_MSK;
 879		list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
 880			if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
 881				struct ieee80211_mgmt *mgmt;
 882
 883				mgmt = (struct ieee80211_mgmt *)
 884					(bss->bss->frame_buf);
 885				IWM_DBG_MLME(iwm, ERR, "BSS removed: %pM\n",
 886					     mgmt->bssid);
 887				list_del(&bss->node);
 888				kfree(bss->bss);
 889				kfree(bss);
 890			}
 891	}
 892
 893	return 0;
 894}
 895
 896static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
 897			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 898{
 899	struct iwm_umac_notif_mgt_frame *mgt_frame =
 900			(struct iwm_umac_notif_mgt_frame *)buf;
 901	struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
 902
 903	IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
 904		    le16_to_cpu(mgt_frame->len));
 905
 906	if (ieee80211_is_assoc_req(mgt->frame_control)) {
 907		iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
 908				  - offsetof(struct ieee80211_mgmt,
 909					     u.assoc_req.variable);
 910		kfree(iwm->req_ie);
 911		iwm->req_ie = kmemdup(mgt->u.assoc_req.variable,
 912				      iwm->req_ie_len, GFP_KERNEL);
 913	} else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
 914		iwm->req_ie_len = le16_to_cpu(mgt_frame->len)
 915				  - offsetof(struct ieee80211_mgmt,
 916					     u.reassoc_req.variable);
 917		kfree(iwm->req_ie);
 918		iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable,
 919				      iwm->req_ie_len, GFP_KERNEL);
 920	} else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
 921		iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
 922				   - offsetof(struct ieee80211_mgmt,
 923					      u.assoc_resp.variable);
 924		kfree(iwm->resp_ie);
 925		iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable,
 926				       iwm->resp_ie_len, GFP_KERNEL);
 927	} else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
 928		iwm->resp_ie_len = le16_to_cpu(mgt_frame->len)
 929				   - offsetof(struct ieee80211_mgmt,
 930					      u.reassoc_resp.variable);
 931		kfree(iwm->resp_ie);
 932		iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
 933				       iwm->resp_ie_len, GFP_KERNEL);
 934	} else {
 935		IWM_ERR(iwm, "Unsupported management frame: 0x%x",
 936			le16_to_cpu(mgt->frame_control));
 937		return 0;
 938	}
 939
 940	return 0;
 941}
 942
 943static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
 944			unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 945{
 946	struct iwm_umac_notif_wifi_if *notif =
 947		(struct iwm_umac_notif_wifi_if *)buf;
 948
 949	switch (notif->status) {
 950	case WIFI_IF_NTFY_ASSOC_START:
 951		return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd);
 952	case WIFI_IF_NTFY_ASSOC_COMPLETE:
 953		return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd);
 954	case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
 955		return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
 956	case WIFI_IF_NTFY_CONNECTION_TERMINATED:
 957		return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd);
 958	case WIFI_IF_NTFY_SCAN_COMPLETE:
 959		return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
 960	case WIFI_IF_NTFY_STA_TABLE_CHANGE:
 961		return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd);
 962	case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
 963		IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
 964		break;
 965	case WIFI_IF_NTFY_RADIO_PREEMPTION:
 966		return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd);
 967	case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
 968		return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
 969	case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
 970		return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd);
 971		break;
 972	case WIFI_IF_NTFY_MGMT_FRAME:
 973		return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd);
 974	case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START:
 975	case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE:
 976	case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START:
 977	case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT:
 978	case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START:
 979	case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE:
 980	case WIFI_DBG_IF_NTFY_CNCT_ATC_START:
 981	case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION:
 982	case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP:
 983	case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP:
 984		IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n",
 985			     notif->status);
 986		break;
 987	default:
 988		IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status);
 989		break;
 990	}
 991
 992	return 0;
 993}
 994
 995#define IWM_STATS_UPDATE_INTERVAL		(2 * HZ)
 996
 997static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
 998			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
 999{
1000	struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf;
1001	struct iw_statistics *wstats = &iwm->wstats;
1002	u16 max_rate = 0;
1003	int i;
1004
1005	IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n");
1006
1007	if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
1008		for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) {
1009			max_rate = max_t(u16, max_rate,
1010					 max(le16_to_cpu(stats->tx_rate[i]),
1011					     le16_to_cpu(stats->rx_rate[i])));
1012		}
1013		/* UMAC passes rate info multiplies by 2 */
1014		iwm->rate = max_rate >> 1;
1015	}
1016	iwm->txpower = le32_to_cpu(stats->tx_power);
1017
1018	wstats->status = 0;
1019
1020	wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid);
1021	wstats->discard.code = le32_to_cpu(stats->rx_drop_decode);
1022	wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly);
1023	wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry);
1024
1025	wstats->miss.beacon = le32_to_cpu(stats->missed_beacons);
1026
1027	/* according to cfg80211 */
1028	if (stats->rssi_dbm < -110)
1029		wstats->qual.qual = 0;
1030	else if (stats->rssi_dbm > -40)
1031		wstats->qual.qual = 70;
1032	else
1033		wstats->qual.qual = stats->rssi_dbm + 110;
1034
1035	wstats->qual.level = stats->rssi_dbm;
1036	wstats->qual.noise = stats->noise_dbm;
1037	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1038
1039	schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL);
1040
1041	mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD));
1042
1043	return 0;
1044}
1045
1046static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
1047				unsigned long buf_size,
1048				struct iwm_wifi_cmd *cmd)
1049{
1050	struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy =
1051		(struct iwm_umac_cmd_eeprom_proxy *)
1052		(buf + sizeof(struct iwm_umac_wifi_in_hdr));
1053	struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr;
1054	u32 hdr_offset = le32_to_cpu(hdr->offset);
1055	u32 hdr_len = le32_to_cpu(hdr->len);
1056	u32 hdr_type = le32_to_cpu(hdr->type);
1057
1058	IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n",
1059		    hdr_type, hdr_len, hdr_offset);
1060
1061	if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
1062		return -EINVAL;
1063
1064	switch (hdr_type) {
1065	case IWM_UMAC_CMD_EEPROM_TYPE_READ:
1066		memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
1067		break;
1068	case IWM_UMAC_CMD_EEPROM_TYPE_WRITE:
1069	default:
1070		return -ENOTSUPP;
1071	}
1072
1073	return 0;
1074}
1075
1076static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
1077				     unsigned long buf_size,
1078				     struct iwm_wifi_cmd *cmd)
1079{
1080	struct iwm_umac_cmd_get_channel_list *ch_list =
1081			(struct iwm_umac_cmd_get_channel_list *)
1082			(buf + sizeof(struct iwm_umac_wifi_in_hdr));
1083	struct wiphy *wiphy = iwm_to_wiphy(iwm);
1084	struct ieee80211_supported_band *band;
1085	int i;
1086
1087	band = wiphy->bands[IEEE80211_BAND_2GHZ];
1088
1089	for (i = 0; i < band->n_channels; i++) {
1090		unsigned long ch_mask_0 =
1091			le32_to_cpu(ch_list->ch[0].channels_mask);
1092		unsigned long ch_mask_2 =
1093			le32_to_cpu(ch_list->ch[2].channels_mask);
1094
1095		if (!test_bit(i, &ch_mask_0))
1096			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
1097
1098		if (!test_bit(i, &ch_mask_2))
1099			band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
1100	}
1101
1102	band = wiphy->bands[IEEE80211_BAND_5GHZ];
1103
1104	for (i = 0; i < min(band->n_channels, 32); i++) {
1105		unsigned long ch_mask_1 =
1106			le32_to_cpu(ch_list->ch[1].channels_mask);
1107		unsigned long ch_mask_3 =
1108			le32_to_cpu(ch_list->ch[3].channels_mask);
1109
1110		if (!test_bit(i, &ch_mask_1))
1111			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
1112
1113		if (!test_bit(i, &ch_mask_3))
1114			band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
1115	}
1116
1117	return 0;
1118}
1119
1120static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
1121				  unsigned long buf_size,
1122				  struct iwm_wifi_cmd *cmd)
1123{
1124	struct iwm_umac_notif_stop_resume_tx *stp_res_tx =
1125		(struct iwm_umac_notif_stop_resume_tx *)buf;
1126	struct iwm_sta_info *sta_info;
1127	struct iwm_tid_info *tid_info;
1128	u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id);
1129	u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk);
1130	int bit, ret = 0;
1131	bool stop = false;
1132
1133	IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n"
1134		    "\tflags:       0x%x\n"
1135		    "\tSTA id:      %d\n"
1136		    "\tTID bitmask: 0x%x\n",
1137		    stp_res_tx->flags, stp_res_tx->sta_id,
1138		    stp_res_tx->stop_resume_tid_msk);
1139
1140	if (stp_res_tx->flags & UMAC_STOP_TX_FLAG)
1141		stop = true;
1142
1143	sta_info = &iwm->sta_table[sta_id];
1144	if (!sta_info->valid) {
1145		IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n",
1146			sta_id, stp_res_tx->sta_id);
1147		return -EINVAL;
1148	}
1149
1150	for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
1151		tid_info = &sta_info->tid_info[bit];
1152
1153		mutex_lock(&tid_info->mutex);
1154		tid_info->stopped = stop;
1155		mutex_unlock(&tid_info->mutex);
1156
1157		if (!stop) {
1158			struct iwm_tx_queue *txq;
1159			int queue = iwm_tid_to_queue(bit);
1160
1161			if (queue < 0)
1162				continue;
1163
1164			txq = &iwm->txq[queue];
1165			/*
1166			 * If we resume, we have to move our SKBs
1167			 * back to the tx queue and queue some work.
1168			 */
1169			spin_lock_bh(&txq->lock);
1170			skb_queue_splice_init(&txq->queue, &txq->stopped_queue);
1171			spin_unlock_bh(&txq->lock);
1172
1173			queue_work(txq->wq, &txq->worker);
1174		}
1175
1176	}
1177
1178	/* We send an ACK only for the stop case */
1179	if (stop)
1180		ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx);
1181
1182	return ret;
1183}
1184
1185static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
1186				   unsigned long buf_size,
1187				   struct iwm_wifi_cmd *cmd)
1188{
1189	struct iwm_umac_wifi_if *hdr;
1190
1191	if (cmd == NULL) {
1192		IWM_ERR(iwm, "Couldn't find expected wifi command\n");
1193		return -EINVAL;
1194	}
1195
1196	hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload;
1197
1198	IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
1199		    "oid is 0x%x\n", hdr->oid);
1200
1201	set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
1202	wake_up_interruptible(&iwm->wifi_ntfy_queue);
1203
1204	switch (hdr->oid) {
1205	case UMAC_WIFI_IF_CMD_SET_PROFILE:
1206		iwm->umac_profile_active = 1;
1207		break;
1208	default:
1209		break;
1210	}
1211
1212	return 0;
1213}
1214
1215#define CT_KILL_DELAY (30 * HZ)
1216static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
1217			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
1218{
1219	struct wiphy *wiphy = iwm_to_wiphy(iwm);
1220	struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
1221				(buf + sizeof(struct iwm_umac_wifi_in_hdr));
1222	u32 flags = le32_to_cpu(state->flags);
1223
1224	IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n",
1225		 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
1226		 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
1227
1228	if (flags & IWM_CARD_STATE_CTKILL_DISABLED) {
1229		/*
1230		 * We got a CTKILL event: We bring the interface down in
1231		 * oder to cool the device down, and try to bring it up
1232		 * 30 seconds later. If it's still too hot, we'll go through
1233		 * this code path again.
1234		 */
1235		cancel_delayed_work_sync(&iwm->ct_kill_delay);
1236		schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY);
1237	}
1238
1239	wiphy_rfkill_set_hw_state(wiphy, flags &
1240				  (IWM_CARD_STATE_HW_DISABLED |
1241				   IWM_CARD_STATE_CTKILL_DISABLED));
1242
1243	return 0;
1244}
1245
1246static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
1247			      unsigned long buf_size)
1248{
1249	struct iwm_umac_wifi_in_hdr *wifi_hdr;
1250	struct iwm_wifi_cmd *cmd;
1251	u8 source, cmd_id;
1252	u16 seq_num;
1253	u32 count;
1254
1255	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1256	cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1257	source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1258	if (source >= IWM_SRC_NUM) {
1259		IWM_CRIT(iwm, "invalid source %d\n", source);
1260		return -EINVAL;
1261	}
1262
1263	if (cmd_id == REPLY_RX_MPDU_CMD)
1264		trace_iwm_rx_packet(iwm, buf, buf_size);
1265	else if ((cmd_id == UMAC_NOTIFY_OPCODE_RX_TICKET) &&
1266		 (source == UMAC_HDI_IN_SOURCE_FW))
1267		trace_iwm_rx_ticket(iwm, buf, buf_size);
1268	else
1269		trace_iwm_rx_wifi_cmd(iwm, wifi_hdr);
1270
1271	count = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT);
1272	count += sizeof(struct iwm_umac_wifi_in_hdr) -
1273		 sizeof(struct iwm_dev_cmd_hdr);
1274	if (count > buf_size) {
1275		IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size);
1276		return -EINVAL;
1277	}
1278
1279	seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
1280
1281	IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
1282		   cmd_id, source, seq_num);
1283
1284	/*
1285	 * If this is a response to a previously sent command, there must
1286	 * be a pending command for this sequence number.
1287	 */
1288	cmd = iwm_get_pending_wifi_cmd(iwm, seq_num);
1289
1290	/* Notify the caller only for sync commands. */
1291	switch (source) {
1292	case UMAC_HDI_IN_SOURCE_FHRX:
1293		if (iwm->lmac_handlers[cmd_id] &&
1294		    test_bit(cmd_id, &iwm->lmac_handler_map[0]))
1295			return iwm_notif_send(iwm, cmd, cmd_id, source,
1296					      buf, count);
1297		break;
1298	case UMAC_HDI_IN_SOURCE_FW:
1299		if (iwm->umac_handlers[cmd_id] &&
1300		    test_bit(cmd_id, &iwm->umac_handler_map[0]))
1301			return iwm_notif_send(iwm, cmd, cmd_id, source,
1302					      buf, count);
1303		break;
1304	case UMAC_HDI_IN_SOURCE_UDMA:
1305		break;
1306	}
1307
1308	return iwm_rx_handle_resp(iwm, buf, count, cmd);
1309}
1310
1311int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
1312		       struct iwm_wifi_cmd *cmd)
1313{
1314	u8 source, cmd_id;
1315	struct iwm_umac_wifi_in_hdr *wifi_hdr;
1316	int ret = 0;
1317
1318	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1319	cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1320
1321	source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1322
1323	IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source);
1324
1325	switch (source) {
1326	case UMAC_HDI_IN_SOURCE_FHRX:
1327		if (iwm->lmac_handlers[cmd_id])
1328			ret = iwm->lmac_handlers[cmd_id]
1329					(iwm, buf, buf_size, cmd);
1330		break;
1331	case UMAC_HDI_IN_SOURCE_FW:
1332		if (iwm->umac_handlers[cmd_id])
1333			ret = iwm->umac_handlers[cmd_id]
1334					(iwm, buf, buf_size, cmd);
1335		break;
1336	case UMAC_HDI_IN_SOURCE_UDMA:
1337		ret = -EINVAL;
1338		break;
1339	}
1340
1341	kfree(cmd);
1342
1343	return ret;
1344}
1345
1346static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
1347				 unsigned long buf_size)
1348{
1349	u8 seq_num;
1350	struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
1351	struct iwm_nonwifi_cmd *cmd;
1352
1353	trace_iwm_rx_nonwifi_cmd(iwm, buf, buf_size);
1354	seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
1355
1356	/*
1357	 * We received a non wifi answer.
1358	 * Let's check if there's a pending command for it, and if so
1359	 * replace the command payload with the buffer, and then wake the
1360	 * callers up.
1361	 * That means we only support synchronised non wifi command response
1362	 * schemes.
1363	 */
1364	list_for_each_entry(cmd, &iwm->nonwifi_pending_cmd, pending)
1365		if (cmd->seq_num == seq_num) {
1366			cmd->resp_received = 1;
1367			cmd->buf.len = buf_size;
1368			memcpy(cmd->buf.hdr, buf, buf_size);
1369			wake_up_interruptible(&iwm->nonwifi_queue);
1370		}
1371
1372	return 0;
1373}
1374
1375static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf,
1376			      unsigned long buf_size)
1377{
1378	int ret = 0;
1379	u8 op_code;
1380	unsigned long buf_offset = 0;
1381	struct iwm_udma_in_hdr *hdr;
1382
1383	/*
1384	 * To allow for a more efficient bus usage, UMAC
1385	 * messages are encapsulated into UDMA ones. This
1386	 * way we can have several UMAC messages in one bus
1387	 * transfer.
1388	 * A UDMA frame size is always aligned on 16 bytes,
1389	 * and a UDMA frame must not start with a UMAC_PAD_TERMINAL
1390	 * word. This is how we parse a bus frame into several
1391	 * UDMA ones.
1392	 */
1393	while (buf_offset < buf_size) {
1394
1395		hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset);
1396
1397		if (iwm_rx_check_udma_hdr(hdr) < 0) {
1398			IWM_DBG_RX(iwm, DBG, "End of frame\n");
1399			break;
1400		}
1401
1402		op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE);
1403
1404		IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code);
1405
1406		if (op_code == UMAC_HDI_IN_OPCODE_WIFI) {
1407			ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset,
1408						  buf_size - buf_offset);
1409		} else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) {
1410			if (GET_VAL32(hdr->cmd,
1411				      UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) !=
1412			    UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) {
1413				IWM_ERR(iwm, "Incorrect hw signature\n");
1414				return -EINVAL;
1415			}
1416			ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset,
1417						     buf_size - buf_offset);
1418		} else {
1419			IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code);
1420			ret |= -EINVAL;
1421		}
1422
1423		buf_offset += iwm_rx_resp_size(hdr);
1424	}
1425
1426	return ret;
1427}
1428
1429int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
1430{
1431	struct iwm_udma_in_hdr *hdr;
1432
1433	hdr = (struct iwm_udma_in_hdr *)buf;
1434
1435	switch (le32_to_cpu(hdr->cmd)) {
1436	case UMAC_REBOOT_BARKER:
1437		if (test_bit(IWM_STATUS_READY, &iwm->status)) {
1438			IWM_ERR(iwm, "Unexpected BARKER\n");
1439
1440			schedule_work(&iwm->reset_worker);
1441
1442			return 0;
1443		}
1444
1445		return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
1446				      IWM_SRC_UDMA, buf, buf_size);
1447	case UMAC_ACK_BARKER:
1448		return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION,
1449				      IWM_SRC_UDMA, NULL, 0);
1450	default:
1451		IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd);
1452		return iwm_rx_handle_umac(iwm, buf, buf_size);
1453	}
1454
1455	return 0;
1456}
1457
1458static const iwm_handler iwm_umac_handlers[] =
1459{
1460	[UMAC_NOTIFY_OPCODE_ERROR]		= iwm_ntf_error,
1461	[UMAC_NOTIFY_OPCODE_ALIVE]		= iwm_ntf_umac_alive,
1462	[UMAC_NOTIFY_OPCODE_INIT_COMPLETE]	= iwm_ntf_init_complete,
1463	[UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS]	= iwm_ntf_wifi_status,
1464	[UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER]	= iwm_ntf_mlme,
1465	[UMAC_NOTIFY_OPCODE_PAGE_DEALLOC]	= iwm_ntf_tx_credit_update,
1466	[UMAC_NOTIFY_OPCODE_RX_TICKET]		= iwm_ntf_rx_ticket,
1467	[UMAC_CMD_OPCODE_RESET]			= iwm_ntf_umac_reset,
1468	[UMAC_NOTIFY_OPCODE_STATS]		= iwm_ntf_statistics,
1469	[UMAC_CMD_OPCODE_EEPROM_PROXY]		= iwm_ntf_eeprom_proxy,
1470	[UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST]	= iwm_ntf_channel_info_list,
1471	[UMAC_CMD_OPCODE_STOP_RESUME_STA_TX]	= iwm_ntf_stop_resume_tx,
1472	[REPLY_RX_MPDU_CMD]			= iwm_ntf_rx_packet,
1473	[UMAC_CMD_OPCODE_WIFI_IF_WRAPPER]	= iwm_ntf_wifi_if_wrapper,
1474};
1475
1476static const iwm_handler iwm_lmac_handlers[] =
1477{
1478	[REPLY_TX]				= iwm_ntf_tx,
1479	[REPLY_ALIVE]				= iwm_ntf_lmac_version,
1480	[CALIBRATION_RES_NOTIFICATION]		= iwm_ntf_calib_res,
1481	[CALIBRATION_COMPLETE_NOTIFICATION]	= iwm_ntf_calib_complete,
1482	[CALIBRATION_CFG_CMD]			= iwm_ntf_calib_cfg,
1483	[REPLY_RX_MPDU_CMD]			= iwm_ntf_rx_packet,
1484	[CARD_STATE_NOTIFICATION]		= iwm_ntf_card_state,
1485};
1486
1487void iwm_rx_setup_handlers(struct iwm_priv *iwm)
1488{
1489	iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers;
1490	iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers;
1491}
1492
1493static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len)
1494{
1495	struct ieee80211_hdr *hdr;
1496	unsigned int hdr_len;
1497
1498	hdr = (struct ieee80211_hdr *)skb->data;
1499
1500	if (!ieee80211_has_protected(hdr->frame_control))
1501		return;
1502
1503	hdr_len = ieee80211_hdrlen(hdr->frame_control);
1504	if (hdr_total_len <= hdr_len)
1505		return;
1506
1507	memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len);
1508	skb_pull(skb, (hdr_total_len - hdr_len));
1509}
1510
1511static void iwm_rx_adjust_packet(struct iwm_priv *iwm,
1512				 struct iwm_rx_packet *packet,
1513				 struct iwm_rx_ticket_node *ticket_node)
1514{
1515	u32 payload_offset = 0, payload_len;
1516	struct iwm_rx_ticket *ticket = ticket_node->ticket;
1517	struct iwm_rx_mpdu_hdr *mpdu_hdr;
1518	struct ieee80211_hdr *hdr;
1519
1520	mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data;
1521	payload_offset += sizeof(struct iwm_rx_mpdu_hdr);
1522	/* Padding is 0 or 2 bytes */
1523	payload_len = le16_to_cpu(mpdu_hdr->len) +
1524		(le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK);
1525	payload_len -= ticket->tail_len;
1526
1527	IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, "
1528		   "ticket offset:%d ticket tail len:%d\n",
1529		   payload_len, payload_offset, ticket->payload_offset,
1530		   ticket->tail_len);
1531
1532	IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len);
1533
1534	skb_pull(packet->skb, payload_offset);
1535	skb_trim(packet->skb, payload_len);
1536
1537	iwm_remove_iv(packet->skb, ticket->payload_offset);
1538
1539	hdr = (struct ieee80211_hdr *) packet->skb->data;
1540	if (ieee80211_is_data_qos(hdr->frame_control)) {
1541		/* UMAC handed QOS_DATA frame with 2 padding bytes appended
1542		 * to the qos_ctl field in IEEE 802.11 headers. */
1543		memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2,
1544			packet->skb->data,
1545			ieee80211_hdrlen(hdr->frame_control) -
1546			IEEE80211_QOS_CTL_LEN);
1547		hdr = (struct ieee80211_hdr *) skb_pull(packet->skb,
1548				IEEE80211_QOS_CTL_LEN + 2);
1549		hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
1550	}
1551
1552	IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ",
1553		    packet->skb->data, packet->skb->len);
1554}
1555
1556static void classify8023(struct sk_buff *skb)
1557{
1558	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1559
1560	if (ieee80211_is_data_qos(hdr->frame_control)) {
1561		u8 *qc = ieee80211_get_qos_ctl(hdr);
1562		/* frame has qos control */
1563		skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK;
1564	} else {
1565		skb->priority = 0;
1566	}
1567}
1568
1569static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb)
1570{
1571	struct wireless_dev *wdev = iwm_to_wdev(iwm);
1572	struct net_device *ndev = iwm_to_ndev(iwm);
1573	struct sk_buff_head list;
1574	struct sk_buff *frame;
1575
1576	IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len);
1577
1578	__skb_queue_head_init(&list);
1579	ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0,
1580									true);
1581
1582	while ((frame = __skb_dequeue(&list))) {
1583		ndev->stats.rx_packets++;
1584		ndev->stats.rx_bytes += frame->len;
1585
1586		frame->protocol = eth_type_trans(frame, ndev);
1587		frame->ip_summed = CHECKSUM_NONE;
1588		memset(frame->cb, 0, sizeof(frame->cb));
1589
1590		if (netif_rx_ni(frame) == NET_RX_DROP) {
1591			IWM_ERR(iwm, "Packet dropped\n");
1592			ndev->stats.rx_dropped++;
1593		}
1594	}
1595}
1596
1597static void iwm_rx_process_packet(struct iwm_priv *iwm,
1598				  struct iwm_rx_packet *packet,
1599				  struct iwm_rx_ticket_node *ticket_node)
1600{
1601	int ret;
1602	struct sk_buff *skb = packet->skb;
1603	struct wireless_dev *wdev = iwm_to_wdev(iwm);
1604	struct net_device *ndev = iwm_to_ndev(iwm);
1605
1606	IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id);
1607
1608	switch (le16_to_cpu(ticket_node->ticket->action)) {
1609	case IWM_RX_TICKET_RELEASE:
1610		IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
1611
1612		iwm_rx_adjust_packet(iwm, packet, ticket_node);
1613		skb->dev = iwm_to_ndev(iwm);
1614		classify8023(skb);
1615
1616		if (le16_to_cpu(ticket_node->ticket->flags) &
1617		    IWM_RX_TICKET_AMSDU_MSK) {
1618			iwm_rx_process_amsdu(iwm, skb);
1619			break;
1620		}
1621
1622		ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
1623		if (ret < 0) {
1624			IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
1625				   "%d\n", ret);
1626			kfree_skb(packet->skb);
1627			break;
1628		}
1629
1630		IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
1631
1632		ndev->stats.rx_packets++;
1633		ndev->stats.rx_bytes += skb->len;
1634
1635		skb->protocol = eth_type_trans(skb, ndev);
1636		skb->ip_summed = CHECKSUM_NONE;
1637		memset(skb->cb, 0, sizeof(skb->cb));
1638
1639		if (netif_rx_ni(skb) == NET_RX_DROP) {
1640			IWM_ERR(iwm, "Packet dropped\n");
1641			ndev->stats.rx_dropped++;
1642		}
1643		break;
1644	case IWM_RX_TICKET_DROP:
1645		IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n",
1646			   le16_to_cpu(ticket_node->ticket->flags));
1647		kfree_skb(packet->skb);
1648		break;
1649	default:
1650		IWM_ERR(iwm, "Unknown ticket action: %d\n",
1651			le16_to_cpu(ticket_node->ticket->action));
1652		kfree_skb(packet->skb);
1653	}
1654
1655	kfree(packet);
1656	iwm_rx_ticket_node_free(ticket_node);
1657}
1658
1659/*
1660 * Rx data processing:
1661 *
1662 * We're receiving Rx packet from the LMAC, and Rx ticket from
1663 * the UMAC.
1664 * To forward a target data packet upstream (i.e. to the
1665 * kernel network stack), we must have received an Rx ticket
1666 * that tells us we're allowed to release this packet (ticket
1667 * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates,
1668 * among other things, where valid data actually starts in the Rx
1669 * packet.
1670 */
1671void iwm_rx_worker(struct work_struct *work)
1672{
1673	struct iwm_priv *iwm;
1674	struct iwm_rx_ticket_node *ticket, *next;
1675
1676	iwm = container_of(work, struct iwm_priv, rx_worker);
1677
1678	/*
1679	 * We go through the tickets list and if there is a pending
1680	 * packet for it, we push it upstream.
1681	 * We stop whenever a ticket is missing its packet, as we're
1682	 * supposed to send the packets in order.
1683	 */
1684	spin_lock(&iwm->ticket_lock);
1685	list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
1686		struct iwm_rx_packet *packet =
1687			iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
1688
1689		if (!packet) {
1690			IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
1691				   "to be handled first\n",
1692				   le16_to_cpu(ticket->ticket->id));
1693			break;
1694		}
1695
1696		list_del(&ticket->node);
1697		iwm_rx_process_packet(iwm, packet, ticket);
1698	}
1699	spin_unlock(&iwm->ticket_lock);
1700}
1701