iwl-core.c 51 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"
43
#include "iwl-agn.h"
Mohamed Abbas's avatar
Mohamed Abbas committed
44
#include "iwl-helpers.h"
45
#include "iwl-shared.h"
Don Fry's avatar
Don Fry committed
46
#include "iwl-agn.h"
47
#include "iwl-trans.h"
Tomas Winkler's avatar
Tomas Winkler committed
48

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 */
Wey-Yi Guy's avatar
Wey-Yi Guy committed
53
static void iwl_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
	u16 max_bit_rate = 0;
58
59
	u8 rx_chains_num = hw_params(priv).rx_chains_num;
	u8 tx_chains_num = hw_params(priv).tx_chains_num;
Ron Rindjunsky's avatar
Ron Rindjunsky committed
60

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 (hw_params(priv).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
}

/**
Wey-Yi Guy's avatar
Wey-Yi Guy committed
109
 * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
110
 */
Wey-Yi Guy's avatar
Wey-Yi Guy committed
111
int iwl_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
		set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
125
126
127
128
129
130
131
132
		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)
Wey-Yi Guy's avatar
Wey-Yi Guy committed
148
		iwl_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)
Wey-Yi Guy's avatar
Wey-Yi Guy committed
158
		iwl_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
	set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
225
226
227
228
229

	return 0;
}

/*
Wey-Yi Guy's avatar
Wey-Yi Guy committed
230
 * iwl_free_geos - undo allocations in iwl_init_geos
231
 */
Wey-Yi Guy's avatar
Wey-Yi Guy committed
232
void iwl_free_geos(struct iwl_priv *priv)
233
234
235
{
	kfree(priv->ieee_channels);
	kfree(priv->ieee_rates);
236
	clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
237
238
}

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
	lockdep_assert_held(&priv->shrd->mutex);
329

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
			IWL_MAX_UCODE_BEACON_INTERVAL * 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 iwl_trans_send_cmd_pdu(trans(priv), 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
	if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
812
813
		return;

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

#ifdef CONFIG_IWLWIFI_DEBUG
820
void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
821
{
822
	struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
823
	struct iwl_rxon_cmd *rxon = &ctx->staging;
824

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

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

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

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

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

859
	/* Set the FW error flag -- cleared on iwl_down */
860
	set_bit(STATUS_FW_ERROR, &priv->shrd->status);
861
862

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

865
866
	iwlagn_abort_notification_waits(priv);

867
868
	/* Keep the restart process from trying to send host
	 * commands by clearing the ready bit */
869
	clear_bit(STATUS_READY, &priv->shrd->status);
870

871
	wake_up_interruptible(&priv->shrd->wait_command_queue);
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

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

894
	if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
Don Fry's avatar
Don Fry committed
895
		if (iwlagn_mod_params.restart_fw) {
896
			IWL_DEBUG_FW_ERRORS(priv,
897
				  "Restarting adapter due to uCode error.\n");
898
			queue_work(priv->shrd->workqueue, &priv->restart);
899
		} else
900
			IWL_DEBUG_FW_ERRORS(priv,
901
902
903
904
				  "Detected FW error, but not restarting\n");
	}
}

905
static int iwl_apm_stop_master(struct iwl_priv *priv)
906
{
907
	int ret = 0;
908

909
	/* stop device's busmaster DMA activity */
910
	iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
911

912
913
	ret = iwl_poll_bit(bus(priv), CSR_RESET,
			CSR_RESET_REG_FLAG_MASTER_DISABLED,
914
			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
915
916
	if (ret)
		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
917
918
919

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

920
	return ret;
921
922
923
924
}

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

927
	clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status);
928

929
	/* Stop device's DMA activity */
930
931
	iwl_apm_stop_master(priv);

932
	/* Reset the entire device */
933
	iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
934
935

	udelay(10);
936
937
938
939
940

	/*
	 * Clear "initialization complete" bit to move adapter from
	 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
	 */
Emmanuel Grumbach's avatar