iwl-core.c 54.7 KB
Newer Older
Tomas Winkler's avatar
Tomas Winkler committed
1
2
3
4
/******************************************************************************
 *
 * GPL LICENSE SUMMARY
 *
Wey-Yi Guy's avatar
Wey-Yi Guy committed
5
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
Tomas Winkler's avatar
Tomas Winkler committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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.GPL.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
Tomas Winkler's avatar
Tomas Winkler committed
26
27
28
29
30
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
31
#include <linux/etherdevice.h>
32
#include <linux/sched.h>
33
#include <linux/slab.h>
34
#include <net/mac80211.h>
Tomas Winkler's avatar
Tomas Winkler committed
35

36
#include "iwl-eeprom.h"
37
#include "iwl-dev.h" /* FIXME: remove */
38
#include "iwl-debug.h"
Tomas Winkler's avatar
Tomas Winkler committed
39
#include "iwl-core.h"
40
#include "iwl-io.h"
41
#include "iwl-power.h"
42
#include "iwl-sta.h"
Mohamed Abbas's avatar
Mohamed Abbas committed
43
#include "iwl-helpers.h"
Tomas Winkler's avatar
Tomas Winkler committed
44

45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 * set bt_coex_active to true, uCode will do kill/defer
 * every time the priority line is asserted (BT is sending signals on the
 * priority line in the PCIx).
 * set bt_coex_active to false, uCode will ignore the BT activity and
 * perform the normal operation
 *
 * User might experience transmit issue on some platform due to WiFi/BT
 * co-exist problem. The possible behaviors are:
 *   Able to scan and finding all the available AP
 *   Not able to associate with any AP
 * On those platforms, WiFi communication can be restored by set
 * "bt_coex_active" module parameter to "false"
 *
 * default: bt_coex_active = true (BT_COEX_ENABLE)
 */
62
bool bt_coex_active = true;
63
module_param(bt_coex_active, bool, S_IRUGO);
64
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
65

66
67
u32 iwl_debug_level;

68
69
70
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };


71
/* This function both allocates and initializes hw and priv. */
72
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
73
74
75
76
{
	struct iwl_priv *priv;
	/* mac80211 allocates memory for this device instance, including
	 *   space for this driver's private structure */
77
78
79
80
	struct ieee80211_hw *hw;

	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
				cfg->ops->ieee80211_ops);
81
	if (hw == NULL) {
82
		pr_err("%s: Can not allocate network device\n",
83
		       cfg->name);
84
85
86
87
88
89
90
91
92
93
		goto out;
	}

	priv = hw->priv;
	priv->hw = hw;

out:
	return hw;
}

94
95
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
96
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
97
			      struct ieee80211_sta_ht_cap *ht_info,
98
99
			      enum ieee80211_band band)
{
Ron Rindjunsky's avatar
Ron Rindjunsky committed
100
101
102
103
	u16 max_bit_rate = 0;
	u8 rx_chains_num = priv->hw_params.rx_chains_num;
	u8 tx_chains_num = priv->hw_params.tx_chains_num;

104
	ht_info->cap = 0;
105
	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
106

107
	ht_info->ht_supported = true;
108

109
110
	if (priv->cfg->ht_params &&
	    priv->cfg->ht_params->ht_greenfield_support)
111
		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
112
	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
113
	max_bit_rate = MAX_BIT_RATE_20_MHZ;
114
	if (priv->hw_params.ht40_channel & BIT(band)) {
115
116
117
		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
		ht_info->mcs.rx_mask[4] = 0x01;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
118
		max_bit_rate = MAX_BIT_RATE_40_MHZ;
119
120
121
	}

	if (priv->cfg->mod_params->amsdu_size_8K)
122
		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
123
124

	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
125
126
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
		ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
127
	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
128
129
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
		ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
130

131
	ht_info->mcs.rx_mask[0] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
132
	if (rx_chains_num >= 2)
133
		ht_info->mcs.rx_mask[1] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
134
	if (rx_chains_num >= 3)
135
		ht_info->mcs.rx_mask[2] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
136
137
138

	/* Highest supported Rx data rate */
	max_bit_rate *= rx_chains_num;
139
140
	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
Ron Rindjunsky's avatar
Ron Rindjunsky committed
141
142

	/* Tx MCS capabilities */
143
	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
144
	if (tx_chains_num != rx_chains_num) {
145
146
147
		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
		ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
Ron Rindjunsky's avatar
Ron Rindjunsky committed
148
	}
149
150
151
152
153
}

/**
 * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
 */
154
int iwlcore_init_geos(struct iwl_priv *priv)
155
156
157
158
159
160
161
162
163
164
{
	struct iwl_channel_info *ch;
	struct ieee80211_supported_band *sband;
	struct ieee80211_channel *channels;
	struct ieee80211_channel *geo_ch;
	struct ieee80211_rate *rates;
	int i = 0;

	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
165
		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
166
167
168
169
170
171
172
173
174
		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
		return 0;
	}

	channels = kzalloc(sizeof(struct ieee80211_channel) *
			   priv->channel_count, GFP_KERNEL);
	if (!channels)
		return -ENOMEM;

175
	rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
176
177
178
179
180
181
182
183
184
185
186
			GFP_KERNEL);
	if (!rates) {
		kfree(channels);
		return -ENOMEM;
	}

	/* 5.2GHz channels start after the 2.4GHz channels */
	sband = &priv->bands[IEEE80211_BAND_5GHZ];
	sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
	/* just OFDM */
	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
187
	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
188

189
	if (priv->cfg->sku & IWL_SKU_N)
190
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
191
					 IEEE80211_BAND_5GHZ);
192
193
194
195
196

	sband = &priv->bands[IEEE80211_BAND_2GHZ];
	sband->channels = channels;
	/* OFDM & CCK */
	sband->bitrates = rates;
197
	sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
198

199
	if (priv->cfg->sku & IWL_SKU_N)
200
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
201
					 IEEE80211_BAND_2GHZ);
202
203
204
205
206
207
208
209
210
211
212

	priv->ieee_channels = channels;
	priv->ieee_rates = rates;

	for (i = 0;  i < priv->channel_count; i++) {
		ch = &priv->channel_info[i];

		/* FIXME: might be removed if scan is OK */
		if (!is_channel_valid(ch))
			continue;

213
		sband =  &priv->bands[ch->band];
214
215
216
217

		geo_ch = &sband->channels[sband->n_channels++];

		geo_ch->center_freq =
218
			ieee80211_channel_to_frequency(ch->channel, ch->band);
219
220
221
222
223
224
225
226
227
228
229
230
231
232
		geo_ch->max_power = ch->max_power_avg;
		geo_ch->max_antenna_gain = 0xff;
		geo_ch->hw_value = ch->channel;

		if (is_channel_valid(ch)) {
			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;

			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;

			if (ch->flags & EEPROM_CHANNEL_RADAR)
				geo_ch->flags |= IEEE80211_CHAN_RADAR;

233
			geo_ch->flags |= ch->ht40_extension_channel;
234

235
236
			if (ch->max_power_avg > priv->tx_power_device_lmt)
				priv->tx_power_device_lmt = ch->max_power_avg;
237
238
239
240
		} else {
			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
		}

241
		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
242
243
244
245
246
247
248
249
250
				ch->channel, geo_ch->center_freq,
				is_channel_a_band(ch) ?  "5.2" : "2.4",
				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
				"restricted" : "valid",
				 geo_ch->flags);
	}

	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
	     priv->cfg->sku & IWL_SKU_A) {
Tomas Winkler's avatar
Tomas Winkler committed
251
252
		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
253
254
			   priv->pci_dev->device,
			   priv->pci_dev->subsystem_device);
255
256
257
		priv->cfg->sku &= ~IWL_SKU_A;
	}

Tomas Winkler's avatar
Tomas Winkler committed
258
	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
259
260
		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
261
262
263
264
265
266
267
268
269

	set_bit(STATUS_GEO_CONFIGURED, &priv->status);

	return 0;
}

/*
 * iwlcore_free_geos - undo allocations in iwlcore_init_geos
 */
270
void iwlcore_free_geos(struct iwl_priv *priv)
271
272
273
274
275
276
{
	kfree(priv->ieee_channels);
	kfree(priv->ieee_rates);
	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}

277
278
279
static bool iwl_is_channel_extension(struct iwl_priv *priv,
				     enum ieee80211_band band,
				     u16 channel, u8 extension_chan_offset)
280
281
282
283
284
{
	const struct iwl_channel_info *ch_info;

	ch_info = iwl_get_channel_info(priv, band, channel);
	if (!is_channel_valid(ch_info))
285
		return false;
286

287
	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
288
		return !(ch_info->ht40_extension_channel &
289
					IEEE80211_CHAN_NO_HT40PLUS);
290
	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
291
		return !(ch_info->ht40_extension_channel &
292
					IEEE80211_CHAN_NO_HT40MINUS);
293

294
	return false;
295
296
}

297
298
299
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
			    struct iwl_rxon_context *ctx,
			    struct ieee80211_sta_ht_cap *ht_cap)
300
{
301
302
	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
		return false;
303

304
305
	/*
	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
306
307
	 * the bit will not set if it is pure 40MHz case
	 */
308
309
310
	if (ht_cap && !ht_cap->ht_supported)
		return false;

311
#ifdef CONFIG_IWLWIFI_DEBUGFS
312
	if (priv->disable_ht40)
313
		return false;
314
#endif
315

316
	return iwl_is_channel_extension(priv, priv->band,
317
			le16_to_cpu(ctx->staging.channel),
318
			ctx->ht.extension_chan_offset);
319
320
}

321
322
static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	u16 new_val;
	u16 beacon_factor;

	/*
	 * If mac80211 hasn't given us a beacon interval, program
	 * the default into the device (not checking this here
	 * would cause the adjustment below to return the maximum
	 * value, which may break PAN.)
	 */
	if (!beacon_val)
		return DEFAULT_BEACON_INTERVAL;

	/*
	 * If the beacon interval we obtained from the peer
	 * is too large, we'll have to wake up more often
	 * (and in IBSS case, we'll beacon too much)
	 *
	 * For example, if max_beacon_val is 4096, and the
	 * requested beacon interval is 7000, we'll have to
	 * use 3500 to be able to wake up on the beacons.
	 *
	 * This could badly influence beacon detection stats.
	 */
346
347
348
349
350
351
352
353
354
355

	beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
	new_val = beacon_val / beacon_factor;

	if (!new_val)
		new_val = max_beacon_val;

	return new_val;
}

356
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
357
358
359
360
361
{
	u64 tsf;
	s32 interval_tm, rem;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int;
362
	struct ieee80211_vif *vif = ctx->vif;
363
364
365

	conf = ieee80211_get_hw_conf(priv->hw);

366
367
	lockdep_assert_held(&priv->mutex);

368
	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
369

370
371
	ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
372

373
	beacon_int = vif ? vif->bss_conf.beacon_int : 0;
374

375
376
377
378
379
	/*
	 * TODO: For IBSS we need to get atim_window from mac80211,
	 *	 for now just always use 0
	 */
	ctx->timing.atim_window = 0;
380

381
	if (ctx->ctxid == IWL_RXON_CTX_PAN &&
382
383
384
385
	    (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) &&
	    iwl_is_associated(priv, IWL_RXON_CTX_BSS) &&
	    priv->contexts[IWL_RXON_CTX_BSS].vif &&
	    priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) {
386
387
388
		ctx->timing.beacon_interval =
			priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval;
		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
389
390
391
392
393
394
395
396
397
	} else if (ctx->ctxid == IWL_RXON_CTX_BSS &&
		   iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
		   priv->contexts[IWL_RXON_CTX_PAN].vif &&
		   priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int &&
		   (!iwl_is_associated_ctx(ctx) || !ctx->vif ||
		    !ctx->vif->bss_conf.beacon_int)) {
		ctx->timing.beacon_interval =
			priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval;
		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
398
399
	} else {
		beacon_int = iwl_adjust_beacon_interval(beacon_int,
400
				priv->hw_params.max_beacon_itrvl * TIME_UNIT);
401
402
		ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
	}
403
404

	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
405
	interval_tm = beacon_int * TIME_UNIT;
406
	rem = do_div(tsf, interval_tm);
407
	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
408

409
	ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
410

411
412
	IWL_DEBUG_ASSOC(priv,
			"beacon interval %d beacon timer %d beacon tim %d\n",
413
414
415
			le16_to_cpu(ctx->timing.beacon_interval),
			le32_to_cpu(ctx->timing.beacon_init_val),
			le16_to_cpu(ctx->timing.atim_window));
416

417
	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
418
				sizeof(ctx->timing), &ctx->timing);
419
420
}

421
422
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
			   int hw_decrypt)
423
{
424
	struct iwl_rxon_cmd *rxon = &ctx->staging;
425
426
427
428
429
430
431
432

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

}

Johannes Berg's avatar
Johannes Berg committed
433
/* validate RXON structure is valid */
434
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
435
{
436
	struct iwl_rxon_cmd *rxon = &ctx->staging;
Johannes Berg's avatar
Johannes Berg committed
437
	bool error = false;
438
439

	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
Johannes Berg's avatar
Johannes Berg committed
440
441
442
443
444
445
446
447
		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
			IWL_WARN(priv, "check 2.4G: wrong narrow\n");
			error = true;
		}
		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
			IWL_WARN(priv, "check 2.4G: wrong radar\n");
			error = true;
		}
448
	} else {
Johannes Berg's avatar
Johannes Berg committed
449
450
451
452
453
454
455
456
457
458
459
460
		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
			IWL_WARN(priv, "check 5.2G: not short slot!\n");
			error = true;
		}
		if (rxon->flags & RXON_FLG_CCK_MSK) {
			IWL_WARN(priv, "check 5.2G: CCK!\n");
			error = true;
		}
	}
	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
		IWL_WARN(priv, "mac/bssid mcast!\n");
		error = true;
461
462
463
	}

	/* make sure basic rates 6Mbps and 1Mbps are supported */
Johannes Berg's avatar
Johannes Berg committed
464
465
466
467
468
	if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
	    (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
		IWL_WARN(priv, "neither 1 nor 6 are basic\n");
		error = true;
	}
469

Johannes Berg's avatar
Johannes Berg committed
470
471
472
473
	if (le16_to_cpu(rxon->assoc_id) > 2007) {
		IWL_WARN(priv, "aid > 2007\n");
		error = true;
	}
474

Johannes Berg's avatar
Johannes Berg committed
475
476
477
478
479
	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
		IWL_WARN(priv, "CCK and short slot\n");
		error = true;
	}
480

Johannes Berg's avatar
Johannes Berg committed
481
482
483
484
485
	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
		IWL_WARN(priv, "CCK and auto detect");
		error = true;
	}
486

Johannes Berg's avatar
Johannes Berg committed
487
488
489
490
491
492
	if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
			    RXON_FLG_TGG_PROTECT_MSK)) ==
			    RXON_FLG_TGG_PROTECT_MSK) {
		IWL_WARN(priv, "TGg but no auto-detect\n");
		error = true;
	}
493
494
495
496
497
498

	if (error)
		IWL_WARN(priv, "Tuning to channel %d\n",
			    le16_to_cpu(rxon->channel));

	if (error) {
Johannes Berg's avatar
Johannes Berg committed
499
500
		IWL_ERR(priv, "Invalid RXON\n");
		return -EINVAL;
501
502
503
504
505
506
507
508
509
510
511
512
	}
	return 0;
}

/**
 * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
 * @priv: staging_rxon is compared to active_rxon
 *
 * 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.
 */
513
514
int iwl_full_rxon_required(struct iwl_priv *priv,
			   struct iwl_rxon_context *ctx)
515
{
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
	const struct iwl_rxon_cmd *staging = &ctx->staging;
	const struct iwl_rxon_cmd *active = &ctx->active;

#define CHK(cond)							\
	if ((cond)) {							\
		IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n");	\
		return 1;						\
	}

#define CHK_NEQ(c1, c2)						\
	if ((c1) != (c2)) {					\
		IWL_DEBUG_INFO(priv, "need full RXON - "	\
			       #c1 " != " #c2 " - %d != %d\n",	\
			       (c1), (c2));			\
		return 1;					\
	}
532
533

	/* These items are only settable from the full RXON command */
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
	CHK(!iwl_is_associated_ctx(ctx));
	CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
	CHK(compare_ether_addr(staging->node_addr, active->node_addr));
	CHK(compare_ether_addr(staging->wlap_bssid_addr,
				active->wlap_bssid_addr));
	CHK_NEQ(staging->dev_type, active->dev_type);
	CHK_NEQ(staging->channel, active->channel);
	CHK_NEQ(staging->air_propagation, active->air_propagation);
	CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
		active->ofdm_ht_single_stream_basic_rates);
	CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
		active->ofdm_ht_dual_stream_basic_rates);
	CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates,
		active->ofdm_ht_triple_stream_basic_rates);
	CHK_NEQ(staging->assoc_id, active->assoc_id);
549
550
551
552
553
554

	/* 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 */
555
556
	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
		active->flags & RXON_FLG_BAND_24G_MSK);
557
558

	/* Check if we are switching association toggle */
559
560
561
562
563
	CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
		active->filter_flags & RXON_FILTER_ASSOC_MSK);

#undef CHK
#undef CHK_NEQ
564
565
566
567

	return 0;
}

568
569
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
			    struct iwl_rxon_context *ctx)
570
{
571
572
573
574
	/*
	 * Assign the lowest rate -- should really get this from
	 * the beacon skb from mac80211.
	 */
575
	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
576
577
578
579
580
		return IWL_RATE_1M_PLCP;
	else
		return IWL_RATE_6M_PLCP;
}

581
582
583
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
			     struct iwl_ht_config *ht_conf,
			     struct iwl_rxon_context *ctx)
584
{
585
	struct iwl_rxon_cmd *rxon = &ctx->staging;
586

587
	if (!ctx->ht.enabled) {
588
		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
589
			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
590
			RXON_FLG_HT40_PROT_MSK |
591
			RXON_FLG_HT_PROT_MSK);
592
		return;
593
	}
594

595
	/* FIXME: if the definition of ht.protection changed, the "translation"
596
597
	 * will be needed for rxon->flags
	 */
598
	rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
599
600

	/* Set up channel bandwidth:
601
	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
602
603
604
	/* clear the HT channel mode before set the mode */
	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
605
	if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
606
		/* pure ht40 */
607
		if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
608
			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
609
			/* Note: control channel is opposite of extension channel */
610
			switch (ctx->ht.extension_chan_offset) {
611
612
613
614
615
616
617
618
			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
				rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
				rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
				break;
			}
		} else {
619
			/* Note: control channel is opposite of extension channel */
620
			switch (ctx->ht.extension_chan_offset) {
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
				rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
				rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_NONE:
			default:
				/* channel location only valid if in Mixed mode */
				IWL_ERR(priv, "invalid extension channel offset\n");
				break;
			}
		}
	} else {
		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
638
639
	}

640
	if (priv->cfg->ops->hcmd->set_rxon_chain)
641
		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
642

643
	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
Johannes Berg's avatar
Johannes Berg committed
644
			"extension channel offset 0x%x\n",
645
646
			le32_to_cpu(rxon->flags), ctx->ht.protection,
			ctx->ht.extension_chan_offset);
647
}
648
649
650
651
652
653
654
655

void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
{
	struct iwl_rxon_context *ctx;

	for_each_context(priv, ctx)
		_iwl_set_rxon_ht(priv, ht_conf, ctx);
}
656

657
/* Return valid, unused, channel for a passive scan to reset the RF */
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
658
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
659
				 enum ieee80211_band band)
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
660
661
662
663
{
	const struct iwl_channel_info *ch_info;
	int i;
	u8 channel = 0;
664
665
	u8 min, max;
	struct iwl_rxon_context *ctx;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
666
667

	if (band == IEEE80211_BAND_5GHZ) {
668
669
		min = 14;
		max = priv->channel_count;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
670
	} else {
671
672
673
674
675
676
677
678
679
680
681
682
		min = 0;
		max = 14;
	}

	for (i = min; i < max; i++) {
		bool busy = false;

		for_each_context(priv, ctx) {
			busy = priv->channel_info[i].channel ==
				le16_to_cpu(ctx->staging.channel);
			if (busy)
				break;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
683
		}
684
685
686
687
688
689
690
691

		if (busy)
			continue;

		channel = priv->channel_info[i].channel;
		ch_info = iwl_get_channel_info(priv, band, channel);
		if (is_channel_valid(ch_info))
			break;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
692
693
694
695
696
	}

	return channel;
}

697
/**
698
699
 * iwl_set_rxon_channel - Set the band and channel values in staging RXON
 * @ch: requested channel as a pointer to struct ieee80211_channel
700
701

 * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
702
 * in the staging RXON flag structure based on the ch->band
703
 */
704
705
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
			 struct iwl_rxon_context *ctx)
706
{
707
	enum ieee80211_band band = ch->band;
708
	u16 channel = ch->hw_value;
709

710
	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
711
712
713
	    (priv->band == band))
		return 0;

714
	ctx->staging.channel = cpu_to_le16(channel);
715
	if (band == IEEE80211_BAND_5GHZ)
716
		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
717
	else
718
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
719
720
721

	priv->band = band;

722
	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
723
724
725
726

	return 0;
}

727
void iwl_set_flags_for_band(struct iwl_priv *priv,
728
			    struct iwl_rxon_context *ctx,
729
730
			    enum ieee80211_band band,
			    struct ieee80211_vif *vif)
731
732
{
	if (band == IEEE80211_BAND_5GHZ) {
733
		ctx->staging.flags &=
734
735
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
736
		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
737
738
	} else {
		/* Copied from iwl_post_associate() */
739
		if (vif && vif->bss_conf.use_short_slot)
740
			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
741
		else
742
			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
743

744
745
746
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
747
748
749
750
751
752
	}
}

/*
 * initialize rxon structure with default values from eeprom
 */
753
void iwl_connection_init_rx_config(struct iwl_priv *priv,
754
				   struct iwl_rxon_context *ctx)
755
756
757
{
	const struct iwl_channel_info *ch_info;

758
	memset(&ctx->staging, 0, sizeof(ctx->staging));
759

760
761
762
	if (!ctx->vif) {
		ctx->staging.dev_type = ctx->unused_devtype;
	} else switch (ctx->vif->type) {
763
	case NL80211_IFTYPE_AP:
764
		ctx->staging.dev_type = ctx->ap_devtype;
765
766
767
		break;

	case NL80211_IFTYPE_STATION:
768
		ctx->staging.dev_type = ctx->station_devtype;
769
		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
770
771
772
		break;

	case NL80211_IFTYPE_ADHOC:
773
		ctx->staging.dev_type = ctx->ibss_devtype;
774
775
		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
776
777
778
779
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	default:
780
781
		IWL_ERR(priv, "Unsupported interface type %d\n",
			ctx->vif->type);
782
783
784
785
786
787
788
		break;
	}

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

	ch_info = iwl_get_channel_info(priv, priv->band,
795
				       le16_to_cpu(ctx->active.channel));
796
797
798
799

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

800
	ctx->staging.channel = cpu_to_le16(ch_info->channel);
801
802
	priv->band = ch_info->band;

803
	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
804

805
	ctx->staging.ofdm_basic_rates =
806
	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
807
	ctx->staging.cck_basic_rates =
808
809
	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

810
	/* clear both MIX and PURE40 mode flag */
811
	ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
812
					RXON_FLG_CHANNEL_MODE_PURE_40);
813
814
	if (ctx->vif)
		memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
815

816
817
818
	ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
	ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
819
820
}

821
void iwl_set_rate(struct iwl_priv *priv)
822
823
824
{
	const struct ieee80211_supported_band *hw = NULL;
	struct ieee80211_rate *rate;
825
	struct iwl_rxon_context *ctx;
826
827
828
829
830
831
832
833
834
835
836
837
	int i;

	hw = iwl_get_hw_mode(priv, priv->band);
	if (!hw) {
		IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
		return;
	}

	priv->active_rate = 0;

	for (i = 0; i < hw->n_bitrates; i++) {
		rate = &(hw->bitrates[i]);
838
		if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
839
840
841
			priv->active_rate |= (1 << rate->hw_value);
	}

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

844
845
846
	for_each_context(priv, ctx) {
		ctx->staging.cck_basic_rates =
		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
847

848
849
850
		ctx->staging.ofdm_basic_rates =
		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
	}
851
}
852
853
854

void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
855
856
857
858
859
860
	/*
	 * MULTI-FIXME
	 * See iwl_mac_channel_switch.
	 */
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];

861
862
863
864
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	if (priv->switch_rxon.switch_in_progress) {
865
		ieee80211_chswitch_done(ctx->vif, is_success);
866
867
868
869
870
		mutex_lock(&priv->mutex);
		priv->switch_rxon.switch_in_progress = false;
		mutex_unlock(&priv->mutex);
	}
}
871
872

#ifdef CONFIG_IWLWIFI_DEBUG
873
874
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
			     struct iwl_rxon_context *ctx)
875
{
876
	struct iwl_rxon_cmd *rxon = &ctx->staging;
877

878
	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
879
	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
880
881
882
	IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
	IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
	IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
883
			le32_to_cpu(rxon->filter_flags));
884
885
	IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
	IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
886
			rxon->ofdm_basic_rates);
887
888
889
890
	IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
	IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
891
}
892
#endif
893
894

void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
895
{
896
897
898
	unsigned int reload_msec;
	unsigned long reload_jiffies;

899
900
901
902
903
904
	/* Set the FW error flag -- cleared on iwl_down */
	set_bit(STATUS_FW_ERROR, &priv->status);

	/* Cancel currently queued command. */
	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);

905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
	/* Keep the restart process from trying to send host
	 * commands by clearing the ready bit */
	clear_bit(STATUS_READY, &priv->status);

	wake_up_interruptible(&priv->wait_command_queue);

	if (!ondemand) {
		/*
		 * If firmware keep reloading, then it indicate something
		 * serious wrong and firmware having problem to recover
		 * from it. Instead of keep trying which will fill the syslog
		 * and hang the system, let's just stop it
		 */
		reload_jiffies = jiffies;
		reload_msec = jiffies_to_msecs((long) reload_jiffies -
					(long) priv->reload_jiffies);
		priv->reload_jiffies = reload_jiffies;
		if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
			priv->reload_count++;
			if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
				IWL_ERR(priv, "BUG_ON, Stop restarting\n");
				return;
			}
		} else
			priv->reload_count = 0;
	}

	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
		if (priv->cfg->mod_params->restart_fw) {
			IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
				  "Restarting adapter due to uCode error.\n");
			queue_work(priv->workqueue, &priv->restart);
		} else
			IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
				  "Detected FW error, but not restarting\n");
	}
}

/**
 * iwl_irq_handle_error - called for HW or SW error interrupt from card
 */
void iwl_irq_handle_error(struct iwl_priv *priv)
{
948
949
950
951
952
953
954
	/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
	if (priv->cfg->internal_wimax_coex &&
	    (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) &
			APMS_CLK_VAL_MRB_FUNC_MODE) ||
	     (iwl_read_prph(priv, APMG_PS_CTRL_REG) &
			APMG_PS_CTRL_VAL_RESET_REQ))) {
		/*
955
956
		 * Keep the restart process from trying to send host
		 * commands by clearing the ready bit.
957
958
		 */
		clear_bit(STATUS_READY, &priv->status);
959
960
		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
		wake_up_interruptible(&priv->wait_command_queue);
961
962
963
964
		IWL_ERR(priv, "RF is used by WiMAX\n");
		return;
	}

965
966
967
	IWL_ERR(priv, "Loaded firmware version: %s\n",
		priv->hw->wiphy->fw_version);

968
	priv->cfg->ops->lib->dump_nic_error_log(priv);
969
970
	if (priv->cfg->ops->lib->dump_csr)
		priv->cfg->ops->lib->dump_csr(priv);
971
972
	if (priv->cfg->ops->lib->dump_fh)
		priv->cfg->ops->lib->dump_fh(priv, NULL, false);
Wey-Yi Guy's avatar
Wey-Yi Guy committed
973
	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
974
#ifdef CONFIG_IWLWIFI_DEBUG
975
	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
976
977
		iwl_print_rx_config_cmd(priv,
					&priv->contexts[IWL_RXON_CTX_BSS]);
978
979
#endif

980
	iwlagn_fw_error(priv, false);
981
982
}

983
static int iwl_apm_stop_master(struct iwl_priv *priv)
984
{
985
	int ret = 0;
986

987
	/* stop device's busmaster DMA activity */
988
989
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);

990
	ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
991
			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
992
993
	if (ret)
		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
994
995
996

	IWL_DEBUG_INFO(priv, "stop master\n");

997
	return ret;
998
999
1000
1001
}

void iwl_apm_stop(struct iwl_priv *priv)
{
1002
1003
	IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");

1004
	/* Stop device's DMA activity */
1005
1006
	iwl_apm_stop_master(priv);

1007
	/* Reset the entire device */
1008
1009
1010
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);

	udelay(10);
1011
1012
1013
1014
1015

	/*
	 * Clear "initialization complete" bit to move adapter from
	 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
	 */
1016
1017
1018
	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
}

1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059

/*
 * Start up NIC's basic functionality after it has been reset
 * (e.g. after platform boot, or shutdown via iwl_apm_stop())
 * NOTE:  This does not load uCode nor start the embedded processor
 */
int iwl_apm_init(struct iwl_priv *priv)
{
	int ret = 0;
	u16 lctl;

	IWL_DEBUG_INFO(priv, "Init card's basic functions\n");

	/*
	 * Use "set_bit" below rather than "write", to preserve any hardware
	 * bits already set by default after reset.
	 */

	/* Disable L0S exit timer (platform NMI Work/Around) */
	iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
			  CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);

	/*
	 * Disable L0s without affecting L1;
	 *  don't wait for ICH L0s (ICH bug W/A)
	 */
	iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
			  CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);

	/* Set FH wait threshold to maximum (HW error during stress W/A) */
	iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL