iwl-core.c 54.5 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
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

70
71
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
72
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
73
			      struct ieee80211_sta_ht_cap *ht_info,
74
75
			      enum ieee80211_band band)
{
Ron Rindjunsky's avatar
Ron Rindjunsky committed
76
77
78
79
	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;

80
	ht_info->cap = 0;
81
	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
82

83
	ht_info->ht_supported = true;
84

85
86
	if (priv->cfg->ht_params &&
	    priv->cfg->ht_params->ht_greenfield_support)
87
		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
88
	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
89
	max_bit_rate = MAX_BIT_RATE_20_MHZ;
90
	if (priv->hw_params.ht40_channel & BIT(band)) {
91
92
93
		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
94
		max_bit_rate = MAX_BIT_RATE_40_MHZ;
95
96
97
	}

	if (priv->cfg->mod_params->amsdu_size_8K)
98
		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
99
100

	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
101
102
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
		ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
103
	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
104
105
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
		ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
106

107
	ht_info->mcs.rx_mask[0] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
108
	if (rx_chains_num >= 2)
109
		ht_info->mcs.rx_mask[1] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
110
	if (rx_chains_num >= 3)
111
		ht_info->mcs.rx_mask[2] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
112
113
114

	/* Highest supported Rx data rate */
	max_bit_rate *= rx_chains_num;
115
116
	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
117
118

	/* Tx MCS capabilities */
119
	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
120
	if (tx_chains_num != rx_chains_num) {
121
122
123
		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
124
	}
125
126
127
128
129
}

/**
 * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
 */
130
int iwlcore_init_geos(struct iwl_priv *priv)
131
132
133
134
135
136
137
{
	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;
138
	s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN;
139
140
141

	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
142
		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
143
144
145
146
147
148
149
150
151
		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
		return 0;
	}

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

152
	rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
153
154
155
156
157
158
159
160
161
162
163
			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];
164
	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
165

166
	if (priv->cfg->sku & IWL_SKU_N)
167
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
168
					 IEEE80211_BAND_5GHZ);
169
170
171
172
173

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

176
	if (priv->cfg->sku & IWL_SKU_N)
177
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
178
					 IEEE80211_BAND_2GHZ);
179
180
181
182
183
184
185
186
187
188
189

	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;

190
		sband =  &priv->bands[ch->band];
191
192
193
194

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

		geo_ch->center_freq =
195
			ieee80211_channel_to_frequency(ch->channel, ch->band);
196
197
198
199
200
201
202
203
204
205
206
207
208
209
		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;

210
			geo_ch->flags |= ch->ht40_extension_channel;
211

212
213
			if (ch->max_power_avg > max_tx_power)
				max_tx_power = ch->max_power_avg;
214
215
216
217
		} else {
			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
		}

218
		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
219
220
221
222
223
224
225
				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);
	}

226
227
228
229
	priv->tx_power_device_lmt = max_tx_power;
	priv->tx_power_user_lmt = max_tx_power;
	priv->tx_power_next = max_tx_power;

230
231
	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
	     priv->cfg->sku & IWL_SKU_A) {
Tomas Winkler's avatar
Tomas Winkler committed
232
233
		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
234
235
			   priv->pci_dev->device,
			   priv->pci_dev->subsystem_device);
236
237
238
		priv->cfg->sku &= ~IWL_SKU_A;
	}

Tomas Winkler's avatar
Tomas Winkler committed
239
	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
240
241
		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
242
243
244
245
246
247
248
249
250

	set_bit(STATUS_GEO_CONFIGURED, &priv->status);

	return 0;
}

/*
 * iwlcore_free_geos - undo allocations in iwlcore_init_geos
 */
251
void iwlcore_free_geos(struct iwl_priv *priv)
252
253
254
255
256
257
{
	kfree(priv->ieee_channels);
	kfree(priv->ieee_rates);
	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}

258
259
260
static bool iwl_is_channel_extension(struct iwl_priv *priv,
				     enum ieee80211_band band,
				     u16 channel, u8 extension_chan_offset)
261
262
263
264
265
{
	const struct iwl_channel_info *ch_info;

	ch_info = iwl_get_channel_info(priv, band, channel);
	if (!is_channel_valid(ch_info))
266
		return false;
267

268
	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
269
		return !(ch_info->ht40_extension_channel &
270
					IEEE80211_CHAN_NO_HT40PLUS);
271
	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
272
		return !(ch_info->ht40_extension_channel &
273
					IEEE80211_CHAN_NO_HT40MINUS);
274

275
	return false;
276
277
}

278
279
280
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
			    struct iwl_rxon_context *ctx,
			    struct ieee80211_sta_ht_cap *ht_cap)
281
{
282
283
	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
		return false;
284

285
286
	/*
	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
287
288
	 * the bit will not set if it is pure 40MHz case
	 */
289
290
291
	if (ht_cap && !ht_cap->ht_supported)
		return false;

292
#ifdef CONFIG_IWLWIFI_DEBUGFS
293
	if (priv->disable_ht40)
294
		return false;
295
#endif
296

297
	return iwl_is_channel_extension(priv, priv->band,
298
			le16_to_cpu(ctx->staging.channel),
299
			ctx->ht.extension_chan_offset);
300
301
}

302
303
static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
	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.
	 */
327
328
329
330
331
332
333
334
335
336

	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;
}

337
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
338
339
340
341
342
{
	u64 tsf;
	s32 interval_tm, rem;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int;
343
	struct ieee80211_vif *vif = ctx->vif;
344
345
346

	conf = ieee80211_get_hw_conf(priv->hw);

347
348
	lockdep_assert_held(&priv->mutex);

349
	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
350

351
352
	ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
353

354
	beacon_int = vif ? vif->bss_conf.beacon_int : 0;
355

356
357
358
359
360
	/*
	 * TODO: For IBSS we need to get atim_window from mac80211,
	 *	 for now just always use 0
	 */
	ctx->timing.atim_window = 0;
361

362
	if (ctx->ctxid == IWL_RXON_CTX_PAN &&
363
364
365
366
	    (!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) {
367
368
369
		ctx->timing.beacon_interval =
			priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval;
		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
370
371
372
373
374
375
376
377
378
	} 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);
379
380
	} else {
		beacon_int = iwl_adjust_beacon_interval(beacon_int,
381
				priv->hw_params.max_beacon_itrvl * TIME_UNIT);
382
383
		ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
	}
384
385

	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
386
	interval_tm = beacon_int * TIME_UNIT;
387
	rem = do_div(tsf, interval_tm);
388
	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
389

390
	ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
391

392
393
	IWL_DEBUG_ASSOC(priv,
			"beacon interval %d beacon timer %d beacon tim %d\n",
394
395
396
			le16_to_cpu(ctx->timing.beacon_interval),
			le32_to_cpu(ctx->timing.beacon_init_val),
			le16_to_cpu(ctx->timing.atim_window));
397

398
	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
399
				sizeof(ctx->timing), &ctx->timing);
400
401
}

402
403
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
			   int hw_decrypt)
404
{
405
	struct iwl_rxon_cmd *rxon = &ctx->staging;
406
407
408
409
410
411
412
413

	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
414
/* validate RXON structure is valid */
415
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
416
{
417
	struct iwl_rxon_cmd *rxon = &ctx->staging;
Johannes Berg's avatar
Johannes Berg committed
418
	bool error = false;
419
420

	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
Johannes Berg's avatar
Johannes Berg committed
421
422
423
424
425
426
427
428
		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;
		}
429
	} else {
Johannes Berg's avatar
Johannes Berg committed
430
431
432
433
434
435
436
437
438
439
440
441
		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;
442
443
444
	}

	/* make sure basic rates 6Mbps and 1Mbps are supported */
Johannes Berg's avatar
Johannes Berg committed
445
446
447
448
449
	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;
	}
450

Johannes Berg's avatar
Johannes Berg committed
451
452
453
454
	if (le16_to_cpu(rxon->assoc_id) > 2007) {
		IWL_WARN(priv, "aid > 2007\n");
		error = true;
	}
455

Johannes Berg's avatar
Johannes Berg committed
456
457
458
459
460
	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;
	}
461

Johannes Berg's avatar
Johannes Berg committed
462
463
464
465
466
	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;
	}
467

Johannes Berg's avatar
Johannes Berg committed
468
469
470
471
472
473
	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;
	}
474
475
476
477
478
479

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

	if (error) {
Johannes Berg's avatar
Johannes Berg committed
480
481
		IWL_ERR(priv, "Invalid RXON\n");
		return -EINVAL;
482
483
484
485
486
487
488
489
490
491
492
493
	}
	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.
 */
494
495
int iwl_full_rxon_required(struct iwl_priv *priv,
			   struct iwl_rxon_context *ctx)
496
{
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
	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;					\
	}
513
514

	/* These items are only settable from the full RXON command */
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
	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);
530
531
532
533
534
535

	/* 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 */
536
537
	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
		active->flags & RXON_FLG_BAND_24G_MSK);
538
539

	/* Check if we are switching association toggle */
540
541
542
543
544
	CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
		active->filter_flags & RXON_FILTER_ASSOC_MSK);

#undef CHK
#undef CHK_NEQ
545
546
547
548

	return 0;
}

549
550
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
			    struct iwl_rxon_context *ctx)
551
{
552
553
554
555
	/*
	 * Assign the lowest rate -- should really get this from
	 * the beacon skb from mac80211.
	 */
556
	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
557
558
559
560
561
		return IWL_RATE_1M_PLCP;
	else
		return IWL_RATE_6M_PLCP;
}

562
563
564
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
			     struct iwl_ht_config *ht_conf,
			     struct iwl_rxon_context *ctx)
565
{
566
	struct iwl_rxon_cmd *rxon = &ctx->staging;
567

568
	if (!ctx->ht.enabled) {
569
		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
570
			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
571
			RXON_FLG_HT40_PROT_MSK |
572
			RXON_FLG_HT_PROT_MSK);
573
		return;
574
	}
575

576
	/* FIXME: if the definition of ht.protection changed, the "translation"
577
578
	 * will be needed for rxon->flags
	 */
579
	rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
580
581

	/* Set up channel bandwidth:
582
	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
583
584
585
	/* clear the HT channel mode before set the mode */
	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
586
	if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
587
		/* pure ht40 */
588
		if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
589
			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
590
			/* Note: control channel is opposite of extension channel */
591
			switch (ctx->ht.extension_chan_offset) {
592
593
594
595
596
597
598
599
			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 {
600
			/* Note: control channel is opposite of extension channel */
601
			switch (ctx->ht.extension_chan_offset) {
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
			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;
619
620
	}

621
	if (priv->cfg->ops->hcmd->set_rxon_chain)
622
		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
623

624
	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
Johannes Berg's avatar
Johannes Berg committed
625
			"extension channel offset 0x%x\n",
626
627
			le32_to_cpu(rxon->flags), ctx->ht.protection,
			ctx->ht.extension_chan_offset);
628
}
629
630
631
632
633
634
635
636

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);
}
637

638
/* Return valid, unused, channel for a passive scan to reset the RF */
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
639
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
640
				 enum ieee80211_band band)
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
641
642
643
644
{
	const struct iwl_channel_info *ch_info;
	int i;
	u8 channel = 0;
645
646
	u8 min, max;
	struct iwl_rxon_context *ctx;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
647
648

	if (band == IEEE80211_BAND_5GHZ) {
649
650
		min = 14;
		max = priv->channel_count;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
651
	} else {
652
653
654
655
656
657
658
659
660
661
662
663
		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
664
		}
665
666
667
668
669
670
671
672

		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
673
674
675
676
677
	}

	return channel;
}

678
/**
679
680
 * iwl_set_rxon_channel - Set the band and channel values in staging RXON
 * @ch: requested channel as a pointer to struct ieee80211_channel
681
682

 * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
683
 * in the staging RXON flag structure based on the ch->band
684
 */
685
686
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
			 struct iwl_rxon_context *ctx)
687
{
688
	enum ieee80211_band band = ch->band;
689
	u16 channel = ch->hw_value;
690

691
	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
692
693
694
	    (priv->band == band))
		return 0;

695
	ctx->staging.channel = cpu_to_le16(channel);
696
	if (band == IEEE80211_BAND_5GHZ)
697
		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
698
	else
699
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
700
701
702

	priv->band = band;

703
	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
704
705
706
707

	return 0;
}

708
void iwl_set_flags_for_band(struct iwl_priv *priv,
709
			    struct iwl_rxon_context *ctx,
710
711
			    enum ieee80211_band band,
			    struct ieee80211_vif *vif)
712
713
{
	if (band == IEEE80211_BAND_5GHZ) {
714
		ctx->staging.flags &=
715
716
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
717
		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
718
719
	} else {
		/* Copied from iwl_post_associate() */
720
		if (vif && vif->bss_conf.use_short_slot)
721
			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
722
		else
723
			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
724

725
726
727
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
728
729
730
731
732
733
	}
}

/*
 * initialize rxon structure with default values from eeprom
 */
734
void iwl_connection_init_rx_config(struct iwl_priv *priv,
735
				   struct iwl_rxon_context *ctx)
736
737
738
{
	const struct iwl_channel_info *ch_info;

739
	memset(&ctx->staging, 0, sizeof(ctx->staging));
740

741
742
743
	if (!ctx->vif) {
		ctx->staging.dev_type = ctx->unused_devtype;
	} else switch (ctx->vif->type) {
744
	case NL80211_IFTYPE_AP:
745
		ctx->staging.dev_type = ctx->ap_devtype;
746
747
748
		break;

	case NL80211_IFTYPE_STATION:
749
		ctx->staging.dev_type = ctx->station_devtype;
750
		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
751
752
753
		break;

	case NL80211_IFTYPE_ADHOC:
754
		ctx->staging.dev_type = ctx->ibss_devtype;
755
756
		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
757
758
759
760
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	default:
761
762
		IWL_ERR(priv, "Unsupported interface type %d\n",
			ctx->vif->type);
763
764
765
766
767
768
769
		break;
	}

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

	ch_info = iwl_get_channel_info(priv, priv->band,
776
				       le16_to_cpu(ctx->active.channel));
777
778
779
780

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

781
	ctx->staging.channel = cpu_to_le16(ch_info->channel);
782
783
	priv->band = ch_info->band;

784
	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
785

786
	ctx->staging.ofdm_basic_rates =
787
	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
788
	ctx->staging.cck_basic_rates =
789
790
	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

791
	/* clear both MIX and PURE40 mode flag */
792
	ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
793
					RXON_FLG_CHANNEL_MODE_PURE_40);
794
795
	if (ctx->vif)
		memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
796

797
798
799
	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;
800
801
}

802
void iwl_set_rate(struct iwl_priv *priv)
803
804
805
{
	const struct ieee80211_supported_band *hw = NULL;
	struct ieee80211_rate *rate;
806
	struct iwl_rxon_context *ctx;
807
808
809
810
811
812
813
814
815
816
817
818
	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]);
819
		if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
820
821
822
			priv->active_rate |= (1 << rate->hw_value);
	}

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

825
826
827
	for_each_context(priv, ctx) {
		ctx->staging.cck_basic_rates =
		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
828

829
830
831
		ctx->staging.ofdm_basic_rates =
		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
	}
832
}
833
834
835

void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
836
837
838
839
840
841
	/*
	 * MULTI-FIXME
	 * See iwl_mac_channel_switch.
	 */
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];

842
843
844
845
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	if (priv->switch_rxon.switch_in_progress) {
846
		ieee80211_chswitch_done(ctx->vif, is_success);
847
848
849
850
851
		mutex_lock(&priv->mutex);
		priv->switch_rxon.switch_in_progress = false;
		mutex_unlock(&priv->mutex);
	}
}
852
853

#ifdef CONFIG_IWLWIFI_DEBUG
854
855
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
			     struct iwl_rxon_context *ctx)
856
{
857
	struct iwl_rxon_cmd *rxon = &ctx->staging;
858

859
	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
860
	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
861
862
863
	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",
864
			le32_to_cpu(rxon->filter_flags));
865
866
	IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
	IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
867
			rxon->ofdm_basic_rates);
868
869
870
871
	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));
872
}
873
#endif
874

875
876
877
878
879
880
881
882
883
884
885
886
887
static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
{
	unsigned long flags;
	struct iwl_notification_wait *wait_entry;

	spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags);
	list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list)
		wait_entry->aborted = true;
	spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags);

	wake_up_all(&priv->_agn.notif_waitq);
}

888
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
889
{
890
891
892
	unsigned int reload_msec;
	unsigned long reload_jiffies;

893
894
895
896
897
898
	/* 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);

899
900
	iwlagn_abort_notification_waits(priv);

901
902
903
904
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
	/* 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)
{
944
945
946
947
948
949
950
	/* 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))) {
		/*
951
952
		 * Keep the restart process from trying to send host
		 * commands by clearing the ready bit.
953
954
		 */
		clear_bit(STATUS_READY, &priv->status);
955
956
		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
		wake_up_interruptible(&priv->wait_command_queue);
957
958
959
960
		IWL_ERR(priv, "RF is used by WiMAX\n");
		return;
	}

961
962
963
	IWL_ERR(priv, "Loaded firmware version: %s\n",
		priv->hw->wiphy->fw_version);

964
965
966
967
	iwl_dump_nic_error_log(priv);
	iwl_dump_csr(priv);
	iwl_dump_fh(priv, NULL, false);
	iwl_dump_nic_event_log(priv, false, NULL, false);
968
#ifdef CONFIG_IWLWIFI_DEBUG
969
	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
970
971
		iwl_print_rx_config_cmd(priv,
					&priv->contexts[IWL_RXON_CTX_BSS]);
972
973
#endif

974
	iwlagn_fw_error(priv, false);
975
976
}

977
static int iwl_apm_stop_master(struct iwl_priv *priv)
978
{
979
	int ret = 0;
980

981
	/* stop device's busmaster DMA activity */
982
983
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);

984
	ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
985
			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
986
987
	if (ret)
		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
988
989
990

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

991
	return ret;
992
993
994
995
}

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

998
999
	clear_bit(STATUS_DEVICE_ENABLED, &priv->status);

1000
	/* Stop device's DMA activity */
1001
1002
	iwl_apm_stop_master(priv);

1003
	/* Reset the entire device */
1004
1005
1006
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);

	udelay(10);
1007
1008
1009
1010
1011

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

1015
1016
1017
1018
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

/*
 * 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);

	/*
	 * Enable HAP INTA (interrupt from management bus) to
	 * wake device's PCI Express link L1a -> L0s
	 */
	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);

	/*
1055
1056
1057
1058
1059
1060
	 * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
	 * If so (likely), disable L0S, so device moves directly L0->L1;
	 *    costs negligible amount of power savings.
	 * If not (unlikely), enable L0S, so there is at least some
	 *    power savings, even without L1.
1061
	 */