iwl-agn.c 112 KB
Newer Older
1
2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * Portions of this file are derived from the ipw3945 project, as well
 * as portions of the ieee80211 subsystem header files.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>

#include <net/mac80211.h>

#include <asm/div64.h>

47
48
#define DRV_NAME        "iwlagn"

49
#include "iwl-eeprom.h"
50
#include "iwl-dev.h"
51
#include "iwl-core.h"
52
#include "iwl-io.h"
53
#include "iwl-helpers.h"
54
#include "iwl-sta.h"
55
#include "iwl-calib.h"
56

57

58
59
60
61
62
63
64
65
66
/******************************************************************************
 *
 * module boiler plate
 *
 ******************************************************************************/

/*
 * module name, copyright, version, etc.
 */
67
#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link AGN driver for Linux"
68

69
#ifdef CONFIG_IWLWIFI_DEBUG
70
71
72
73
74
#define VD "d"
#else
#define VD
#endif

Tomas Winkler's avatar
Tomas Winkler committed
75
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
76
77
78
79
80
#define VS "s"
#else
#define VS
#endif

Tomas Winkler's avatar
Tomas Winkler committed
81
#define DRV_VERSION     IWLWIFI_VERSION VD VS
82
83
84
85


MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
86
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
87
MODULE_LICENSE("GPL");
Tomas Winkler's avatar
Tomas Winkler committed
88
MODULE_ALIAS("iwl4965");
89
90

/*************** STATION TABLE MANAGEMENT ****
91
 * mac80211 should be examined to determine if sta_info is duplicating
92
93
94
95
96
97
98
 * the functionality provided here
 */

/**************************************************************/



99
static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
100
{
Gregory Greenman's avatar
Gregory Greenman committed
101
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
102
103
104
105
106
107
108
109

	if (hw_decrypt)
		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
	else
		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;

}

110
/**
111
 * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
112
 * @priv: staging_rxon is compared to active_rxon
113
 *
114
115
116
 * If the RXON structure is changing enough to require a new tune,
 * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
 * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
117
 */
118
static int iwl_full_rxon_required(struct iwl_priv *priv)
119
120
121
{

	/* These items are only settable from the full RXON command */
122
	if (!(iwl_is_associated(priv)) ||
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	    compare_ether_addr(priv->staging_rxon.bssid_addr,
			       priv->active_rxon.bssid_addr) ||
	    compare_ether_addr(priv->staging_rxon.node_addr,
			       priv->active_rxon.node_addr) ||
	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
			       priv->active_rxon.wlap_bssid_addr) ||
	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
	    (priv->staging_rxon.air_propagation !=
	     priv->active_rxon.air_propagation) ||
	    (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
		return 1;

	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
	 * be updated with the RXON_ASSOC command -- however only some
	 * flag transitions are allowed using RXON_ASSOC */

	/* Check if we are not switching bands */
	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
		return 1;

	/* Check if we are switching association toggle */
	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
		return 1;

	return 0;
}

/**
158
 * iwl_commit_rxon - commit staging_rxon to hardware
159
 *
160
 * The RXON command in staging_rxon is committed to the hardware and
161
162
163
164
 * the active_rxon structure is updated with the new data.  This
 * function correctly transitions out of the RXON_ASSOC_MSK state if
 * a HW tune is required based on the RXON structure changes.
 */
165
static int iwl_commit_rxon(struct iwl_priv *priv)
166
167
{
	/* cast away the const for active_rxon in this function */
Gregory Greenman's avatar
Gregory Greenman committed
168
	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
169
170
171
	int ret;
	bool new_assoc =
		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
172

173
	if (!iwl_is_alive(priv))
174
		return -EBUSY;
175
176
177

	/* always get timestamp with Rx frame */
	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
178
179
180
	/* allow CTS-to-self if possible. this is relevant only for
	 * 5000, but will not damage 4965 */
	priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
181

182
	ret = iwl_agn_check_rxon_cmd(priv);
183
	if (ret) {
184
		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
185
186
187
188
		return -EINVAL;
	}

	/* If we don't need to send a full RXON, we can use
189
	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
190
	 * and other flags for the current radio configuration. */
191
	if (!iwl_full_rxon_required(priv)) {
192
193
		ret = iwl_send_rxon_assoc(priv);
		if (ret) {
194
			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
195
			return ret;
196
197
198
199
200
201
202
203
204
205
206
207
208
		}

		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
		return 0;
	}

	/* station table will be cleared */
	priv->assoc_station_added = 0;

	/* If we are currently associated and the new config requires
	 * an RXON_ASSOC and the new config wants the associated mask enabled,
	 * we must clear the associated from the active configuration
	 * before we apply the new config */
209
	if (iwl_is_associated(priv) && new_assoc) {
210
211
212
		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

213
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
Gregory Greenman's avatar
Gregory Greenman committed
214
				      sizeof(struct iwl_rxon_cmd),
215
216
217
218
				      &priv->active_rxon);

		/* If the mask clearing failed then we set
		 * active_rxon back to what it was previously */
219
		if (ret) {
220
			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
221
			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
222
			return ret;
223
224
225
226
227
228
		}
	}

	IWL_DEBUG_INFO("Sending RXON\n"
		       "* with%s RXON_FILTER_ASSOC_MSK\n"
		       "* channel = %d\n"
Johannes Berg's avatar
Johannes Berg committed
229
		       "* bssid = %pM\n",
230
		       (new_assoc ? "" : "out"),
231
		       le16_to_cpu(priv->staging_rxon.channel),
Johannes Berg's avatar
Johannes Berg committed
232
		       priv->staging_rxon.bssid_addr);
233

234
	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
235
236
237
238
239
240
241
242

	/* Apply the new configuration
	 * RXON unassoc clears the station table in uCode, send it before
	 * we add the bcast station. If assoc bit is set, we will send RXON
	 * after having added the bcast and bssid station.
	 */
	if (!new_assoc) {
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
Gregory Greenman's avatar
Gregory Greenman committed
243
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
244
		if (ret) {
245
			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
246
247
248
			return ret;
		}
		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
249
250
	}

251
	iwl_clear_stations_table(priv);
252

253
254
255
256
	if (!priv->error_recovering)
		priv->start_calib = 0;

	/* Add the broadcast address so we can send broadcast frames */
257
	if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
258
						IWL_INVALID_STATION) {
259
		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
260
261
262
263
264
		return -EIO;
	}

	/* If we have set the ASSOC_MSK and we are in BSS mode then
	 * add the IWL_AP_ID to the station rate table */
265
	if (new_assoc) {
266
		if (priv->iw_mode == NL80211_IFTYPE_STATION) {
267
268
269
			ret = iwl_rxon_add_station(priv,
					   priv->active_rxon.bssid_addr, 1);
			if (ret == IWL_INVALID_STATION) {
270
271
				IWL_ERR(priv,
					"Error adding AP address for TX.\n");
272
273
274
275
276
				return -EIO;
			}
			priv->assoc_station_added = 1;
			if (priv->default_wep_key &&
			    iwl_send_static_wepkey_cmd(priv, 0))
277
278
				IWL_ERR(priv,
					"Could not send WEP static key.\n");
279
		}
280
281
282
283
284
285
286

		/* Apply the new configuration
		 * RXON assoc doesn't clear the station table in uCode,
		 */
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
		if (ret) {
287
			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
288
289
290
			return ret;
		}
		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
291
292
	}

293
294
295
296
297
298
	iwl_init_sensitivity(priv);

	/* If we issue a new RXON command which required a tune then we must
	 * send a new TXPOWER command or we won't be able to Tx any frames */
	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
	if (ret) {
299
		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
300
301
302
		return ret;
	}

303
304
305
	return 0;
}

306
void iwl_update_chain_flags(struct iwl_priv *priv)
307
308
{

309
	iwl_set_rxon_chain(priv);
310
	iwl_commit_rxon(priv);
311
312
}

313
static int iwl_send_bt_config(struct iwl_priv *priv)
314
{
315
	struct iwl_bt_cmd bt_cmd = {
316
317
318
319
320
321
322
		.flags = 3,
		.lead_time = 0xAA,
		.max_kill = 1,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

323
	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
324
				sizeof(struct iwl_bt_cmd), &bt_cmd);
325
326
}

327
static void iwl_clear_free_frames(struct iwl_priv *priv)
328
329
330
331
332
333
334
335
336
{
	struct list_head *element;

	IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n",
		       priv->frames_count);

	while (!list_empty(&priv->free_frames)) {
		element = priv->free_frames.next;
		list_del(element);
337
		kfree(list_entry(element, struct iwl_frame, list));
338
339
340
341
		priv->frames_count--;
	}

	if (priv->frames_count) {
342
		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
343
344
345
346
347
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

348
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
349
{
350
	struct iwl_frame *frame;
351
352
353
354
	struct list_head *element;
	if (list_empty(&priv->free_frames)) {
		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
		if (!frame) {
355
			IWL_ERR(priv, "Could not allocate frame!\n");
356
357
358
359
360
361
362
363
364
			return NULL;
		}

		priv->frames_count++;
		return frame;
	}

	element = priv->free_frames.next;
	list_del(element);
365
	return list_entry(element, struct iwl_frame, list);
366
367
}

368
static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
369
370
371
372
373
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

374
375
static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
					  struct ieee80211_hdr *hdr,
376
					  int left)
377
{
378
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
379
380
	    ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
	     (priv->iw_mode != NL80211_IFTYPE_AP)))
381
382
383
384
385
386
387
388
389
390
		return 0;

	if (priv->ibss_beacon->len > left)
		return 0;

	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);

	return priv->ibss_beacon->len;
}

391
static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
392
{
Guy Cohen's avatar
Guy Cohen committed
393
394
395
396
397
	int i;
	int rate_mask;

	/* Set rate mask*/
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
398
		rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
Guy Cohen's avatar
Guy Cohen committed
399
	else
400
		rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
401

Guy Cohen's avatar
Guy Cohen committed
402
	/* Find lowest valid rate */
403
	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
404
					i = iwl_rates[i].next_ieee) {
405
		if (rate_mask & (1 << i))
406
			return iwl_rates[i].plcp;
407
408
	}

Guy Cohen's avatar
Guy Cohen committed
409
410
411
412
413
	/* No valid rate was found. Assign the lowest one */
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
		return IWL_RATE_1M_PLCP;
	else
		return IWL_RATE_6M_PLCP;
414
415
}

416
static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
				       struct iwl_frame *frame, u8 rate)
{
	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
	unsigned int frame_size;

	tx_beacon_cmd = &frame->u.beacon;
	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));

	tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

	frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
				sizeof(frame->u) - sizeof(*tx_beacon_cmd));

	BUG_ON(frame_size > MAX_MPDU_SIZE);
	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);

	if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
		tx_beacon_cmd->tx.rate_n_flags =
			iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
	else
		tx_beacon_cmd->tx.rate_n_flags =
			iwl_hw_set_rate_n_flags(rate, 0);

	tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
				     TX_CMD_FLG_TSF_MSK |
				     TX_CMD_FLG_STA_RATE_MSK;

	return sizeof(*tx_beacon_cmd) + frame_size;
}
447
static int iwl_send_beacon_cmd(struct iwl_priv *priv)
448
{
449
	struct iwl_frame *frame;
450
451
452
453
	unsigned int frame_size;
	int rc;
	u8 rate;

454
	frame = iwl_get_free_frame(priv);
455
456

	if (!frame) {
457
		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
458
459
460
461
			  "command.\n");
		return -ENOMEM;
	}

462
	rate = iwl_rate_get_lowest_plcp(priv);
463

464
	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
465

466
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
467
468
			      &frame->u.cmd[0]);

469
	iwl_free_frame(priv, frame);
470
471
472
473
474
475
476
477
478
479

	return rc;
}

/******************************************************************************
 *
 * Misc. internal state and helper functions
 *
 ******************************************************************************/

480
static void iwl_ht_conf(struct iwl_priv *priv,
481
482
			    struct ieee80211_bss_conf *bss_conf)
{
Johannes Berg's avatar
Johannes Berg committed
483
	struct ieee80211_sta_ht_cap *ht_conf;
484
	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
Johannes Berg's avatar
Johannes Berg committed
485
	struct ieee80211_sta *sta;
486
487
488
489
490
491

	IWL_DEBUG_MAC80211("enter: \n");

	if (!iwl_conf->is_ht)
		return;

Johannes Berg's avatar
Johannes Berg committed
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

	/*
	 * It is totally wrong to base global information on something
	 * that is valid only when associated, alas, this driver works
	 * that way and I don't know how to fix it.
	 */

	rcu_read_lock();
	sta = ieee80211_find_sta(priv->hw, priv->bssid);
	if (!sta) {
		rcu_read_unlock();
		return;
	}
	ht_conf = &sta->ht_cap;

507
	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
508
		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
509
	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
510
		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
511
512
513
514
515
516

	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
	iwl_conf->max_amsdu_size =
		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);

	iwl_conf->supported_chan_width =
517
		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
Johannes Berg's avatar
Johannes Berg committed
518

Sujith's avatar
Sujith committed
519
520
521
522
523
524
	/*
	 * XXX: The HT configuration needs to be moved into iwl_mac_config()
	 *	to be done there correctly.
	 */

	iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
525
	if (conf_is_ht40_minus(&priv->hw->conf))
Sujith's avatar
Sujith committed
526
		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
527
	else if (conf_is_ht40_plus(&priv->hw->conf))
Sujith's avatar
Sujith committed
528
529
		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;

530
	/* If no above or below channel supplied disable FAT channel */
531
	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
Sujith's avatar
Sujith committed
532
	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
533
534
		iwl_conf->supported_chan_width = 0;

535
536
	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);

537
	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
538

Sujith's avatar
Sujith committed
539
	iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
540
	iwl_conf->ht_protection =
Johannes Berg's avatar
Johannes Berg committed
541
		bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
542
	iwl_conf->non_GF_STA_present =
Johannes Berg's avatar
Johannes Berg committed
543
544
545
		!!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);

	rcu_read_unlock();
546
547
548
549

	IWL_DEBUG_MAC80211("leave\n");
}

550
551
552
/*
 * QoS  support
*/
553
static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
554
555
556
557
558
559
560
561
562
563
564
565
566
567
{
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	priv->qos_data.def_qos_parm.qos_flags = 0;

	if (priv->qos_data.qos_cap.q_AP.queue_request &&
	    !priv->qos_data.qos_cap.q_AP.txop_request)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_TXOP_TYPE_MSK;
	if (priv->qos_data.qos_active)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_UPDATE_EDCA_MSK;

568
	if (priv->current_ht_config.is_ht)
569
570
		priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;

571
	if (force || iwl_is_associated(priv)) {
572
573
574
		IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
				priv->qos_data.qos_active,
				priv->qos_data.def_qos_parm.qos_flags);
575

576
577
578
		iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
				       sizeof(struct iwl_qosparam_cmd),
				       &priv->qos_data.def_qos_parm, NULL);
579
580
581
582
583
	}
}

#define MAX_UCODE_BEACON_INTERVAL	4096

584
static u16 iwl_adjust_beacon_interval(u16 beacon_val)
585
586
587
588
{
	u16 new_val = 0;
	u16 beacon_factor = 0;

589
590
	beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL)
					/ MAX_UCODE_BEACON_INTERVAL;
591
592
	new_val = beacon_val / beacon_factor;

593
	return new_val;
594
595
}

596
static void iwl_setup_rxon_timing(struct iwl_priv *priv)
597
{
598
599
	u64 tsf;
	s32 interval_tm, rem;
600
601
602
603
604
605
606
	unsigned long flags;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int = 0;

	conf = ieee80211_get_hw_conf(priv->hw);

	spin_lock_irqsave(&priv->lock, flags);
607
	priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
608
	priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
609

610
	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
611
		beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
612
613
		priv->rxon_timing.atim_window = 0;
	} else {
614
615
		beacon_int = iwl_adjust_beacon_interval(conf->beacon_int);

616
617
618
619
620
		/* TODO: we need to get atim_window from upper stack
		 * for now we set to 0 */
		priv->rxon_timing.atim_window = 0;
	}

621
	priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
622

623
624
625
626
627
628
629
630
631
632
	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
	interval_tm = beacon_int * 1024;
	rem = do_div(tsf, interval_tm);
	priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);

	spin_unlock_irqrestore(&priv->lock, flags);
	IWL_DEBUG_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n",
			le16_to_cpu(priv->rxon_timing.beacon_interval),
			le32_to_cpu(priv->rxon_timing.beacon_init_val),
			le16_to_cpu(priv->rxon_timing.atim_window));
633
634
}

635
636
static void iwl_set_flags_for_band(struct iwl_priv *priv,
				   enum ieee80211_band band)
637
{
638
	if (band == IEEE80211_BAND_5GHZ) {
639
640
641
642
643
		priv->staging_rxon.flags &=
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
	} else {
644
		/* Copied from iwl_post_associate() */
645
646
647
648
649
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

650
		if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
651
652
653
654
655
656
657
658
659
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
		priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
	}
}

/*
660
 * initialize rxon structure with default values from eeprom
661
 */
662
static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
663
{
664
	const struct iwl_channel_info *ch_info;
665
666
667

	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));

668
	switch (mode) {
669
	case NL80211_IFTYPE_AP:
670
671
672
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
		break;

673
	case NL80211_IFTYPE_STATION:
674
675
676
677
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
		break;

678
	case NL80211_IFTYPE_ADHOC:
679
680
681
682
683
684
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

685
	case NL80211_IFTYPE_MONITOR:
686
687
688
689
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
		break;
690
	default:
691
		IWL_ERR(priv, "Unsupported interface type %d\n", mode);
692
		break;
693
694
695
696
697
698
699
700
701
702
703
	}

#if 0
	/* TODO:  Figure out when short_preamble would be set and cache from
	 * that */
	if (!hw_to_local(priv->hw)->short_preamble)
		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
	else
		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif

704
	ch_info = iwl_get_channel_info(priv, priv->band,
705
				       le16_to_cpu(priv->active_rxon.channel));
706
707
708
709
710
711
712
713

	if (!ch_info)
		ch_info = &priv->channel_info[0];

	/*
	 * in some case A channels are all non IBSS
	 * in this case force B/G channel
	 */
714
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
715
716
717
718
	    !(is_channel_ibss(ch_info)))
		ch_info = &priv->channel_info[0];

	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
719
	priv->band = ch_info->band;
720

721
	iwl_set_flags_for_band(priv, priv->band);
722
723
724
725
726
727
728
729
730
731
732
733

	priv->staging_rxon.ofdm_basic_rates =
	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
	priv->staging_rxon.cck_basic_rates =
	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
					RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
	memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
734
	iwl_set_rxon_chain(priv);
735
736
}

737
static int iwl_set_mode(struct iwl_priv *priv, int mode)
738
{
739
	iwl_connection_init_rx_config(priv, mode);
740
741
	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);

742
	iwl_clear_stations_table(priv);
743

744
	/* dont commit rxon if rf-kill is on*/
745
	if (!iwl_is_ready_rf(priv))
746
747
748
		return -EAGAIN;

	cancel_delayed_work(&priv->scan_check);
749
	if (iwl_scan_cancel_timeout(priv, 100)) {
750
		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
751
752
753
754
		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
		return -EAGAIN;
	}

755
	iwl_commit_rxon(priv);
756
757
758
759

	return 0;
}

760
static void iwl_set_rate(struct iwl_priv *priv)
761
{
762
	const struct ieee80211_supported_band *hw = NULL;
763
764
765
	struct ieee80211_rate *rate;
	int i;

766
	hw = iwl_get_hw_mode(priv, priv->band);
767
	if (!hw) {
768
		IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
769
770
		return;
	}
771
772
773
774

	priv->active_rate = 0;
	priv->active_rate_basic = 0;

775
776
777
778
	for (i = 0; i < hw->n_bitrates; i++) {
		rate = &(hw->bitrates[i]);
		if (rate->hw_value < IWL_RATE_COUNT)
			priv->active_rate |= (1 << rate->hw_value);
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
	}

	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
		       priv->active_rate, priv->active_rate_basic);

	/*
	 * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
	 * otherwise set it to the default of all CCK rates and 6, 12, 24 for
	 * OFDM
	 */
	if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
		priv->staging_rxon.cck_basic_rates =
		    ((priv->active_rate_basic &
		      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
	else
		priv->staging_rxon.cck_basic_rates =
		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

	if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
		priv->staging_rxon.ofdm_basic_rates =
		    ((priv->active_rate_basic &
		      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
		      IWL_FIRST_OFDM_RATE) & 0xFF;
	else
		priv->staging_rxon.ofdm_basic_rates =
		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}


/******************************************************************************
 *
 * Generic RX handler implementations
 *
 ******************************************************************************/
813
814
static void iwl_rx_reply_alive(struct iwl_priv *priv,
				struct iwl_rx_mem_buffer *rxb)
815
{
816
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
817
	struct iwl_alive_resp *palive;
818
819
820
821
822
823
824
825
826
827
828
829
830
	struct delayed_work *pwork;

	palive = &pkt->u.alive_frame;

	IWL_DEBUG_INFO("Alive ucode status 0x%08X revision "
		       "0x%01X 0x%01X\n",
		       palive->is_valid, palive->ver_type,
		       palive->ver_subtype);

	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
		IWL_DEBUG_INFO("Initialization Alive received.\n");
		memcpy(&priv->card_alive_init,
		       &pkt->u.alive_frame,
831
		       sizeof(struct iwl_init_alive_resp));
832
833
834
835
		pwork = &priv->init_alive_start;
	} else {
		IWL_DEBUG_INFO("Runtime Alive received.\n");
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
836
		       sizeof(struct iwl_alive_resp));
837
838
839
840
841
842
843
844
845
		pwork = &priv->alive_start;
	}

	/* We delay the ALIVE response by 5ms to
	 * give the HW RF Kill time to activate... */
	if (palive->is_valid == UCODE_VALID_OK)
		queue_delayed_work(priv->workqueue, pwork,
				   msecs_to_jiffies(5));
	else
846
		IWL_WARN(priv, "uCode did not respond OK.\n");
847
848
}

849
static void iwl_rx_reply_error(struct iwl_priv *priv,
850
				   struct iwl_rx_mem_buffer *rxb)
851
{
852
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
853

854
	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
855
856
857
858
859
860
861
862
863
864
		"seq 0x%04X ser 0x%08X\n",
		le32_to_cpu(pkt->u.err_resp.error_type),
		get_cmd_string(pkt->u.err_resp.cmd_id),
		pkt->u.err_resp.cmd_id,
		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
		le32_to_cpu(pkt->u.err_resp.error_info));
}

#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x

865
static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
866
{
867
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Gregory Greenman's avatar
Gregory Greenman committed
868
	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
869
	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
870
871
872
873
874
875
	IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
		      le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
	rxon->channel = csa->channel;
	priv->staging_rxon.channel = csa->channel;
}

876
static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
877
				      struct iwl_rx_mem_buffer *rxb)
878
{
879
#ifdef CONFIG_IWLWIFI_DEBUG
880
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
881
	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
882
883
884
885
886
	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}

887
static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
888
					     struct iwl_rx_mem_buffer *rxb)
889
{
890
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
891
892
893
	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
			"notification for %s:\n",
			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
894
	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
895
896
}

897
static void iwl_bg_beacon_update(struct work_struct *work)
898
{
899
900
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
901
902
903
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
904
	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
905
906

	if (!beacon) {
907
		IWL_ERR(priv, "update beacon failed\n");
908
909
910
911
912
913
914
915
916
917
918
		return;
	}

	mutex_lock(&priv->mutex);
	/* new beacon skb is allocated every time; dispose previous.*/
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = beacon;
	mutex_unlock(&priv->mutex);

919
	iwl_send_beacon_cmd(priv);
920
921
}

922
/**
923
 * iwl_bg_statistics_periodic - Timer callback to queue statistics
924
925
926
927
928
929
930
931
 *
 * This callback is provided in order to send a statistics request.
 *
 * This timer function is continually reset to execute within
 * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
 * was received.  We need to ensure we receive the statistics in order
 * to update the temperature used for calibrating the TXPOWER.
 */
932
static void iwl_bg_statistics_periodic(unsigned long data)
933
934
935
936
937
938
{
	struct iwl_priv *priv = (struct iwl_priv *)data;

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

939
940
941
942
	/* dont send host command if rf-kill is on */
	if (!iwl_is_ready_rf(priv))
		return;

943
944
945
	iwl_send_statistics_request(priv, CMD_ASYNC);
}

946
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
947
				struct iwl_rx_mem_buffer *rxb)
948
{
949
#ifdef CONFIG_IWLWIFI_DEBUG
950
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
951
952
	struct iwl4965_beacon_notif *beacon =
		(struct iwl4965_beacon_notif *)pkt->u.raw;
953
	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
954
955
956

	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
		"tsf %d %d rate %d\n",
957
		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
958
959
960
961
962
963
		beacon->beacon_notify_hdr.failure_frame,
		le32_to_cpu(beacon->ibss_mgr_status),
		le32_to_cpu(beacon->high_tsf),
		le32_to_cpu(beacon->low_tsf), rate);
#endif

964
	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
965
966
967
968
969
970
	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
		queue_work(priv->workqueue, &priv->beacon_update);
}

/* Handle notification from uCode that card's power state is changing
 * due to software, hardware, or critical temperature RFKILL */
971
static void iwl_rx_card_state_notif(struct iwl_priv *priv,
972
				    struct iwl_rx_mem_buffer *rxb)
973
{
974
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
975
976
977
978
979
980
981
982
983
984
	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
	unsigned long status = priv->status;

	IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n",
			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");

	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
		     RF_CARD_DISABLED)) {

985
		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
986
987
			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

988
989
		if (!iwl_grab_nic_access(priv)) {
			iwl_write_direct32(
990
991
992
				priv, HBUS_TARG_MBX_C,
				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

993
			iwl_release_nic_access(priv);
994
995
996
		}

		if (!(flags & RXON_CARD_DISABLED)) {
997
			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
998
				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
999
1000
			if (!iwl_grab_nic_access(priv)) {
				iwl_write_direct32(
1001
1002
1003
					priv, HBUS_TARG_MBX_C,
					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

1004
				iwl_release_nic_access(priv);
1005
1006
1007
1008
			}
		}

		if (flags & RF_CARD_DISABLED) {
1009
			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
1010
				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
1011
1012
1013
			iwl_read32(priv, CSR_UCODE_DRV_GP1);
			if (!iwl_grab_nic_access(priv))
				iwl_release_nic_access(priv);
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
		}
	}

	if (flags & HW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_HW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_HW, &priv->status);


	if (flags & SW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_SW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_SW, &priv->status);

	if (!(flags & RXON_CARD_DISABLED))
1029
		iwl_scan_cancel(priv);
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
	    (test_bit(STATUS_RF_KILL_SW, &status) !=
	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
		queue_work(priv->workqueue, &priv->rf_kill);
	else
		wake_up_interruptible(&priv->wait_command_queue);
}

1040
int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
{
	int ret;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
	ret = iwl_grab_nic_access(priv);
	if (ret)
		goto err;

	if (src == IWL_PWR_SRC_VAUX) {
		u32 val;
1052
		ret = pci_read_config_dword(priv->pci_dev, PCI_CFG_POWER_SOURCE,
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
					    &val);

		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
					       ~APMG_PS_CTRL_MSK_PWR_SRC);
	} else {
		iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
				       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
				       ~APMG_PS_CTRL_MSK_PWR_SRC);
	}

	iwl_release_nic_access(priv);
err:
	spin_unlock_irqrestore(&priv->lock, flags);
	return ret;
}

1071
/**
1072
 * iwl_setup_rx_handlers - Initialize Rx handler callbacks
1073
1074
1075
1076
1077
1078
1079
 *
 * Setup the RX handlers for each of the reply types sent from the uCode
 * to the host.
 *
 * This function chains into the hardware specific files for them to setup
 * any hardware specific handlers as well.
 */
1080
static void iwl_setup_rx_handlers(struct iwl_priv *priv)
1081
{
1082
	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
1083
1084
1085
	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
1086
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
1087
1088
	    iwl_rx_pm_debug_statistics_notif;
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
1089

1090
1091
1092
1093
	/*
	 * The same handler is used for both the REPLY to a discrete
	 * statistics request from the host as well as for the periodic
	 * statistics notifications (after received beacons) from the uCode.
1094
	 */
1095
1096
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
1097

1098
	iwl_setup_spectrum_handlers(priv);
1099
1100
	iwl_setup_rx_scan_handlers(priv);

1101
	/* status change handler */
1102
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
1103

1104
1105
	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
	    iwl_rx_missed_beacon_notif;
1106
	/* Rx handlers */
1107
1108
	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
1109
1110
	/* block ack */
	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
1111
	/* Set up hardware specific Rx handlers */
1112
	priv->cfg->ops->lib->rx_handler_setup(priv);
1113
1114
1115
}

/**