iwl-core.c 52.4 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"
Don Fry's avatar
Don Fry committed
44
#include "iwl-agn.h"
45
#include "iwl-trans.h"
Tomas Winkler's avatar
Tomas Winkler committed
46

47
48
u32 iwl_debug_level;

49
50
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

51
52
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
53
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
54
			      struct ieee80211_sta_ht_cap *ht_info,
55
56
			      enum ieee80211_band band)
{
Ron Rindjunsky's avatar
Ron Rindjunsky committed
57
58
59
60
	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;

61
	ht_info->cap = 0;
62
	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
63

64
	ht_info->ht_supported = true;
65

66
67
	if (priv->cfg->ht_params &&
	    priv->cfg->ht_params->ht_greenfield_support)
68
		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
69
	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
70
	max_bit_rate = MAX_BIT_RATE_20_MHZ;
71
	if (priv->hw_params.ht40_channel & BIT(band)) {
72
73
74
		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
75
		max_bit_rate = MAX_BIT_RATE_40_MHZ;
76
77
	}

Don Fry's avatar
Don Fry committed
78
	if (iwlagn_mod_params.amsdu_size_8K)
79
		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
80
81

	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
82
83
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
		ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
84
	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
85
86
	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
		ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
87

88
	ht_info->mcs.rx_mask[0] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
89
	if (rx_chains_num >= 2)
90
		ht_info->mcs.rx_mask[1] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
91
	if (rx_chains_num >= 3)
92
		ht_info->mcs.rx_mask[2] = 0xFF;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
93
94
95

	/* Highest supported Rx data rate */
	max_bit_rate *= rx_chains_num;
96
97
	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
98
99

	/* Tx MCS capabilities */
100
	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
101
	if (tx_chains_num != rx_chains_num) {
102
103
104
		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
105
	}
106
107
108
109
110
}

/**
 * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
 */
111
int iwlcore_init_geos(struct iwl_priv *priv)
112
113
114
115
116
117
118
{
	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;
119
	s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN;
120
121
122

	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
123
		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
124
125
126
127
128
129
130
131
132
		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
		return 0;
	}

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

133
	rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
134
135
136
137
138
139
140
141
142
143
144
			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];
145
	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
146

147
	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
148
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
149
					 IEEE80211_BAND_5GHZ);
150
151
152
153
154

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

157
	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
158
		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
159
					 IEEE80211_BAND_2GHZ);
160
161
162
163
164
165
166
167
168
169
170

	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;

171
		sband =  &priv->bands[ch->band];
172
173
174
175

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

		geo_ch->center_freq =
176
			ieee80211_channel_to_frequency(ch->channel, ch->band);
177
178
179
180
181
182
183
184
185
186
187
188
189
190
		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;

191
			geo_ch->flags |= ch->ht40_extension_channel;
192

193
194
			if (ch->max_power_avg > max_tx_power)
				max_tx_power = ch->max_power_avg;
195
196
197
198
		} else {
			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
		}

199
		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
200
201
202
203
204
205
206
				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);
	}

207
208
209
210
	priv->tx_power_device_lmt = max_tx_power;
	priv->tx_power_user_lmt = max_tx_power;
	priv->tx_power_next = max_tx_power;

211
	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
212
	     priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
213
		char buf[32];
214
		bus_get_hw_id(priv->bus, buf, sizeof(buf));
Tomas Winkler's avatar
Tomas Winkler committed
215
		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
216
			"Please send your %s to maintainer.\n", buf);
217
		priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
218
219
	}

Tomas Winkler's avatar
Tomas Winkler committed
220
	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
221
222
		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
223
224
225
226
227
228
229
230
231

	set_bit(STATUS_GEO_CONFIGURED, &priv->status);

	return 0;
}

/*
 * iwlcore_free_geos - undo allocations in iwlcore_init_geos
 */
232
void iwlcore_free_geos(struct iwl_priv *priv)
233
234
235
236
237
238
{
	kfree(priv->ieee_channels);
	kfree(priv->ieee_rates);
	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
}

239
240
241
static bool iwl_is_channel_extension(struct iwl_priv *priv,
				     enum ieee80211_band band,
				     u16 channel, u8 extension_chan_offset)
242
243
244
245
246
{
	const struct iwl_channel_info *ch_info;

	ch_info = iwl_get_channel_info(priv, band, channel);
	if (!is_channel_valid(ch_info))
247
		return false;
248

249
	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
250
		return !(ch_info->ht40_extension_channel &
251
					IEEE80211_CHAN_NO_HT40PLUS);
252
	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
253
		return !(ch_info->ht40_extension_channel &
254
					IEEE80211_CHAN_NO_HT40MINUS);
255

256
	return false;
257
258
}

259
260
261
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
			    struct iwl_rxon_context *ctx,
			    struct ieee80211_sta_ht_cap *ht_cap)
262
{
263
264
	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
		return false;
265

266
267
	/*
	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
268
269
	 * the bit will not set if it is pure 40MHz case
	 */
270
271
272
	if (ht_cap && !ht_cap->ht_supported)
		return false;

273
#ifdef CONFIG_IWLWIFI_DEBUGFS
274
	if (priv->disable_ht40)
275
		return false;
276
#endif
277

278
	return iwl_is_channel_extension(priv, priv->band,
279
			le16_to_cpu(ctx->staging.channel),
280
			ctx->ht.extension_chan_offset);
281
282
}

283
284
static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
	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.
	 */
308
309
310
311
312
313
314
315
316
317

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

318
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
319
320
321
322
323
{
	u64 tsf;
	s32 interval_tm, rem;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int;
324
	struct ieee80211_vif *vif = ctx->vif;
325
326
327

	conf = ieee80211_get_hw_conf(priv->hw);

328
329
	lockdep_assert_held(&priv->mutex);

330
	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
331

332
333
	ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
334

335
	beacon_int = vif ? vif->bss_conf.beacon_int : 0;
336

337
338
339
340
341
	/*
	 * TODO: For IBSS we need to get atim_window from mac80211,
	 *	 for now just always use 0
	 */
	ctx->timing.atim_window = 0;
342

343
	if (ctx->ctxid == IWL_RXON_CTX_PAN &&
344
345
346
347
	    (!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) {
348
349
350
		ctx->timing.beacon_interval =
			priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval;
		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
351
352
353
354
355
356
357
358
359
	} 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);
360
361
	} else {
		beacon_int = iwl_adjust_beacon_interval(beacon_int,
362
				priv->hw_params.max_beacon_itrvl * TIME_UNIT);
363
364
		ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
	}
365

366
367
	ctx->beacon_int = beacon_int;

368
	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
369
	interval_tm = beacon_int * TIME_UNIT;
370
	rem = do_div(tsf, interval_tm);
371
	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
372

373
	ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
374

375
376
	IWL_DEBUG_ASSOC(priv,
			"beacon interval %d beacon timer %d beacon tim %d\n",
377
378
379
			le16_to_cpu(ctx->timing.beacon_interval),
			le32_to_cpu(ctx->timing.beacon_init_val),
			le16_to_cpu(ctx->timing.atim_window));
380

381
	return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd,
382
				CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
383
384
}

385
386
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
			   int hw_decrypt)
387
{
388
	struct iwl_rxon_cmd *rxon = &ctx->staging;
389
390
391
392
393
394
395
396

	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
397
/* validate RXON structure is valid */
398
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
399
{
400
	struct iwl_rxon_cmd *rxon = &ctx->staging;
Johannes Berg's avatar
Johannes Berg committed
401
	u32 errors = 0;
402
403

	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
Johannes Berg's avatar
Johannes Berg committed
404
405
		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
			IWL_WARN(priv, "check 2.4G: wrong narrow\n");
Johannes Berg's avatar
Johannes Berg committed
406
			errors |= BIT(0);
Johannes Berg's avatar
Johannes Berg committed
407
408
409
		}
		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
			IWL_WARN(priv, "check 2.4G: wrong radar\n");
Johannes Berg's avatar
Johannes Berg committed
410
			errors |= BIT(1);
Johannes Berg's avatar
Johannes Berg committed
411
		}
412
	} else {
Johannes Berg's avatar
Johannes Berg committed
413
414
		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
			IWL_WARN(priv, "check 5.2G: not short slot!\n");
Johannes Berg's avatar
Johannes Berg committed
415
			errors |= BIT(2);
Johannes Berg's avatar
Johannes Berg committed
416
417
418
		}
		if (rxon->flags & RXON_FLG_CCK_MSK) {
			IWL_WARN(priv, "check 5.2G: CCK!\n");
Johannes Berg's avatar
Johannes Berg committed
419
			errors |= BIT(3);
Johannes Berg's avatar
Johannes Berg committed
420
421
422
423
		}
	}
	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
		IWL_WARN(priv, "mac/bssid mcast!\n");
Johannes Berg's avatar
Johannes Berg committed
424
		errors |= BIT(4);
425
426
427
	}

	/* make sure basic rates 6Mbps and 1Mbps are supported */
Johannes Berg's avatar
Johannes Berg committed
428
429
430
	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");
Johannes Berg's avatar
Johannes Berg committed
431
		errors |= BIT(5);
Johannes Berg's avatar
Johannes Berg committed
432
	}
433

Johannes Berg's avatar
Johannes Berg committed
434
435
	if (le16_to_cpu(rxon->assoc_id) > 2007) {
		IWL_WARN(priv, "aid > 2007\n");
Johannes Berg's avatar
Johannes Berg committed
436
		errors |= BIT(6);
Johannes Berg's avatar
Johannes Berg committed
437
	}
438

Johannes Berg's avatar
Johannes Berg committed
439
440
441
	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");
Johannes Berg's avatar
Johannes Berg committed
442
		errors |= BIT(7);
Johannes Berg's avatar
Johannes Berg committed
443
	}
444

Johannes Berg's avatar
Johannes Berg committed
445
446
447
	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");
Johannes Berg's avatar
Johannes Berg committed
448
		errors |= BIT(8);
Johannes Berg's avatar
Johannes Berg committed
449
	}
450

Johannes Berg's avatar
Johannes Berg committed
451
452
453
454
	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");
Johannes Berg's avatar
Johannes Berg committed
455
		errors |= BIT(9);
Johannes Berg's avatar
Johannes Berg committed
456
	}
457

Johannes Berg's avatar
Johannes Berg committed
458
459
460
	if (rxon->channel == 0) {
		IWL_WARN(priv, "zero channel is invalid\n");
		errors |= BIT(10);
461
	}
Johannes Berg's avatar
Johannes Berg committed
462
463
464
465
466

	WARN(errors, "Invalid RXON (%#x), channel %d",
	     errors, le16_to_cpu(rxon->channel));

	return errors ? -EINVAL : 0;
467
468
469
470
471
472
473
474
475
476
}

/**
 * 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.
 */
477
478
int iwl_full_rxon_required(struct iwl_priv *priv,
			   struct iwl_rxon_context *ctx)
479
{
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	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;					\
	}
496
497

	/* These items are only settable from the full RXON command */
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
	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);
513
514
515
516
517
518

	/* 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 */
519
520
	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
		active->flags & RXON_FLG_BAND_24G_MSK);
521
522

	/* Check if we are switching association toggle */
523
524
525
526
527
	CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
		active->filter_flags & RXON_FILTER_ASSOC_MSK);

#undef CHK
#undef CHK_NEQ
528
529
530
531

	return 0;
}

532
533
534
static void _iwl_set_rxon_ht(struct iwl_priv *priv,
			     struct iwl_ht_config *ht_conf,
			     struct iwl_rxon_context *ctx)
535
{
536
	struct iwl_rxon_cmd *rxon = &ctx->staging;
537

538
	if (!ctx->ht.enabled) {
539
		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
540
			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
541
			RXON_FLG_HT40_PROT_MSK |
542
			RXON_FLG_HT_PROT_MSK);
543
		return;
544
	}
545

546
	/* FIXME: if the definition of ht.protection changed, the "translation"
547
548
	 * will be needed for rxon->flags
	 */
549
	rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
550
551

	/* Set up channel bandwidth:
552
	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
553
554
555
	/* clear the HT channel mode before set the mode */
	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
556
	if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
557
		/* pure ht40 */
558
		if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
559
			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
560
			/* Note: control channel is opposite of extension channel */
561
			switch (ctx->ht.extension_chan_offset) {
562
563
564
565
566
567
568
569
			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 {
570
			/* Note: control channel is opposite of extension channel */
571
			switch (ctx->ht.extension_chan_offset) {
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
			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;
589
590
	}

Wey-Yi Guy's avatar
Wey-Yi Guy committed
591
	iwlagn_set_rxon_chain(priv, ctx);
592

593
	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
Johannes Berg's avatar
Johannes Berg committed
594
			"extension channel offset 0x%x\n",
595
596
			le32_to_cpu(rxon->flags), ctx->ht.protection,
			ctx->ht.extension_chan_offset);
597
}
598
599
600
601
602
603
604
605

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

607
/* Return valid, unused, channel for a passive scan to reset the RF */
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
608
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
609
				 enum ieee80211_band band)
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
610
611
612
613
{
	const struct iwl_channel_info *ch_info;
	int i;
	u8 channel = 0;
614
615
	u8 min, max;
	struct iwl_rxon_context *ctx;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
616
617

	if (band == IEEE80211_BAND_5GHZ) {
618
619
		min = 14;
		max = priv->channel_count;
Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
620
	} else {
621
622
623
624
625
626
627
628
629
630
631
632
		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
633
		}
634
635
636
637
638
639
640
641

		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
642
643
644
645
646
	}

	return channel;
}

647
/**
648
649
 * iwl_set_rxon_channel - Set the band and channel values in staging RXON
 * @ch: requested channel as a pointer to struct ieee80211_channel
650
651

 * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
652
 * in the staging RXON flag structure based on the ch->band
653
 */
654
655
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
			 struct iwl_rxon_context *ctx)
656
{
657
	enum ieee80211_band band = ch->band;
658
	u16 channel = ch->hw_value;
659

660
	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
661
662
663
	    (priv->band == band))
		return 0;

664
	ctx->staging.channel = cpu_to_le16(channel);
665
	if (band == IEEE80211_BAND_5GHZ)
666
		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
667
	else
668
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
669
670
671

	priv->band = band;

672
	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
673
674
675
676

	return 0;
}

677
void iwl_set_flags_for_band(struct iwl_priv *priv,
678
			    struct iwl_rxon_context *ctx,
679
680
			    enum ieee80211_band band,
			    struct ieee80211_vif *vif)
681
682
{
	if (band == IEEE80211_BAND_5GHZ) {
683
		ctx->staging.flags &=
684
685
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
686
		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
687
688
	} else {
		/* Copied from iwl_post_associate() */
689
		if (vif && vif->bss_conf.use_short_slot)
690
			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
691
		else
692
			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
693

694
695
696
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
697
698
699
700
701
702
	}
}

/*
 * initialize rxon structure with default values from eeprom
 */
703
void iwl_connection_init_rx_config(struct iwl_priv *priv,
704
				   struct iwl_rxon_context *ctx)
705
706
707
{
	const struct iwl_channel_info *ch_info;

708
	memset(&ctx->staging, 0, sizeof(ctx->staging));
709

710
711
712
	if (!ctx->vif) {
		ctx->staging.dev_type = ctx->unused_devtype;
	} else switch (ctx->vif->type) {
713
	case NL80211_IFTYPE_AP:
714
		ctx->staging.dev_type = ctx->ap_devtype;
715
716
717
		break;

	case NL80211_IFTYPE_STATION:
718
		ctx->staging.dev_type = ctx->station_devtype;
719
		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
720
721
722
		break;

	case NL80211_IFTYPE_ADHOC:
723
		ctx->staging.dev_type = ctx->ibss_devtype;
724
725
		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
726
727
728
729
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	default:
730
731
		IWL_ERR(priv, "Unsupported interface type %d\n",
			ctx->vif->type);
732
733
734
735
736
737
738
		break;
	}

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

	ch_info = iwl_get_channel_info(priv, priv->band,
745
				       le16_to_cpu(ctx->active.channel));
746
747
748
749

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

750
	ctx->staging.channel = cpu_to_le16(ch_info->channel);
751
752
	priv->band = ch_info->band;

753
	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
754

755
	ctx->staging.ofdm_basic_rates =
756
	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
757
	ctx->staging.cck_basic_rates =
758
759
	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

760
	/* clear both MIX and PURE40 mode flag */
761
	ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
762
					RXON_FLG_CHANNEL_MODE_PURE_40);
763
764
	if (ctx->vif)
		memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
765

766
767
768
	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;
769
770
}

771
void iwl_set_rate(struct iwl_priv *priv)
772
773
774
{
	const struct ieee80211_supported_band *hw = NULL;
	struct ieee80211_rate *rate;
775
	struct iwl_rxon_context *ctx;
776
777
778
779
780
781
782
783
784
785
786
787
	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]);
788
		if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
789
790
791
			priv->active_rate |= (1 << rate->hw_value);
	}

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

794
795
796
	for_each_context(priv, ctx) {
		ctx->staging.cck_basic_rates =
		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
797

798
799
800
		ctx->staging.ofdm_basic_rates =
		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
	}
801
}
802
803
804

void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
805
806
807
808
809
810
	/*
	 * MULTI-FIXME
	 * See iwl_mac_channel_switch.
	 */
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];

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

814
	if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
815
		ieee80211_chswitch_done(ctx->vif, is_success);
816
}
817
818

#ifdef CONFIG_IWLWIFI_DEBUG
819
820
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
			     struct iwl_rxon_context *ctx)
821
{
822
	struct iwl_rxon_cmd *rxon = &ctx->staging;
823

824
	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
825
	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
826
827
828
	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",
829
			le32_to_cpu(rxon->filter_flags));
830
831
	IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
	IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
832
			rxon->ofdm_basic_rates);
833
834
835
836
	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));
837
}
838
#endif
839

840
841
842
843
844
static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
{
	unsigned long flags;
	struct iwl_notification_wait *wait_entry;

845
846
	spin_lock_irqsave(&priv->notif_wait_lock, flags);
	list_for_each_entry(wait_entry, &priv->notif_waits, list)
847
		wait_entry->aborted = true;
848
	spin_unlock_irqrestore(&priv->notif_wait_lock, flags);
849

850
	wake_up_all(&priv->notif_waitq);
851
852
}

853
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
854
{
855
856
857
	unsigned int reload_msec;
	unsigned long reload_jiffies;

858
859
860
861
862
863
	/* 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);

864
865
	iwlagn_abort_notification_waits(priv);

866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
	/* 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)) {
Don Fry's avatar
Don Fry committed
894
		if (iwlagn_mod_params.restart_fw) {
895
896
897
898
899
900
901
902
903
904
905
906
907
908
			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)
{
909
910
911
912
913
914
915
	/* 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))) {
		/*
916
917
		 * Keep the restart process from trying to send host
		 * commands by clearing the ready bit.
918
919
		 */
		clear_bit(STATUS_READY, &priv->status);
920
921
		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
		wake_up_interruptible(&priv->wait_command_queue);
922
923
924
925
		IWL_ERR(priv, "RF is used by WiMAX\n");
		return;
	}

926
927
928
	IWL_ERR(priv, "Loaded firmware version: %s\n",
		priv->hw->wiphy->fw_version);

929
930
931
932
	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);
933
#ifdef CONFIG_IWLWIFI_DEBUG
934
	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
935
936
		iwl_print_rx_config_cmd(priv,
					&priv->contexts[IWL_RXON_CTX_BSS]);
937
938
#endif

939
	iwlagn_fw_error(priv, false);
940
941
}

942
static int iwl_apm_stop_master(struct iwl_priv *priv)
943
{
944
	int ret = 0;
945

946
	/* stop device's busmaster DMA activity */
947
948
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);

949
	ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
950
			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
951
952
	if (ret)
		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
953
954
955

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

956
	return ret;
957
958
959
960
}

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

963
964
	clear_bit(STATUS_DEVICE_ENABLED, &priv->status);

965
	/* Stop device's DMA activity */
966
967
	iwl_apm_stop_master(priv);

968
	/* Reset the entire device */
969
970
971
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);

	udelay(10);
972
973
974
975
976

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

980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016

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

1017
	bus_apm_config(priv->bus);