common.c 66.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
/******************************************************************************
 *
 * GPL LICENSE SUMMARY
 *
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 *
 * 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:
 *  Intel Linux Wireless <ilw@linux.intel.com>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <net/mac80211.h>

#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-debug.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-power.h"
#include "iwl-sta.h"
#include "iwl-helpers.h"


MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965");
MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");

/*
 * 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)
 */
67
static bool bt_coex_active = true;
68 69 70
module_param(bt_coex_active, bool, S_IRUGO);
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");

71 72
u32 il_debug_level;
EXPORT_SYMBOL(il_debug_level);
73

74 75
const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(il_bcast_addr);
76 77


S
Stanislaw Gruszka 已提交
78
/* This function both allocates and initializes hw and il. */
S
Stanislaw Gruszka 已提交
79
struct ieee80211_hw *il_alloc_all(struct il_cfg *cfg)
80
{
S
Stanislaw Gruszka 已提交
81
	struct il_priv *il;
82
	/* mac80211 allocates memory for this device instance, including
S
Stanislaw Gruszka 已提交
83
	 *   space for this driver's ilate structure */
84 85
	struct ieee80211_hw *hw;

S
Stanislaw Gruszka 已提交
86
	hw = ieee80211_alloc_hw(sizeof(struct il_priv),
87 88 89 90 91 92 93
				cfg->ops->ieee80211_ops);
	if (hw == NULL) {
		pr_err("%s: Can not allocate network device\n",
		       cfg->name);
		goto out;
	}

S
Stanislaw Gruszka 已提交
94 95
	il = hw->priv;
	il->hw = hw;
96 97 98 99

out:
	return hw;
}
S
Stanislaw Gruszka 已提交
100
EXPORT_SYMBOL(il_alloc_all);
101 102 103

#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
S
Stanislaw Gruszka 已提交
104
static void il_init_ht_hw_capab(const struct il_priv *il,
105 106 107 108
			      struct ieee80211_sta_ht_cap *ht_info,
			      enum ieee80211_band band)
{
	u16 max_bit_rate = 0;
S
Stanislaw Gruszka 已提交
109 110
	u8 rx_chains_num = il->hw_params.rx_chains_num;
	u8 tx_chains_num = il->hw_params.tx_chains_num;
111 112 113 114 115 116 117 118

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

	ht_info->ht_supported = true;

	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
	max_bit_rate = MAX_BIT_RATE_20_MHZ;
S
Stanislaw Gruszka 已提交
119
	if (il->hw_params.ht40_channel & BIT(band)) {
120 121 122 123 124 125
		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;
		max_bit_rate = MAX_BIT_RATE_40_MHZ;
	}

S
Stanislaw Gruszka 已提交
126
	if (il->cfg->mod_params->amsdu_size_8K)
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;

	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;

	ht_info->mcs.rx_mask[0] = 0xFF;
	if (rx_chains_num >= 2)
		ht_info->mcs.rx_mask[1] = 0xFF;
	if (rx_chains_num >= 3)
		ht_info->mcs.rx_mask[2] = 0xFF;

	/* Highest supported Rx data rate */
	max_bit_rate *= rx_chains_num;
	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);

	/* Tx MCS capabilities */
	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
	if (tx_chains_num != rx_chains_num) {
		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);
	}
}

/**
S
Stanislaw Gruszka 已提交
153
 * il_init_geos - Initialize mac80211's geo/channel info based from eeprom
154
 */
S
Stanislaw Gruszka 已提交
155
int il_init_geos(struct il_priv *il)
156
{
S
Stanislaw Gruszka 已提交
157
	struct il_channel_info *ch;
158 159 160 161 162
	struct ieee80211_supported_band *sband;
	struct ieee80211_channel *channels;
	struct ieee80211_channel *geo_ch;
	struct ieee80211_rate *rates;
	int i = 0;
163
	s8 max_tx_power = 0;
164

S
Stanislaw Gruszka 已提交
165 166
	if (il->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
	    il->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
167
		D_INFO("Geography modes already initialized.\n");
S
Stanislaw Gruszka 已提交
168
		set_bit(S_GEO_CONFIGURED, &il->status);
169 170 171 172
		return 0;
	}

	channels = kzalloc(sizeof(struct ieee80211_channel) *
S
Stanislaw Gruszka 已提交
173
			   il->channel_count, GFP_KERNEL);
174 175 176
	if (!channels)
		return -ENOMEM;

S
Stanislaw Gruszka 已提交
177
	rates = kzalloc((sizeof(struct ieee80211_rate) * RATE_COUNT_LEGACY),
178 179 180 181 182 183 184
			GFP_KERNEL);
	if (!rates) {
		kfree(channels);
		return -ENOMEM;
	}

	/* 5.2GHz channels start after the 2.4GHz channels */
S
Stanislaw Gruszka 已提交
185
	sband = &il->bands[IEEE80211_BAND_5GHZ];
186
	sband->channels = &channels[ARRAY_SIZE(il_eeprom_band_1)];
187
	/* just OFDM */
S
Stanislaw Gruszka 已提交
188
	sband->bitrates = &rates[IL_FIRST_OFDM_RATE];
S
Stanislaw Gruszka 已提交
189
	sband->n_bitrates = RATE_COUNT_LEGACY - IL_FIRST_OFDM_RATE;
190

S
Stanislaw Gruszka 已提交
191 192
	if (il->cfg->sku & IL_SKU_N)
		il_init_ht_hw_capab(il, &sband->ht_cap,
193 194
					 IEEE80211_BAND_5GHZ);

S
Stanislaw Gruszka 已提交
195
	sband = &il->bands[IEEE80211_BAND_2GHZ];
196 197 198
	sband->channels = channels;
	/* OFDM & CCK */
	sband->bitrates = rates;
S
Stanislaw Gruszka 已提交
199
	sband->n_bitrates = RATE_COUNT_LEGACY;
200

S
Stanislaw Gruszka 已提交
201 202
	if (il->cfg->sku & IL_SKU_N)
		il_init_ht_hw_capab(il, &sband->ht_cap,
203 204
					 IEEE80211_BAND_2GHZ);

S
Stanislaw Gruszka 已提交
205 206
	il->ieee_channels = channels;
	il->ieee_rates = rates;
207

S
Stanislaw Gruszka 已提交
208 209
	for (i = 0;  i < il->channel_count; i++) {
		ch = &il->channel_info[i];
210

S
Stanislaw Gruszka 已提交
211
		if (!il_is_channel_valid(ch))
212 213
			continue;

S
Stanislaw Gruszka 已提交
214
		sband = &il->bands[ch->band];
215 216 217 218 219 220 221 222 223

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

		geo_ch->center_freq =
			ieee80211_channel_to_frequency(ch->channel, ch->band);
		geo_ch->max_power = ch->max_power_avg;
		geo_ch->max_antenna_gain = 0xff;
		geo_ch->hw_value = ch->channel;

S
Stanislaw Gruszka 已提交
224
		if (il_is_channel_valid(ch)) {
225 226 227 228 229 230 231 232 233 234 235
			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;

			geo_ch->flags |= ch->ht40_extension_channel;

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

242
		D_INFO("Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
243
				ch->channel, geo_ch->center_freq,
S
Stanislaw Gruszka 已提交
244
				il_is_channel_a_band(ch) ?  "5.2" : "2.4",
245 246 247 248 249
				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
				"restricted" : "valid",
				 geo_ch->flags);
	}

S
Stanislaw Gruszka 已提交
250 251 252
	il->tx_power_device_lmt = max_tx_power;
	il->tx_power_user_lmt = max_tx_power;
	il->tx_power_next = max_tx_power;
253

254 255
	if (il->bands[IEEE80211_BAND_5GHZ].n_channels == 0 &&
	    (il->cfg->sku & IL_SKU_A)) {
256
		IL_INFO("Incorrectly detected BG card as ABG. "
257
			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
S
Stanislaw Gruszka 已提交
258 259 260
			   il->pci_dev->device,
			   il->pci_dev->subsystem_device);
		il->cfg->sku &= ~IL_SKU_A;
261 262
	}

263
	IL_INFO("Tunable channels: %d 802.11bg, %d 802.11a channels\n",
S
Stanislaw Gruszka 已提交
264 265
		   il->bands[IEEE80211_BAND_2GHZ].n_channels,
		   il->bands[IEEE80211_BAND_5GHZ].n_channels);
266

S
Stanislaw Gruszka 已提交
267
	set_bit(S_GEO_CONFIGURED, &il->status);
268 269 270

	return 0;
}
S
Stanislaw Gruszka 已提交
271
EXPORT_SYMBOL(il_init_geos);
272 273

/*
S
Stanislaw Gruszka 已提交
274
 * il_free_geos - undo allocations in il_init_geos
275
 */
S
Stanislaw Gruszka 已提交
276
void il_free_geos(struct il_priv *il)
277
{
S
Stanislaw Gruszka 已提交
278 279
	kfree(il->ieee_channels);
	kfree(il->ieee_rates);
S
Stanislaw Gruszka 已提交
280
	clear_bit(S_GEO_CONFIGURED, &il->status);
281
}
S
Stanislaw Gruszka 已提交
282
EXPORT_SYMBOL(il_free_geos);
283

S
Stanislaw Gruszka 已提交
284
static bool il_is_channel_extension(struct il_priv *il,
285 286 287
				     enum ieee80211_band band,
				     u16 channel, u8 extension_chan_offset)
{
S
Stanislaw Gruszka 已提交
288
	const struct il_channel_info *ch_info;
289

S
Stanislaw Gruszka 已提交
290
	ch_info = il_get_channel_info(il, band, channel);
S
Stanislaw Gruszka 已提交
291
	if (!il_is_channel_valid(ch_info))
292 293 294 295 296 297 298 299 300 301 302 303
		return false;

	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
		return !(ch_info->ht40_extension_channel &
					IEEE80211_CHAN_NO_HT40PLUS);
	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
		return !(ch_info->ht40_extension_channel &
					IEEE80211_CHAN_NO_HT40MINUS);

	return false;
}

S
Stanislaw Gruszka 已提交
304
bool il_is_ht40_tx_allowed(struct il_priv *il,
S
Stanislaw Gruszka 已提交
305
			    struct il_rxon_context *ctx,
306 307 308 309 310 311 312 313 314 315 316 317
			    struct ieee80211_sta_ht_cap *ht_cap)
{
	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
		return false;

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

318
#ifdef CONFIG_IWLEGACY_DEBUGFS
S
Stanislaw Gruszka 已提交
319
	if (il->disable_ht40)
320 321 322
		return false;
#endif

S
Stanislaw Gruszka 已提交
323
	return il_is_channel_extension(il, il->band,
324 325 326
			le16_to_cpu(ctx->staging.channel),
			ctx->ht.extension_chan_offset);
}
S
Stanislaw Gruszka 已提交
327
EXPORT_SYMBOL(il_is_ht40_tx_allowed);
328

S
Stanislaw Gruszka 已提交
329
static u16 il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
{
	u16 new_val;
	u16 beacon_factor;

	/*
	 * If mac80211 hasn't given us a beacon interval, program
	 * the default into the device.
	 */
	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.
	 */

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

int
S
Stanislaw Gruszka 已提交
363
il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx)
364 365 366 367 368 369 370
{
	u64 tsf;
	s32 interval_tm, rem;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int;
	struct ieee80211_vif *vif = ctx->vif;

S
Stanislaw Gruszka 已提交
371
	conf = il_ieee80211_get_hw_conf(il->hw);
372

S
Stanislaw Gruszka 已提交
373
	lockdep_assert_held(&il->mutex);
374

S
Stanislaw Gruszka 已提交
375
	memset(&ctx->timing, 0, sizeof(struct il_rxon_time_cmd));
376

S
Stanislaw Gruszka 已提交
377
	ctx->timing.timestamp = cpu_to_le64(il->timestamp);
378 379 380 381 382
	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);

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

	/*
S
Stanislaw Gruszka 已提交
383
	 * TODO: For IBSS we need to get atim_win from mac80211,
384 385
	 *	 for now just always use 0
	 */
S
Stanislaw Gruszka 已提交
386
	ctx->timing.atim_win = 0;
387

S
Stanislaw Gruszka 已提交
388
	beacon_int = il_adjust_beacon_interval(beacon_int,
S
Stanislaw Gruszka 已提交
389
			il->hw_params.max_beacon_itrvl * TIME_UNIT);
390 391
	ctx->timing.beacon_interval = cpu_to_le16(beacon_int);

S
Stanislaw Gruszka 已提交
392
	tsf = il->timestamp; /* tsf is modifed by do_div: copy it */
393 394 395 396 397 398
	interval_tm = beacon_int * TIME_UNIT;
	rem = do_div(tsf, interval_tm);
	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);

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

399
	D_ASSOC(
400 401 402
			"beacon interval %d beacon timer %d beacon tim %d\n",
			le16_to_cpu(ctx->timing.beacon_interval),
			le32_to_cpu(ctx->timing.beacon_init_val),
S
Stanislaw Gruszka 已提交
403
			le16_to_cpu(ctx->timing.atim_win));
404

S
Stanislaw Gruszka 已提交
405
	return il_send_cmd_pdu(il, ctx->rxon_timing_cmd,
406 407
				sizeof(ctx->timing), &ctx->timing);
}
S
Stanislaw Gruszka 已提交
408
EXPORT_SYMBOL(il_send_rxon_timing);
409 410

void
S
Stanislaw Gruszka 已提交
411
il_set_rxon_hwcrypto(struct il_priv *il,
S
Stanislaw Gruszka 已提交
412
				struct il_rxon_context *ctx,
413 414
				int hw_decrypt)
{
S
Stanislaw Gruszka 已提交
415
	struct il_rxon_cmd *rxon = &ctx->staging;
416 417 418 419 420 421 422

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

}
S
Stanislaw Gruszka 已提交
423
EXPORT_SYMBOL(il_set_rxon_hwcrypto);
424 425 426

/* validate RXON structure is valid */
int
S
Stanislaw Gruszka 已提交
427
il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx)
428
{
S
Stanislaw Gruszka 已提交
429
	struct il_rxon_cmd *rxon = &ctx->staging;
430 431 432 433
	bool error = false;

	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
434
			IL_WARN("check 2.4G: wrong narrow\n");
435 436 437
			error = true;
		}
		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
438
			IL_WARN("check 2.4G: wrong radar\n");
439 440 441 442
			error = true;
		}
	} else {
		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
443
			IL_WARN("check 5.2G: not short slot!\n");
444 445 446
			error = true;
		}
		if (rxon->flags & RXON_FLG_CCK_MSK) {
447
			IL_WARN("check 5.2G: CCK!\n");
448 449 450 451
			error = true;
		}
	}
	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
452
		IL_WARN("mac/bssid mcast!\n");
453 454 455 456
		error = true;
	}

	/* make sure basic rates 6Mbps and 1Mbps are supported */
S
Stanislaw Gruszka 已提交
457 458
	if ((rxon->ofdm_basic_rates & RATE_6M_MASK) == 0 &&
	    (rxon->cck_basic_rates & RATE_1M_MASK) == 0) {
459
		IL_WARN("neither 1 nor 6 are basic\n");
460 461 462 463
		error = true;
	}

	if (le16_to_cpu(rxon->assoc_id) > 2007) {
464
		IL_WARN("aid > 2007\n");
465 466 467 468 469
		error = true;
	}

	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
470
		IL_WARN("CCK and short slot\n");
471 472 473 474 475
		error = true;
	}

	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
476
		IL_WARN("CCK and auto detect");
477 478 479 480 481 482
		error = true;
	}

	if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
			    RXON_FLG_TGG_PROTECT_MSK)) ==
			    RXON_FLG_TGG_PROTECT_MSK) {
483
		IL_WARN("TGg but no auto-detect\n");
484 485 486 487
		error = true;
	}

	if (error)
488
		IL_WARN("Tuning to channel %d\n",
489 490 491
			    le16_to_cpu(rxon->channel));

	if (error) {
492
		IL_ERR("Invalid RXON\n");
493 494 495 496
		return -EINVAL;
	}
	return 0;
}
S
Stanislaw Gruszka 已提交
497
EXPORT_SYMBOL(il_check_rxon_cmd);
498 499

/**
S
Stanislaw Gruszka 已提交
500
 * il_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
S
Stanislaw Gruszka 已提交
501
 * @il: staging_rxon is compared to active_rxon
502 503 504 505 506
 *
 * 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.
 */
S
Stanislaw Gruszka 已提交
507
int il_full_rxon_required(struct il_priv *il,
S
Stanislaw Gruszka 已提交
508
			   struct il_rxon_context *ctx)
509
{
S
Stanislaw Gruszka 已提交
510 511
	const struct il_rxon_cmd *staging = &ctx->staging;
	const struct il_rxon_cmd *active = &ctx->active;
512 513 514

#define CHK(cond)							\
	if ((cond)) {							\
515
		D_INFO("need full RXON - " #cond "\n");	\
516 517 518 519 520
		return 1;						\
	}

#define CHK_NEQ(c1, c2)						\
	if ((c1) != (c2)) {					\
521
		D_INFO("need full RXON - "	\
522 523 524 525 526 527
			       #c1 " != " #c2 " - %d != %d\n",	\
			       (c1), (c2));			\
		return 1;					\
	}

	/* These items are only settable from the full RXON command */
S
Stanislaw Gruszka 已提交
528
	CHK(!il_is_associated_ctx(ctx));
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
	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->assoc_id, active->assoc_id);

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

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

#undef CHK
#undef CHK_NEQ

	return 0;
}
S
Stanislaw Gruszka 已提交
559
EXPORT_SYMBOL(il_full_rxon_required);
560

S
Stanislaw Gruszka 已提交
561
u8 il_get_lowest_plcp(struct il_priv *il,
S
Stanislaw Gruszka 已提交
562
			    struct il_rxon_context *ctx)
563 564 565 566 567 568
{
	/*
	 * Assign the lowest rate -- should really get this from
	 * the beacon skb from mac80211.
	 */
	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
S
Stanislaw Gruszka 已提交
569
		return RATE_1M_PLCP;
570
	else
S
Stanislaw Gruszka 已提交
571
		return RATE_6M_PLCP;
572
}
S
Stanislaw Gruszka 已提交
573
EXPORT_SYMBOL(il_get_lowest_plcp);
574

S
Stanislaw Gruszka 已提交
575
static void _il_set_rxon_ht(struct il_priv *il,
S
Stanislaw Gruszka 已提交
576 577
			     struct il_ht_config *ht_conf,
			     struct il_rxon_context *ctx)
578
{
S
Stanislaw Gruszka 已提交
579
	struct il_rxon_cmd *rxon = &ctx->staging;
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

	if (!ctx->ht.enabled) {
		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
			RXON_FLG_HT40_PROT_MSK |
			RXON_FLG_HT_PROT_MSK);
		return;
	}

	rxon->flags |= cpu_to_le32(ctx->ht.protection <<
					RXON_FLG_HT_OPERATING_MODE_POS);

	/* Set up channel bandwidth:
	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
	/* clear the HT channel mode before set the mode */
	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
S
Stanislaw Gruszka 已提交
597
	if (il_is_ht40_tx_allowed(il, ctx, NULL)) {
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
		/* pure ht40 */
		if (ctx->ht.protection ==
				IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
			/* Note: control channel is opposite of extension channel */
			switch (ctx->ht.extension_chan_offset) {
			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 {
			/* Note: control channel is opposite of extension channel */
			switch (ctx->ht.extension_chan_offset) {
			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 */
629
				IL_ERR(
630 631 632 633 634 635 636 637
					"invalid extension channel offset\n");
				break;
			}
		}
	} else {
		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
	}

S
Stanislaw Gruszka 已提交
638 639
	if (il->cfg->ops->hcmd->set_rxon_chain)
		il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
640

641
	D_ASSOC("rxon flags 0x%X operation mode :0x%X "
642 643 644 645 646
			"extension channel offset 0x%x\n",
			le32_to_cpu(rxon->flags), ctx->ht.protection,
			ctx->ht.extension_chan_offset);
}

S
Stanislaw Gruszka 已提交
647
void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf)
648
{
649
	_il_set_rxon_ht(il, ht_conf, &il->ctx);
650
}
S
Stanislaw Gruszka 已提交
651
EXPORT_SYMBOL(il_set_rxon_ht);
652 653

/* Return valid, unused, channel for a passive scan to reset the RF */
S
Stanislaw Gruszka 已提交
654
u8 il_get_single_channel_number(struct il_priv *il,
655 656
				 enum ieee80211_band band)
{
S
Stanislaw Gruszka 已提交
657
	const struct il_channel_info *ch_info;
658 659 660 661 662 663
	int i;
	u8 channel = 0;
	u8 min, max;

	if (band == IEEE80211_BAND_5GHZ) {
		min = 14;
S
Stanislaw Gruszka 已提交
664
		max = il->channel_count;
665 666 667 668 669 670
	} else {
		min = 0;
		max = 14;
	}

	for (i = min; i < max; i++) {
671 672
		channel = il->channel_info[i].channel;
		if (channel == le16_to_cpu(il->ctx.staging.channel))
673 674
			continue;

S
Stanislaw Gruszka 已提交
675
		ch_info = il_get_channel_info(il, band, channel);
S
Stanislaw Gruszka 已提交
676
		if (il_is_channel_valid(ch_info))
677 678 679 680 681
			break;
	}

	return channel;
}
S
Stanislaw Gruszka 已提交
682
EXPORT_SYMBOL(il_get_single_channel_number);
683 684

/**
S
Stanislaw Gruszka 已提交
685
 * il_set_rxon_channel - Set the band and channel values in staging RXON
686 687 688 689 690 691
 * @ch: requested channel as a pointer to struct ieee80211_channel

 * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
 * in the staging RXON flag structure based on the ch->band
 */
int
S
Stanislaw Gruszka 已提交
692
il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch,
S
Stanislaw Gruszka 已提交
693
			 struct il_rxon_context *ctx)
694 695 696 697
{
	enum ieee80211_band band = ch->band;
	u16 channel = ch->hw_value;

698
	if (le16_to_cpu(ctx->staging.channel) == channel && il->band == band)
699 700 701 702 703 704 705 706
		return 0;

	ctx->staging.channel = cpu_to_le16(channel);
	if (band == IEEE80211_BAND_5GHZ)
		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
	else
		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;

S
Stanislaw Gruszka 已提交
707
	il->band = band;
708

709
	D_INFO("Staging channel set to %d [%d]\n", channel, band);
710 711 712

	return 0;
}
S
Stanislaw Gruszka 已提交
713
EXPORT_SYMBOL(il_set_rxon_channel);
714

S
Stanislaw Gruszka 已提交
715
void il_set_flags_for_band(struct il_priv *il,
S
Stanislaw Gruszka 已提交
716
			    struct il_rxon_context *ctx,
717 718 719 720 721 722 723 724 725
			    enum ieee80211_band band,
			    struct ieee80211_vif *vif)
{
	if (band == IEEE80211_BAND_5GHZ) {
		ctx->staging.flags &=
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
	} else {
S
Stanislaw Gruszka 已提交
726
		/* Copied from il_post_associate() */
727 728 729 730 731 732 733 734 735 736
		if (vif && vif->bss_conf.use_short_slot)
			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
		else
			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
	}
}
S
Stanislaw Gruszka 已提交
737
EXPORT_SYMBOL(il_set_flags_for_band);
738 739 740 741

/*
 * initialize rxon structure with default values from eeprom
 */
S
Stanislaw Gruszka 已提交
742
void il_connection_init_rx_config(struct il_priv *il,
S
Stanislaw Gruszka 已提交
743
				   struct il_rxon_context *ctx)
744
{
S
Stanislaw Gruszka 已提交
745
	const struct il_channel_info *ch_info;
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766

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

	if (!ctx->vif) {
		ctx->staging.dev_type = ctx->unused_devtype;
	} else
	switch (ctx->vif->type) {

	case NL80211_IFTYPE_STATION:
		ctx->staging.dev_type = ctx->station_devtype;
		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	case NL80211_IFTYPE_ADHOC:
		ctx->staging.dev_type = ctx->ibss_devtype;
		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	default:
767
		IL_ERR("Unsupported interface type %d\n",
768 769 770 771 772 773 774
			ctx->vif->type);
		break;
	}

#if 0
	/* TODO:  Figure out when short_preamble would be set and cache from
	 * that */
S
Stanislaw Gruszka 已提交
775
	if (!hw_to_local(il->hw)->short_preamble)
776 777 778 779 780
		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
	else
		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif

S
Stanislaw Gruszka 已提交
781
	ch_info = il_get_channel_info(il, il->band,
782 783 784
				       le16_to_cpu(ctx->active.channel));

	if (!ch_info)
S
Stanislaw Gruszka 已提交
785
		ch_info = &il->channel_info[0];
786 787

	ctx->staging.channel = cpu_to_le16(ch_info->channel);
S
Stanislaw Gruszka 已提交
788
	il->band = ch_info->band;
789

S
Stanislaw Gruszka 已提交
790
	il_set_flags_for_band(il, ctx, il->band, ctx->vif);
791 792

	ctx->staging.ofdm_basic_rates =
S
Stanislaw Gruszka 已提交
793
	    (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
794
	ctx->staging.cck_basic_rates =
S
Stanislaw Gruszka 已提交
795
	    (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF;
796 797 798 799 800 801 802 803 804 805

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

	ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
}
S
Stanislaw Gruszka 已提交
806
EXPORT_SYMBOL(il_connection_init_rx_config);
807

S
Stanislaw Gruszka 已提交
808
void il_set_rate(struct il_priv *il)
809 810 811 812 813
{
	const struct ieee80211_supported_band *hw = NULL;
	struct ieee80211_rate *rate;
	int i;

S
Stanislaw Gruszka 已提交
814
	hw = il_get_hw_mode(il, il->band);
815
	if (!hw) {
816
		IL_ERR("Failed to set rate: unable to get hw mode\n");
817 818 819
		return;
	}

S
Stanislaw Gruszka 已提交
820
	il->active_rate = 0;
821 822 823

	for (i = 0; i < hw->n_bitrates; i++) {
		rate = &(hw->bitrates[i]);
S
Stanislaw Gruszka 已提交
824
		if (rate->hw_value < RATE_COUNT_LEGACY)
S
Stanislaw Gruszka 已提交
825
			il->active_rate |= (1 << rate->hw_value);
826 827
	}

828
	D_RATE("Set active_rate = %0x\n", il->active_rate);
829

830
	il->ctx.staging.cck_basic_rates =
S
Stanislaw Gruszka 已提交
831
		    (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF;
832

833
	il->ctx.staging.ofdm_basic_rates =
S
Stanislaw Gruszka 已提交
834
		   (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
835
}
S
Stanislaw Gruszka 已提交
836
EXPORT_SYMBOL(il_set_rate);
837

S
Stanislaw Gruszka 已提交
838
void il_chswitch_done(struct il_priv *il, bool is_success)
839
{
840
	struct il_rxon_context *ctx = &il->ctx;
841

S
Stanislaw Gruszka 已提交
842
	if (test_bit(S_EXIT_PENDING, &il->status))
843 844
		return;

S
Stanislaw Gruszka 已提交
845
	if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
846 847
		ieee80211_chswitch_done(ctx->vif, is_success);
}
S
Stanislaw Gruszka 已提交
848
EXPORT_SYMBOL(il_chswitch_done);
849

850
void il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb)
851
{
852
	struct il_rx_pkt *pkt = rxb_addr(rxb);
S
Stanislaw Gruszka 已提交
853
	struct il_csa_notification *csa = &(pkt->u.csa_notif);
854

855
	struct il_rxon_context *ctx = &il->ctx;
S
Stanislaw Gruszka 已提交
856
	struct il_rxon_cmd *rxon = (void *)&ctx->active;
857

S
Stanislaw Gruszka 已提交
858
	if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
859 860
		return;

S
Stanislaw Gruszka 已提交
861
	if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) {
862 863
		rxon->channel = csa->channel;
		ctx->staging.channel = csa->channel;
864
		D_11H("CSA notif: channel %d\n",
865
			      le16_to_cpu(csa->channel));
S
Stanislaw Gruszka 已提交
866
		il_chswitch_done(il, true);
867
	} else {
868
		IL_ERR("CSA notif (fail) : channel %d\n",
869
			le16_to_cpu(csa->channel));
S
Stanislaw Gruszka 已提交
870
		il_chswitch_done(il, false);
871 872
	}
}
873
EXPORT_SYMBOL(il_hdl_csa);
874

875
#ifdef CONFIG_IWLEGACY_DEBUG
S
Stanislaw Gruszka 已提交
876
void il_print_rx_config_cmd(struct il_priv *il,
S
Stanislaw Gruszka 已提交
877
			     struct il_rxon_context *ctx)
878
{
S
Stanislaw Gruszka 已提交
879
	struct il_rxon_cmd *rxon = &ctx->staging;
880

881
	D_RADIO("RX CONFIG:\n");
S
Stanislaw Gruszka 已提交
882
	il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
883
	D_RADIO("u16 channel: 0x%x\n",
884
				le16_to_cpu(rxon->channel));
885 886
	D_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
	D_RADIO("u32 filter_flags: 0x%08x\n",
887
				le32_to_cpu(rxon->filter_flags));
888 889
	D_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
	D_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
890
			rxon->ofdm_basic_rates);
891
	D_RADIO("u8 cck_basic_rates: 0x%02x\n",
892
				rxon->cck_basic_rates);
893 894 895
	D_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
	D_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
	D_RADIO("u16 assoc_id: 0x%x\n",
896 897
				le16_to_cpu(rxon->assoc_id));
}
S
Stanislaw Gruszka 已提交
898
EXPORT_SYMBOL(il_print_rx_config_cmd);
899 900
#endif
/**
S
Stanislaw Gruszka 已提交
901
 * il_irq_handle_error - called for HW or SW error interrupt from card
902
 */
S
Stanislaw Gruszka 已提交
903
void il_irq_handle_error(struct il_priv *il)
904
{
S
Stanislaw Gruszka 已提交
905
	/* Set the FW error flag -- cleared on il_down */
S
Stanislaw Gruszka 已提交
906
	set_bit(S_FW_ERROR, &il->status);
907 908

	/* Cancel currently queued command. */
S
Stanislaw Gruszka 已提交
909
	clear_bit(S_HCMD_ACTIVE, &il->status);
910

911
	IL_ERR("Loaded firmware version: %s\n",
S
Stanislaw Gruszka 已提交
912
		il->hw->wiphy->fw_version);
913

S
Stanislaw Gruszka 已提交
914 915 916
	il->cfg->ops->lib->dump_nic_error_log(il);
	if (il->cfg->ops->lib->dump_fh)
		il->cfg->ops->lib->dump_fh(il, NULL, false);
917
#ifdef CONFIG_IWLEGACY_DEBUG
S
Stanislaw Gruszka 已提交
918 919
	if (il_get_debug_level(il) & IL_DL_FW_ERRORS)
		il_print_rx_config_cmd(il,
920
					&il->ctx);
921 922
#endif

S
Stanislaw Gruszka 已提交
923
	wake_up(&il->wait_command_queue);
924 925 926

	/* Keep the restart process from trying to send host
	 * commands by clearing the INIT status bit */
S
Stanislaw Gruszka 已提交
927
	clear_bit(S_READY, &il->status);
928

S
Stanislaw Gruszka 已提交
929
	if (!test_bit(S_EXIT_PENDING, &il->status)) {
930
		IL_DBG(IL_DL_FW_ERRORS,
931 932
			  "Restarting adapter due to uCode error.\n");

S
Stanislaw Gruszka 已提交
933 934
		if (il->cfg->mod_params->restart_fw)
			queue_work(il->workqueue, &il->restart);
935 936
	}
}
S
Stanislaw Gruszka 已提交
937
EXPORT_SYMBOL(il_irq_handle_error);
938

S
Stanislaw Gruszka 已提交
939
static int il_apm_stop_master(struct il_priv *il)
940 941 942 943
{
	int ret = 0;

	/* stop device's busmaster DMA activity */
S
Stanislaw Gruszka 已提交
944
	il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
945

946
	ret = _il_poll_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
947 948
			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
	if (ret)
949
		IL_WARN("Master Disable Timed Out, 100 usec\n");
950

951
	D_INFO("stop master\n");
952 953 954 955

	return ret;
}

S
Stanislaw Gruszka 已提交
956
void il_apm_stop(struct il_priv *il)
957
{
958
	D_INFO("Stop card, put in low power state\n");
959 960

	/* Stop device's DMA activity */
S
Stanislaw Gruszka 已提交
961
	il_apm_stop_master(il);
962 963

	/* Reset the entire device */
S
Stanislaw Gruszka 已提交
964
	il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
965 966 967 968 969 970 971

	udelay(10);

	/*
	 * Clear "initialization complete" bit to move adapter from
	 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
	 */
S
Stanislaw Gruszka 已提交
972
	il_clear_bit(il, CSR_GP_CNTRL,
973 974
				CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
}
S
Stanislaw Gruszka 已提交
975
EXPORT_SYMBOL(il_apm_stop);
976 977 978 979


/*
 * Start up NIC's basic functionality after it has been reset
S
Stanislaw Gruszka 已提交
980
 * (e.g. after platform boot, or shutdown via il_apm_stop())
981 982
 * NOTE:  This does not load uCode nor start the embedded processor
 */
S
Stanislaw Gruszka 已提交
983
int il_apm_init(struct il_priv *il)
984 985 986 987
{
	int ret = 0;
	u16 lctl;

988
	D_INFO("Init card's basic functions\n");
989 990 991 992 993 994 995

	/*
	 * 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) */
S
Stanislaw Gruszka 已提交
996
	il_set_bit(il, CSR_GIO_CHICKEN_BITS,
997 998 999 1000 1001 1002
			  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)
	 */
S
Stanislaw Gruszka 已提交
1003
	il_set_bit(il, CSR_GIO_CHICKEN_BITS,
1004 1005 1006
			  CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);

	/* Set FH wait threshold to maximum (HW error during stress W/A) */
S
Stanislaw Gruszka 已提交
1007
	il_set_bit(il, CSR_DBG_HPET_MEM_REG,
1008 1009 1010 1011 1012
					CSR_DBG_HPET_MEM_REG_VAL);

	/*
	 * Enable HAP INTA (interrupt from management bus) to
	 * wake device's PCI Express link L1a -> L0s
L
Lucas De Marchi 已提交
1013
	 * NOTE:  This is no-op for 3945 (non-existent bit)
1014
	 */
S
Stanislaw Gruszka 已提交
1015
	il_set_bit(il, CSR_HW_IF_CONFIG_REG,
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);

	/*
	 * 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.
	 */
S
Stanislaw Gruszka 已提交
1026 1027
	if (il->cfg->base_params->set_l0s) {
		lctl = il_pcie_link_ctl(il);
1028 1029 1030
		if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
					PCI_CFG_LINK_CTRL_VAL_L1_EN) {
			/* L1-ASPM enabled; disable(!) L0S  */
S
Stanislaw Gruszka 已提交
1031
			il_set_bit(il, CSR_GIO_REG,
1032
					CSR_GIO_REG_VAL_L0S_ENABLED);
1033
			D_POWER("L1 Enabled; Disabling L0S\n");
1034 1035
		} else {
			/* L1-ASPM disabled; enable(!) L0S */
S
Stanislaw Gruszka 已提交
1036
			il_clear_bit(il, CSR_GIO_REG,
1037
					CSR_GIO_REG_VAL_L0S_ENABLED);
1038
			D_POWER("L1 Disabled; Enabling L0S\n");
1039 1040 1041 1042
		}
	}

	/* Configure analog phase-lock-loop before activating to D0A */
S
Stanislaw Gruszka 已提交
1043 1044 1045
	if (il->cfg->base_params->pll_cfg_val)
		il_set_bit(il, CSR_ANA_PLL_CFG,
			    il->cfg->base_params->pll_cfg_val);
1046 1047 1048 1049 1050

	/*
	 * Set "initialization complete" bit to move adapter from
	 * D0U* --> D0A* (powered-up active) state.
	 */
S
Stanislaw Gruszka 已提交
1051
	il_set_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
1052 1053 1054

	/*
	 * Wait for clock stabilization; once stabilized, access to
1055
	 * device-internal resources is supported, e.g. il_wr_prph()
1056 1057
	 * and accesses to uCode SRAM.
	 */
1058
	ret = _il_poll_bit(il, CSR_GP_CNTRL,
1059 1060 1061
			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
	if (ret < 0) {
1062
		D_INFO("Failed to init the card\n");
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
		goto out;
	}

	/*
	 * Enable DMA and BSM (if used) clocks, wait for them to stabilize.
	 * BSM (Boostrap State Machine) is only in 3945 and 4965.
	 *
	 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
	 * do not disable clocks.  This preserves any hardware bits already
	 * set by default in "CLK_CTRL_REG" after reset.
	 */
S
Stanislaw Gruszka 已提交
1074
	if (il->cfg->base_params->use_bsm)
1075
		il_wr_prph(il, APMG_CLK_EN_REG,
1076 1077
			APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
	else
1078
		il_wr_prph(il, APMG_CLK_EN_REG,
1079 1080 1081 1082
			APMG_CLK_VAL_DMA_CLK_RQT);
	udelay(20);

	/* Disable L1-Active */
S
Stanislaw Gruszka 已提交
1083
	il_set_bits_prph(il, APMG_PCIDEV_STT_REG,
1084 1085 1086 1087 1088
			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);

out:
	return ret;
}
S
Stanislaw Gruszka 已提交
1089
EXPORT_SYMBOL(il_apm_init);
1090 1091


S
Stanislaw Gruszka 已提交
1092
int il_set_tx_power(struct il_priv *il, s8 tx_power, bool force)
1093 1094 1095
{
	int ret;
	s8 prev_tx_power;
1096
	bool defer;
1097
	struct il_rxon_context *ctx = &il->ctx;
1098

S
Stanislaw Gruszka 已提交
1099
	lockdep_assert_held(&il->mutex);
1100

S
Stanislaw Gruszka 已提交
1101
	if (il->tx_power_user_lmt == tx_power && !force)
1102 1103
		return 0;

S
Stanislaw Gruszka 已提交
1104
	if (!il->cfg->ops->lib->send_tx_power)
1105 1106
		return -EOPNOTSUPP;

1107 1108
	/* 0 dBm mean 1 milliwatt */
	if (tx_power < 0) {
1109
		IL_WARN(
1110 1111
			 "Requested user TXPOWER %d below 1 mW.\n",
			 tx_power);
1112 1113 1114
		return -EINVAL;
	}

S
Stanislaw Gruszka 已提交
1115
	if (tx_power > il->tx_power_device_lmt) {
1116
		IL_WARN(
1117
			"Requested user TXPOWER %d above upper limit %d.\n",
S
Stanislaw Gruszka 已提交
1118
			 tx_power, il->tx_power_device_lmt);
1119 1120 1121
		return -EINVAL;
	}

S
Stanislaw Gruszka 已提交
1122
	if (!il_is_ready_rf(il))
1123 1124
		return -EIO;

1125 1126
	/* scan complete and commit_rxon use tx_power_next value,
	 * it always need to be updated for newest request */
S
Stanislaw Gruszka 已提交
1127
	il->tx_power_next = tx_power;
1128 1129

	/* do not set tx power when scanning or channel changing */
S
Stanislaw Gruszka 已提交
1130
	defer = test_bit(S_SCANNING, &il->status) ||
1131 1132
		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
	if (defer && !force) {
1133
		D_INFO("Deferring tx power set\n");
1134 1135 1136
		return 0;
	}

S
Stanislaw Gruszka 已提交
1137 1138
	prev_tx_power = il->tx_power_user_lmt;
	il->tx_power_user_lmt = tx_power;
1139

S
Stanislaw Gruszka 已提交
1140
	ret = il->cfg->ops->lib->send_tx_power(il);
1141 1142 1143

	/* if fail to set tx_power, restore the orig. tx power */
	if (ret) {
S
Stanislaw Gruszka 已提交
1144 1145
		il->tx_power_user_lmt = prev_tx_power;
		il->tx_power_next = prev_tx_power;
1146 1147 1148
	}
	return ret;
}
S
Stanislaw Gruszka 已提交
1149
EXPORT_SYMBOL(il_set_tx_power);
1150

S
Stanislaw Gruszka 已提交
1151
void il_send_bt_config(struct il_priv *il)
1152
{
S
Stanislaw Gruszka 已提交
1153
	struct il_bt_cmd bt_cmd = {
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
		.lead_time = BT_LEAD_TIME_DEF,
		.max_kill = BT_MAX_KILL_DEF,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

	if (!bt_coex_active)
		bt_cmd.flags = BT_COEX_DISABLE;
	else
		bt_cmd.flags = BT_COEX_ENABLE;

1165
	D_INFO("BT coex %s\n",
1166 1167
		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");

1168
	if (il_send_cmd_pdu(il, C_BT_CONFIG,
S
Stanislaw Gruszka 已提交
1169
			     sizeof(struct il_bt_cmd), &bt_cmd))
1170
		IL_ERR("failed to send BT Coex Config\n");
1171
}
S
Stanislaw Gruszka 已提交
1172
EXPORT_SYMBOL(il_send_bt_config);
1173

S
Stanislaw Gruszka 已提交
1174
int il_send_stats_request(struct il_priv *il, u8 flags, bool clear)
1175
{
S
Stanislaw Gruszka 已提交
1176
	struct il_stats_cmd stats_cmd = {
1177
		.configuration_flags =
S
Stanislaw Gruszka 已提交
1178
			clear ? IL_STATS_CONF_CLEAR_STATS : 0,
1179 1180 1181
	};

	if (flags & CMD_ASYNC)
1182
		return il_send_cmd_pdu_async(il, C_STATS,
S
Stanislaw Gruszka 已提交
1183 1184
					sizeof(struct il_stats_cmd),
					&stats_cmd, NULL);
1185
	else
1186
		return il_send_cmd_pdu(il, C_STATS,
S
Stanislaw Gruszka 已提交
1187 1188
					sizeof(struct il_stats_cmd),
					&stats_cmd);
1189
}
S
Stanislaw Gruszka 已提交
1190
EXPORT_SYMBOL(il_send_stats_request);
1191

1192
void il_hdl_pm_sleep(struct il_priv *il,
1193
			   struct il_rx_buf *rxb)
1194
{
1195
#ifdef CONFIG_IWLEGACY_DEBUG
1196
	struct il_rx_pkt *pkt = rxb_addr(rxb);
S
Stanislaw Gruszka 已提交
1197
	struct il_sleep_notification *sleep = &(pkt->u.sleep_notif);
1198
	D_RX("sleep mode: %d, src: %d\n",
1199 1200 1201
		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
1202
EXPORT_SYMBOL(il_hdl_pm_sleep);
1203

1204
void il_hdl_pm_debug_stats(struct il_priv *il,
1205
				      struct il_rx_buf *rxb)
1206
{
1207
	struct il_rx_pkt *pkt = rxb_addr(rxb);
1208
	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
1209
	D_RADIO("Dumping %d bytes of unhandled "
1210
			"notification for %s:\n", len,
S
Stanislaw Gruszka 已提交
1211
			il_get_cmd_string(pkt->hdr.cmd));
S
Stanislaw Gruszka 已提交
1212
	il_print_hex_dump(il, IL_DL_RADIO, pkt->u.raw, len);
1213
}
1214
EXPORT_SYMBOL(il_hdl_pm_debug_stats);
1215

S
Stanislaw Gruszka 已提交
1216
void il_hdl_error(struct il_priv *il,
1217
			struct il_rx_buf *rxb)
1218
{
1219
	struct il_rx_pkt *pkt = rxb_addr(rxb);
1220

1221
	IL_ERR("Error Reply type 0x%08X cmd %s (0x%02X) "
1222 1223
		"seq 0x%04X ser 0x%08X\n",
		le32_to_cpu(pkt->u.err_resp.error_type),
S
Stanislaw Gruszka 已提交
1224
		il_get_cmd_string(pkt->u.err_resp.cmd_id),
1225 1226 1227 1228
		pkt->u.err_resp.cmd_id,
		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
		le32_to_cpu(pkt->u.err_resp.error_info));
}
S
Stanislaw Gruszka 已提交
1229
EXPORT_SYMBOL(il_hdl_error);
1230

S
Stanislaw Gruszka 已提交
1231
void il_clear_isr_stats(struct il_priv *il)
1232
{
S
Stanislaw Gruszka 已提交
1233
	memset(&il->isr_stats, 0, sizeof(il->isr_stats));
1234 1235
}

S
Stanislaw Gruszka 已提交
1236
int il_mac_conf_tx(struct ieee80211_hw *hw,
1237
			   struct ieee80211_vif *vif, u16 queue,
1238 1239
			   const struct ieee80211_tx_queue_params *params)
{
S
Stanislaw Gruszka 已提交
1240
	struct il_priv *il = hw->priv;
1241 1242 1243
	unsigned long flags;
	int q;

1244
	D_MAC80211("enter\n");
1245

S
Stanislaw Gruszka 已提交
1246
	if (!il_is_ready_rf(il)) {
1247
		D_MAC80211("leave - RF not ready\n");
1248 1249 1250 1251
		return -EIO;
	}

	if (queue >= AC_NUM) {
1252
		D_MAC80211("leave - queue >= AC_NUM %d\n", queue);
1253 1254 1255 1256 1257
		return 0;
	}

	q = AC_NUM - 1 - queue;

S
Stanislaw Gruszka 已提交
1258
	spin_lock_irqsave(&il->lock, flags);
1259

1260
	il->ctx.qos_data.def_qos_parm.ac[q].cw_min =
1261
			cpu_to_le16(params->cw_min);
1262
	il->ctx.qos_data.def_qos_parm.ac[q].cw_max =
1263
			cpu_to_le16(params->cw_max);
1264 1265
	il->ctx.qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
	il->ctx.qos_data.def_qos_parm.ac[q].edca_txop =
1266 1267
				cpu_to_le16((params->txop * 32));

1268
	il->ctx.qos_data.def_qos_parm.ac[q].reserved1 = 0;
1269

S
Stanislaw Gruszka 已提交
1270
	spin_unlock_irqrestore(&il->lock, flags);
1271

1272
	D_MAC80211("leave\n");
1273 1274
	return 0;
}
S
Stanislaw Gruszka 已提交
1275
EXPORT_SYMBOL(il_mac_conf_tx);
1276

S
Stanislaw Gruszka 已提交
1277
int il_mac_tx_last_beacon(struct ieee80211_hw *hw)
1278
{
S
Stanislaw Gruszka 已提交
1279
	struct il_priv *il = hw->priv;
1280

S
Stanislaw Gruszka 已提交
1281
	return il->ibss_manager == IL_IBSS_MANAGER;
1282
}
S
Stanislaw Gruszka 已提交
1283
EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon);
1284 1285

static int
S
Stanislaw Gruszka 已提交
1286
il_set_mode(struct il_priv *il, struct il_rxon_context *ctx)
1287
{
S
Stanislaw Gruszka 已提交
1288
	il_connection_init_rx_config(il, ctx);
1289

S
Stanislaw Gruszka 已提交
1290 1291
	if (il->cfg->ops->hcmd->set_rxon_chain)
		il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
1292

S
Stanislaw Gruszka 已提交
1293
	return il_commit_rxon(il, ctx);
1294 1295
}

S
Stanislaw Gruszka 已提交
1296
static int il_setup_interface(struct il_priv *il,
S
Stanislaw Gruszka 已提交
1297
			       struct il_rxon_context *ctx)
1298 1299 1300 1301
{
	struct ieee80211_vif *vif = ctx->vif;
	int err;

S
Stanislaw Gruszka 已提交
1302
	lockdep_assert_held(&il->mutex);
1303 1304 1305 1306 1307 1308

	/*
	 * This variable will be correct only when there's just
	 * a single context, but all code using it is for hardware
	 * that supports only one context.
	 */
S
Stanislaw Gruszka 已提交
1309
	il->iw_mode = vif->type;
1310 1311 1312

	ctx->is_active = true;

S
Stanislaw Gruszka 已提交
1313
	err = il_set_mode(il, ctx);
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
	if (err) {
		if (!ctx->always_active)
			ctx->is_active = false;
		return err;
	}

	return 0;
}

int
S
Stanislaw Gruszka 已提交
1324
il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1325
{
S
Stanislaw Gruszka 已提交
1326
	struct il_priv *il = hw->priv;
S
Stanislaw Gruszka 已提交
1327
	struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
1328
	int err;
1329
	u32 modes;
1330

1331
	D_MAC80211("enter: type %d, addr %pM\n",
1332 1333
			   vif->type, vif->addr);

S
Stanislaw Gruszka 已提交
1334
	mutex_lock(&il->mutex);
1335

S
Stanislaw Gruszka 已提交
1336
	if (!il_is_ready_rf(il)) {
1337
		IL_WARN("Try to add interface when device not ready\n");
1338 1339 1340 1341 1342
		err = -EINVAL;
		goto out;
	}


1343 1344 1345 1346 1347
	/* check if busy context is exclusive */
	if (il->ctx.vif &&
	    (il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type))) {
		err = -EINVAL;
		goto out;
1348 1349
	}

1350 1351
	modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes;
	if (!(modes & BIT(vif->type))) {
1352 1353 1354 1355
		err = -EOPNOTSUPP;
		goto out;
	}

1356 1357
	vif_priv->ctx = &il->ctx;
	il->ctx.vif = vif;
1358

1359 1360 1361 1362 1363
	err = il_setup_interface(il, &il->ctx);
	if (err) {
		il->ctx.vif = NULL;
		il->iw_mode = NL80211_IFTYPE_STATION;
	}
1364 1365

 out:
S
Stanislaw Gruszka 已提交
1366
	mutex_unlock(&il->mutex);
1367

1368
	D_MAC80211("leave\n");
1369 1370
	return err;
}
S
Stanislaw Gruszka 已提交
1371
EXPORT_SYMBOL(il_mac_add_interface);
1372

S
Stanislaw Gruszka 已提交
1373
static void il_teardown_interface(struct il_priv *il,
1374 1375 1376
				   struct ieee80211_vif *vif,
				   bool mode_change)
{
S
Stanislaw Gruszka 已提交
1377
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
1378

S
Stanislaw Gruszka 已提交
1379
	lockdep_assert_held(&il->mutex);
1380

S
Stanislaw Gruszka 已提交
1381 1382 1383
	if (il->scan_vif == vif) {
		il_scan_cancel_timeout(il, 200);
		il_force_scan_end(il);
1384 1385 1386
	}

	if (!mode_change) {
S
Stanislaw Gruszka 已提交
1387
		il_set_mode(il, ctx);
1388 1389 1390 1391 1392
		if (!ctx->always_active)
			ctx->is_active = false;
	}
}

S
Stanislaw Gruszka 已提交
1393
void il_mac_remove_interface(struct ieee80211_hw *hw,
1394 1395
			      struct ieee80211_vif *vif)
{
S
Stanislaw Gruszka 已提交
1396
	struct il_priv *il = hw->priv;
S
Stanislaw Gruszka 已提交
1397
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
1398

1399
	D_MAC80211("enter\n");
1400

S
Stanislaw Gruszka 已提交
1401
	mutex_lock(&il->mutex);
1402 1403 1404 1405

	WARN_ON(ctx->vif != vif);
	ctx->vif = NULL;

S
Stanislaw Gruszka 已提交
1406
	il_teardown_interface(il, vif, false);
1407

S
Stanislaw Gruszka 已提交
1408 1409
	memset(il->bssid, 0, ETH_ALEN);
	mutex_unlock(&il->mutex);
1410

1411
	D_MAC80211("leave\n");
1412 1413

}
S
Stanislaw Gruszka 已提交
1414
EXPORT_SYMBOL(il_mac_remove_interface);
1415

S
Stanislaw Gruszka 已提交
1416
int il_alloc_txq_mem(struct il_priv *il)
1417
{
S
Stanislaw Gruszka 已提交
1418 1419
	if (!il->txq)
		il->txq = kzalloc(
S
Stanislaw Gruszka 已提交
1420
			sizeof(struct il_tx_queue) *
S
Stanislaw Gruszka 已提交
1421
				il->cfg->base_params->num_of_queues,
1422
			GFP_KERNEL);
S
Stanislaw Gruszka 已提交
1423
	if (!il->txq) {
1424
		IL_ERR("Not enough memory for txq\n");
1425 1426 1427 1428
		return -ENOMEM;
	}
	return 0;
}
S
Stanislaw Gruszka 已提交
1429
EXPORT_SYMBOL(il_alloc_txq_mem);
1430

S
Stanislaw Gruszka 已提交
1431
void il_txq_mem(struct il_priv *il)
1432
{
S
Stanislaw Gruszka 已提交
1433 1434
	kfree(il->txq);
	il->txq = NULL;
1435
}
S
Stanislaw Gruszka 已提交
1436
EXPORT_SYMBOL(il_txq_mem);
1437

1438
#ifdef CONFIG_IWLEGACY_DEBUGFS
1439

S
Stanislaw Gruszka 已提交
1440
#define IL_TRAFFIC_DUMP_SIZE	(IL_TRAFFIC_ENTRY_SIZE * IL_TRAFFIC_ENTRIES)
1441

S
Stanislaw Gruszka 已提交
1442
void il_reset_traffic_log(struct il_priv *il)
1443
{
S
Stanislaw Gruszka 已提交
1444 1445 1446 1447 1448 1449
	il->tx_traffic_idx = 0;
	il->rx_traffic_idx = 0;
	if (il->tx_traffic)
		memset(il->tx_traffic, 0, IL_TRAFFIC_DUMP_SIZE);
	if (il->rx_traffic)
		memset(il->rx_traffic, 0, IL_TRAFFIC_DUMP_SIZE);
1450 1451
}

S
Stanislaw Gruszka 已提交
1452
int il_alloc_traffic_mem(struct il_priv *il)
1453
{
S
Stanislaw Gruszka 已提交
1454
	u32 traffic_size = IL_TRAFFIC_DUMP_SIZE;
1455

1456
	if (il_debug_level & IL_DL_TX) {
S
Stanislaw Gruszka 已提交
1457 1458
		if (!il->tx_traffic) {
			il->tx_traffic =
1459
				kzalloc(traffic_size, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
1460
			if (!il->tx_traffic)
1461 1462 1463
				return -ENOMEM;
		}
	}
1464
	if (il_debug_level & IL_DL_RX) {
S
Stanislaw Gruszka 已提交
1465 1466
		if (!il->rx_traffic) {
			il->rx_traffic =
1467
				kzalloc(traffic_size, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
1468
			if (!il->rx_traffic)
1469 1470 1471
				return -ENOMEM;
		}
	}
S
Stanislaw Gruszka 已提交
1472
	il_reset_traffic_log(il);
1473 1474
	return 0;
}
S
Stanislaw Gruszka 已提交
1475
EXPORT_SYMBOL(il_alloc_traffic_mem);
1476

S
Stanislaw Gruszka 已提交
1477
void il_free_traffic_mem(struct il_priv *il)
1478
{
S
Stanislaw Gruszka 已提交
1479 1480
	kfree(il->tx_traffic);
	il->tx_traffic = NULL;
1481

S
Stanislaw Gruszka 已提交
1482 1483
	kfree(il->rx_traffic);
	il->rx_traffic = NULL;
1484
}
S
Stanislaw Gruszka 已提交
1485
EXPORT_SYMBOL(il_free_traffic_mem);
1486

S
Stanislaw Gruszka 已提交
1487
void il_dbg_log_tx_data_frame(struct il_priv *il,
1488 1489 1490 1491 1492
		      u16 length, struct ieee80211_hdr *header)
{
	__le16 fc;
	u16 len;

1493
	if (likely(!(il_debug_level & IL_DL_TX)))
1494 1495
		return;

S
Stanislaw Gruszka 已提交
1496
	if (!il->tx_traffic)
1497 1498 1499 1500
		return;

	fc = header->frame_control;
	if (ieee80211_is_data(fc)) {
S
Stanislaw Gruszka 已提交
1501 1502
		len = (length > IL_TRAFFIC_ENTRY_SIZE)
		       ? IL_TRAFFIC_ENTRY_SIZE : length;
S
Stanislaw Gruszka 已提交
1503 1504
		memcpy((il->tx_traffic +
		       (il->tx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)),
1505
		       header, len);
S
Stanislaw Gruszka 已提交
1506 1507
		il->tx_traffic_idx =
			(il->tx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES;
1508 1509
	}
}
S
Stanislaw Gruszka 已提交
1510
EXPORT_SYMBOL(il_dbg_log_tx_data_frame);
1511

S
Stanislaw Gruszka 已提交
1512
void il_dbg_log_rx_data_frame(struct il_priv *il,
1513 1514 1515 1516 1517
		      u16 length, struct ieee80211_hdr *header)
{
	__le16 fc;
	u16 len;

1518
	if (likely(!(il_debug_level & IL_DL_RX)))
1519 1520
		return;

S
Stanislaw Gruszka 已提交
1521
	if (!il->rx_traffic)
1522 1523 1524 1525
		return;

	fc = header->frame_control;
	if (ieee80211_is_data(fc)) {
S
Stanislaw Gruszka 已提交
1526 1527
		len = (length > IL_TRAFFIC_ENTRY_SIZE)
		       ? IL_TRAFFIC_ENTRY_SIZE : length;
S
Stanislaw Gruszka 已提交
1528 1529
		memcpy((il->rx_traffic +
		       (il->rx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)),
1530
		       header, len);
S
Stanislaw Gruszka 已提交
1531 1532
		il->rx_traffic_idx =
			(il->rx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES;
1533 1534
	}
}
S
Stanislaw Gruszka 已提交
1535
EXPORT_SYMBOL(il_dbg_log_rx_data_frame);
1536

S
Stanislaw Gruszka 已提交
1537
const char *il_get_mgmt_string(int cmd)
1538 1539
{
	switch (cmd) {
S
Stanislaw Gruszka 已提交
1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
		IL_CMD(MANAGEMENT_ASSOC_REQ);
		IL_CMD(MANAGEMENT_ASSOC_RESP);
		IL_CMD(MANAGEMENT_REASSOC_REQ);
		IL_CMD(MANAGEMENT_REASSOC_RESP);
		IL_CMD(MANAGEMENT_PROBE_REQ);
		IL_CMD(MANAGEMENT_PROBE_RESP);
		IL_CMD(MANAGEMENT_BEACON);
		IL_CMD(MANAGEMENT_ATIM);
		IL_CMD(MANAGEMENT_DISASSOC);
		IL_CMD(MANAGEMENT_AUTH);
		IL_CMD(MANAGEMENT_DEAUTH);
		IL_CMD(MANAGEMENT_ACTION);
1552 1553 1554 1555 1556 1557
	default:
		return "UNKNOWN";

	}
}

S
Stanislaw Gruszka 已提交
1558
const char *il_get_ctrl_string(int cmd)
1559 1560
{
	switch (cmd) {
S
Stanislaw Gruszka 已提交
1561 1562 1563 1564 1565 1566 1567 1568
		IL_CMD(CONTROL_BACK_REQ);
		IL_CMD(CONTROL_BACK);
		IL_CMD(CONTROL_PSPOLL);
		IL_CMD(CONTROL_RTS);
		IL_CMD(CONTROL_CTS);
		IL_CMD(CONTROL_ACK);
		IL_CMD(CONTROL_CFEND);
		IL_CMD(CONTROL_CFENDACK);
1569 1570 1571 1572 1573 1574
	default:
		return "UNKNOWN";

	}
}

S
Stanislaw Gruszka 已提交
1575
void il_clear_traffic_stats(struct il_priv *il)
1576
{
S
Stanislaw Gruszka 已提交
1577 1578
	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
1579 1580 1581
}

/*
1582
 * if CONFIG_IWLEGACY_DEBUGFS defined,
S
Stanislaw Gruszka 已提交
1583
 * il_update_stats function will
1584
 * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass
S
Stanislaw Gruszka 已提交
1585
 * Use debugFs to display the rx/rx_stats
1586
 * if CONFIG_IWLEGACY_DEBUGFS not being defined, then no MGMT and CTRL
1587
 * information will be recorded, but DATA pkt still will be recorded
S
Stanislaw Gruszka 已提交
1588
 * for the reason of il_led.c need to control the led blinking based on
1589 1590 1591 1592
 * number of tx and rx data.
 *
 */
void
S
Stanislaw Gruszka 已提交
1593
il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
1594 1595 1596 1597
{
	struct traffic_stats	*stats;

	if (is_tx)
S
Stanislaw Gruszka 已提交
1598
		stats = &il->tx_stats;
1599
	else
S
Stanislaw Gruszka 已提交
1600
		stats = &il->rx_stats;
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673

	if (ieee80211_is_mgmt(fc)) {
		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_BEACON):
			stats->mgmt[MANAGEMENT_BEACON]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_ATIM):
			stats->mgmt[MANAGEMENT_ATIM]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
			stats->mgmt[MANAGEMENT_DISASSOC]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_AUTH):
			stats->mgmt[MANAGEMENT_AUTH]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
			stats->mgmt[MANAGEMENT_DEAUTH]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_ACTION):
			stats->mgmt[MANAGEMENT_ACTION]++;
			break;
		}
	} else if (ieee80211_is_ctl(fc)) {
		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
			stats->ctrl[CONTROL_BACK_REQ]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_BACK):
			stats->ctrl[CONTROL_BACK]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
			stats->ctrl[CONTROL_PSPOLL]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_RTS):
			stats->ctrl[CONTROL_RTS]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_CTS):
			stats->ctrl[CONTROL_CTS]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_ACK):
			stats->ctrl[CONTROL_ACK]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_CFEND):
			stats->ctrl[CONTROL_CFEND]++;
			break;
		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
			stats->ctrl[CONTROL_CFENDACK]++;
			break;
		}
	} else {
		/* data */
		stats->data_cnt++;
		stats->data_bytes += len;
	}
}
S
Stanislaw Gruszka 已提交
1674
EXPORT_SYMBOL(il_update_stats);
1675 1676
#endif

S
Stanislaw Gruszka 已提交
1677
int il_force_reset(struct il_priv *il, bool external)
1678
{
S
Stanislaw Gruszka 已提交
1679
	struct il_force_reset *force_reset;
1680

S
Stanislaw Gruszka 已提交
1681
	if (test_bit(S_EXIT_PENDING, &il->status))
1682 1683
		return -EINVAL;

S
Stanislaw Gruszka 已提交
1684
	force_reset = &il->force_reset;
1685 1686 1687 1688 1689
	force_reset->reset_request_count++;
	if (!external) {
		if (force_reset->last_force_reset_jiffies &&
		    time_after(force_reset->last_force_reset_jiffies +
		    force_reset->reset_duration, jiffies)) {
1690
			D_INFO("force reset rejected\n");
1691 1692 1693 1694 1695 1696
			force_reset->reset_reject_count++;
			return -EAGAIN;
		}
	}
	force_reset->reset_success_count++;
	force_reset->last_force_reset_jiffies = jiffies;
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706

	/*
	 * if the request is from external(ex: debugfs),
	 * then always perform the request in regardless the module
	 * parameter setting
	 * if the request is from internal (uCode error or driver
	 * detect failure), then fw_restart module parameter
	 * need to be check before performing firmware reload
	 */

S
Stanislaw Gruszka 已提交
1707
	if (!external && !il->cfg->mod_params->restart_fw) {
1708
		D_INFO("Cancel firmware reload based on "
1709 1710
			       "module parameter setting\n");
		return 0;
1711
	}
1712

1713
	IL_ERR("On demand firmware reload\n");
1714

S
Stanislaw Gruszka 已提交
1715
	/* Set the FW error flag -- cleared on il_down */
S
Stanislaw Gruszka 已提交
1716
	set_bit(S_FW_ERROR, &il->status);
S
Stanislaw Gruszka 已提交
1717
	wake_up(&il->wait_command_queue);
1718 1719 1720 1721
	/*
	 * Keep the restart process from trying to send host
	 * commands by clearing the INIT status bit
	 */
S
Stanislaw Gruszka 已提交
1722
	clear_bit(S_READY, &il->status);
S
Stanislaw Gruszka 已提交
1723
	queue_work(il->workqueue, &il->restart);
1724

1725 1726 1727 1728
	return 0;
}

int
S
Stanislaw Gruszka 已提交
1729
il_mac_change_interface(struct ieee80211_hw *hw,
1730 1731 1732
			struct ieee80211_vif *vif,
			enum nl80211_iftype newtype, bool newp2p)
{
S
Stanislaw Gruszka 已提交
1733
	struct il_priv *il = hw->priv;
S
Stanislaw Gruszka 已提交
1734
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
1735
	u32 modes;
1736 1737 1738 1739
	int err;

	newtype = ieee80211_iftype_p2p(newtype, newp2p);

S
Stanislaw Gruszka 已提交
1740
	mutex_lock(&il->mutex);
1741

S
Stanislaw Gruszka 已提交
1742
	if (!ctx->vif || !il_is_ready_rf(il)) {
1743 1744 1745 1746 1747 1748 1749 1750
		/*
		 * Huh? But wait ... this can maybe happen when
		 * we're in the middle of a firmware restart!
		 */
		err = -EBUSY;
		goto out;
	}

1751 1752 1753
	modes = ctx->interface_modes | ctx->exclusive_interface_modes;
	if (!(modes & BIT(newtype))) {
		err = -EOPNOTSUPP;
1754 1755 1756
		goto out;
	}

1757 1758 1759 1760
	if ((il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type)) ||
	    (il->ctx.exclusive_interface_modes & BIT(newtype))) {
		err = -EINVAL;
		goto out;
1761 1762 1763
	}

	/* success */
S
Stanislaw Gruszka 已提交
1764
	il_teardown_interface(il, vif, true);
1765
	vif->type = newtype;
1766
	vif->p2p = newp2p;
S
Stanislaw Gruszka 已提交
1767
	err = il_setup_interface(il, ctx);
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
	WARN_ON(err);
	/*
	 * We've switched internally, but submitting to the
	 * device may have failed for some reason. Mask this
	 * error, because otherwise mac80211 will not switch
	 * (and set the interface type back) and we'll be
	 * out of sync with it.
	 */
	err = 0;

 out:
S
Stanislaw Gruszka 已提交
1779
	mutex_unlock(&il->mutex);
1780 1781
	return err;
}
S
Stanislaw Gruszka 已提交
1782
EXPORT_SYMBOL(il_mac_change_interface);
1783 1784 1785 1786 1787

/*
 * On every watchdog tick we check (latest) time stamp. If it does not
 * change during timeout period and queue is not empty we reset firmware.
 */
S
Stanislaw Gruszka 已提交
1788
static int il_check_stuck_queue(struct il_priv *il, int cnt)
1789
{
S
Stanislaw Gruszka 已提交
1790
	struct il_tx_queue *txq = &il->txq[cnt];
S
Stanislaw Gruszka 已提交
1791
	struct il_queue *q = &txq->q;
1792 1793 1794 1795 1796 1797 1798 1799 1800
	unsigned long timeout;
	int ret;

	if (q->read_ptr == q->write_ptr) {
		txq->time_stamp = jiffies;
		return 0;
	}

	timeout = txq->time_stamp +
S
Stanislaw Gruszka 已提交
1801
		  msecs_to_jiffies(il->cfg->base_params->wd_timeout);
1802 1803

	if (time_after(jiffies, timeout)) {
1804
		IL_ERR("Queue %d stuck for %u ms.\n",
S
Stanislaw Gruszka 已提交
1805 1806
				q->id, il->cfg->base_params->wd_timeout);
		ret = il_force_reset(il, false);
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816
		return (ret == -EAGAIN) ? 0 : 1;
	}

	return 0;
}

/*
 * Making watchdog tick be a quarter of timeout assure we will
 * discover the queue hung between timeout and 1.25*timeout
 */
S
Stanislaw Gruszka 已提交
1817
#define IL_WD_TICK(timeout) ((timeout) / 4)
1818 1819 1820 1821 1822

/*
 * Watchdog timer callback, we check each tx queue for stuck, if if hung
 * we reset the firmware. If everything is fine just rearm the timer.
 */
S
Stanislaw Gruszka 已提交
1823
void il_bg_watchdog(unsigned long data)
1824
{
S
Stanislaw Gruszka 已提交
1825
	struct il_priv *il = (struct il_priv *)data;
1826 1827 1828
	int cnt;
	unsigned long timeout;

S
Stanislaw Gruszka 已提交
1829
	if (test_bit(S_EXIT_PENDING, &il->status))
1830 1831
		return;

S
Stanislaw Gruszka 已提交
1832
	timeout = il->cfg->base_params->wd_timeout;
1833 1834 1835 1836
	if (timeout == 0)
		return;

	/* monitor and check for stuck cmd queue */
S
Stanislaw Gruszka 已提交
1837
	if (il_check_stuck_queue(il, il->cmd_queue))
1838 1839 1840
		return;

	/* monitor and check for other stuck queues */
S
Stanislaw Gruszka 已提交
1841 1842
	if (il_is_any_associated(il)) {
		for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
1843
			/* skip as we already checked the command queue */
S
Stanislaw Gruszka 已提交
1844
			if (cnt == il->cmd_queue)
1845
				continue;
S
Stanislaw Gruszka 已提交
1846
			if (il_check_stuck_queue(il, cnt))
1847 1848 1849 1850
				return;
		}
	}

S
Stanislaw Gruszka 已提交
1851
	mod_timer(&il->watchdog, jiffies +
S
Stanislaw Gruszka 已提交
1852
		  msecs_to_jiffies(IL_WD_TICK(timeout)));
1853
}
S
Stanislaw Gruszka 已提交
1854
EXPORT_SYMBOL(il_bg_watchdog);
1855

S
Stanislaw Gruszka 已提交
1856
void il_setup_watchdog(struct il_priv *il)
1857
{
S
Stanislaw Gruszka 已提交
1858
	unsigned int timeout = il->cfg->base_params->wd_timeout;
1859 1860

	if (timeout)
S
Stanislaw Gruszka 已提交
1861
		mod_timer(&il->watchdog,
S
Stanislaw Gruszka 已提交
1862
			  jiffies + msecs_to_jiffies(IL_WD_TICK(timeout)));
1863
	else
S
Stanislaw Gruszka 已提交
1864
		del_timer(&il->watchdog);
1865
}
S
Stanislaw Gruszka 已提交
1866
EXPORT_SYMBOL(il_setup_watchdog);
1867 1868 1869 1870 1871 1872 1873 1874

/*
 * extended beacon time format
 * time in usec will be changed into a 32-bit value in extended:internal format
 * the extended part is the beacon counts
 * the internal part is the time in usec within one beacon interval
 */
u32
S
Stanislaw Gruszka 已提交
1875
il_usecs_to_beacons(struct il_priv *il,
1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
					u32 usec, u32 beacon_interval)
{
	u32 quot;
	u32 rem;
	u32 interval = beacon_interval * TIME_UNIT;

	if (!interval || !usec)
		return 0;

	quot = (usec / interval) &
S
Stanislaw Gruszka 已提交
1886 1887 1888 1889 1890
		(il_beacon_time_mask_high(il,
		il->hw_params.beacon_time_tsf_bits) >>
		il->hw_params.beacon_time_tsf_bits);
	rem = (usec % interval) & il_beacon_time_mask_low(il,
				   il->hw_params.beacon_time_tsf_bits);
1891

S
Stanislaw Gruszka 已提交
1892
	return (quot << il->hw_params.beacon_time_tsf_bits) + rem;
1893
}
S
Stanislaw Gruszka 已提交
1894
EXPORT_SYMBOL(il_usecs_to_beacons);
1895 1896 1897 1898

/* base is usually what we get from ucode with each received frame,
 * the same as HW timer counter counting down
 */
S
Stanislaw Gruszka 已提交
1899
__le32 il_add_beacon_time(struct il_priv *il, u32 base,
1900 1901
			   u32 addon, u32 beacon_interval)
{
S
Stanislaw Gruszka 已提交
1902 1903 1904 1905
	u32 base_low = base & il_beacon_time_mask_low(il,
					il->hw_params.beacon_time_tsf_bits);
	u32 addon_low = addon & il_beacon_time_mask_low(il,
					il->hw_params.beacon_time_tsf_bits);
1906
	u32 interval = beacon_interval * TIME_UNIT;
S
Stanislaw Gruszka 已提交
1907 1908 1909 1910
	u32 res = (base & il_beacon_time_mask_high(il,
				il->hw_params.beacon_time_tsf_bits)) +
				(addon & il_beacon_time_mask_high(il,
				il->hw_params.beacon_time_tsf_bits));
1911 1912 1913 1914 1915

	if (base_low > addon_low)
		res += base_low - addon_low;
	else if (base_low < addon_low) {
		res += interval + base_low - addon_low;
S
Stanislaw Gruszka 已提交
1916
		res += (1 << il->hw_params.beacon_time_tsf_bits);
1917
	} else
S
Stanislaw Gruszka 已提交
1918
		res += (1 << il->hw_params.beacon_time_tsf_bits);
1919 1920 1921

	return cpu_to_le32(res);
}
S
Stanislaw Gruszka 已提交
1922
EXPORT_SYMBOL(il_add_beacon_time);
1923 1924 1925

#ifdef CONFIG_PM

S
Stanislaw Gruszka 已提交
1926
int il_pci_suspend(struct device *device)
1927 1928
{
	struct pci_dev *pdev = to_pci_dev(device);
S
Stanislaw Gruszka 已提交
1929
	struct il_priv *il = pci_get_drvdata(pdev);
1930 1931 1932

	/*
	 * This function is called when system goes into suspend state
S
Stanislaw Gruszka 已提交
1933 1934
	 * mac80211 will call il_mac_stop() from the mac80211 suspend function
	 * first but since il_mac_stop() has no knowledge of who the caller is,
1935 1936 1937
	 * it will not call apm_ops.stop() to stop the DMA operation.
	 * Calling apm_ops.stop here to make sure we stop the DMA.
	 */
S
Stanislaw Gruszka 已提交
1938
	il_apm_stop(il);
1939 1940 1941

	return 0;
}
S
Stanislaw Gruszka 已提交
1942
EXPORT_SYMBOL(il_pci_suspend);
1943

S
Stanislaw Gruszka 已提交
1944
int il_pci_resume(struct device *device)
1945 1946
{
	struct pci_dev *pdev = to_pci_dev(device);
S
Stanislaw Gruszka 已提交
1947
	struct il_priv *il = pci_get_drvdata(pdev);
1948 1949 1950 1951 1952 1953 1954 1955
	bool hw_rfkill = false;

	/*
	 * We disable the RETRY_TIMEOUT register (0x41) to keep
	 * PCI Tx retries from interfering with C3 CPU state.
	 */
	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);

S
Stanislaw Gruszka 已提交
1956
	il_enable_interrupts(il);
1957

1958
	if (!(_il_rd(il, CSR_GP_CNTRL) &
1959 1960 1961 1962
				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
		hw_rfkill = true;

	if (hw_rfkill)
S
Stanislaw Gruszka 已提交
1963
		set_bit(S_RF_KILL_HW, &il->status);
1964
	else
S
Stanislaw Gruszka 已提交
1965
		clear_bit(S_RF_KILL_HW, &il->status);
1966

S
Stanislaw Gruszka 已提交
1967
	wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rfkill);
1968 1969 1970

	return 0;
}
S
Stanislaw Gruszka 已提交
1971
EXPORT_SYMBOL(il_pci_resume);
1972

S
Stanislaw Gruszka 已提交
1973 1974 1975 1976 1977 1978 1979
const struct dev_pm_ops il_pm_ops = {
	.suspend = il_pci_suspend,
	.resume = il_pci_resume,
	.freeze = il_pci_suspend,
	.thaw = il_pci_resume,
	.poweroff = il_pci_suspend,
	.restore = il_pci_resume,
1980
};
S
Stanislaw Gruszka 已提交
1981
EXPORT_SYMBOL(il_pm_ops);
1982 1983 1984 1985

#endif /* CONFIG_PM */

static void
S
Stanislaw Gruszka 已提交
1986
il_update_qos(struct il_priv *il, struct il_rxon_context *ctx)
1987
{
S
Stanislaw Gruszka 已提交
1988
	if (test_bit(S_EXIT_PENDING, &il->status))
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
		return;

	if (!ctx->is_active)
		return;

	ctx->qos_data.def_qos_parm.qos_flags = 0;

	if (ctx->qos_data.qos_active)
		ctx->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_UPDATE_EDCA_MSK;

	if (ctx->ht.enabled)
		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;

2003
	D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
2004 2005 2006
		      ctx->qos_data.qos_active,
		      ctx->qos_data.def_qos_parm.qos_flags);

S
Stanislaw Gruszka 已提交
2007
	il_send_cmd_pdu_async(il, ctx->qos_cmd,
S
Stanislaw Gruszka 已提交
2008
			       sizeof(struct il_qosparam_cmd),
2009 2010 2011 2012
			       &ctx->qos_data.def_qos_parm, NULL);
}

/**
S
Stanislaw Gruszka 已提交
2013
 * il_mac_config - mac80211 config callback
2014
 */
S
Stanislaw Gruszka 已提交
2015
int il_mac_config(struct ieee80211_hw *hw, u32 changed)
2016
{
S
Stanislaw Gruszka 已提交
2017
	struct il_priv *il = hw->priv;
S
Stanislaw Gruszka 已提交
2018
	const struct il_channel_info *ch_info;
2019 2020
	struct ieee80211_conf *conf = &hw->conf;
	struct ieee80211_channel *channel = conf->channel;
S
Stanislaw Gruszka 已提交
2021
	struct il_ht_config *ht_conf = &il->current_ht_config;
2022
	struct il_rxon_context *ctx = &il->ctx;
2023 2024 2025 2026
	unsigned long flags = 0;
	int ret = 0;
	u16 ch;
	int scan_active = 0;
2027
	bool ht_changed = false;
2028

S
Stanislaw Gruszka 已提交
2029
	if (WARN_ON(!il->cfg->ops->legacy))
2030 2031
		return -EOPNOTSUPP;

S
Stanislaw Gruszka 已提交
2032
	mutex_lock(&il->mutex);
2033

2034
	D_MAC80211("enter to channel %d changed 0x%X\n",
2035 2036
					channel->hw_value, changed);

S
Stanislaw Gruszka 已提交
2037
	if (unlikely(test_bit(S_SCANNING, &il->status))) {
2038
		scan_active = 1;
2039
		D_MAC80211("scan active\n");
2040 2041 2042 2043 2044
	}

	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
		       IEEE80211_CONF_CHANGE_CHANNEL)) {
		/* mac80211 uses static for non-HT which is what we want */
S
Stanislaw Gruszka 已提交
2045
		il->current_ht_config.smps = conf->smps_mode;
2046 2047 2048 2049 2050 2051 2052 2053

		/*
		 * Recalculate chain counts.
		 *
		 * If monitor mode is enabled then mac80211 will
		 * set up the SM PS mode to OFF if an HT channel is
		 * configured.
		 */
S
Stanislaw Gruszka 已提交
2054
		if (il->cfg->ops->hcmd->set_rxon_chain)
2055
			il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
2056 2057 2058 2059 2060 2061
	}

	/* during scanning mac80211 will delay channel setting until
	 * scan finish with changed = 0
	 */
	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
2062

2063 2064 2065 2066
		if (scan_active)
			goto set_ch_out;

		ch = channel->hw_value;
S
Stanislaw Gruszka 已提交
2067
		ch_info = il_get_channel_info(il, channel->band, ch);
S
Stanislaw Gruszka 已提交
2068
		if (!il_is_channel_valid(ch_info)) {
2069
			D_MAC80211("leave - invalid channel\n");
2070 2071 2072 2073
			ret = -EINVAL;
			goto set_ch_out;
		}

S
Stanislaw Gruszka 已提交
2074
		if (il->iw_mode == NL80211_IFTYPE_ADHOC &&
S
Stanislaw Gruszka 已提交
2075
		    !il_is_channel_ibss(ch_info)) {
2076
			D_MAC80211("leave - not IBSS channel\n");
2077 2078 2079 2080
			ret = -EINVAL;
			goto set_ch_out;
		}

S
Stanislaw Gruszka 已提交
2081
		spin_lock_irqsave(&il->lock, flags);
2082

2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
		/* Configure HT40 channels */
		if (ctx->ht.enabled != conf_is_ht(conf)) {
			ctx->ht.enabled = conf_is_ht(conf);
			ht_changed = true;
		}
		if (ctx->ht.enabled) {
			if (conf_is_ht40_minus(conf)) {
				ctx->ht.extension_chan_offset =
				IEEE80211_HT_PARAM_CHA_SEC_BELOW;
				ctx->ht.is_40mhz = true;
			} else if (conf_is_ht40_plus(conf)) {
				ctx->ht.extension_chan_offset =
				IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
				ctx->ht.is_40mhz = true;
			} else {
				ctx->ht.extension_chan_offset =
				IEEE80211_HT_PARAM_CHA_SEC_NONE;
2100
				ctx->ht.is_40mhz = false;
2101 2102 2103
			}
		} else
			ctx->ht.is_40mhz = false;
2104

2105 2106 2107 2108 2109 2110
		/*
		 * Default to no protection. Protection mode will
		 * later be set from BSS config in il_ht_conf
		 */
		ctx->ht.protection =
				IEEE80211_HT_OP_MODE_PROTECTION_NONE;
2111

2112 2113 2114 2115 2116
		/* if we are switching from ht to 2.4 clear flags
		 * from any ht related info since 2.4 does not
		 * support ht */
		if ((le16_to_cpu(ctx->staging.channel) != ch))
			ctx->staging.flags = 0;
2117

2118 2119
		il_set_rxon_channel(il, channel, ctx);
		il_set_rxon_ht(il, ht_conf);
2120

2121 2122
		il_set_flags_for_band(il, ctx, channel->band,
				       ctx->vif);
2123

S
Stanislaw Gruszka 已提交
2124
		spin_unlock_irqrestore(&il->lock, flags);
2125

S
Stanislaw Gruszka 已提交
2126
		if (il->cfg->ops->legacy->update_bcast_stations)
2127
			ret =
S
Stanislaw Gruszka 已提交
2128
			il->cfg->ops->legacy->update_bcast_stations(il);
2129 2130 2131 2132 2133

 set_ch_out:
		/* The list of supported rates and rate mask can be different
		 * for each band; since the band may have changed, reset
		 * the rate mask to what mac80211 lists */
S
Stanislaw Gruszka 已提交
2134
		il_set_rate(il);
2135 2136 2137 2138
	}

	if (changed & (IEEE80211_CONF_CHANGE_PS |
			IEEE80211_CONF_CHANGE_IDLE)) {
S
Stanislaw Gruszka 已提交
2139
		ret = il_power_update_mode(il, false);
2140
		if (ret)
2141
			D_MAC80211("Error setting sleep level\n");
2142 2143 2144
	}

	if (changed & IEEE80211_CONF_CHANGE_POWER) {
2145
		D_MAC80211("TX Power old=%d new=%d\n",
S
Stanislaw Gruszka 已提交
2146
			il->tx_power_user_lmt, conf->power_level);
2147

S
Stanislaw Gruszka 已提交
2148
		il_set_tx_power(il, conf->power_level, false);
2149 2150
	}

S
Stanislaw Gruszka 已提交
2151
	if (!il_is_ready(il)) {
2152
		D_MAC80211("leave - not ready\n");
2153 2154 2155 2156 2157 2158
		goto out;
	}

	if (scan_active)
		goto out;

2159 2160 2161 2162 2163 2164
	if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
		il_commit_rxon(il, ctx);
	else
		D_INFO("Not re-sending same RXON configuration.\n");
	if (ht_changed)
		il_update_qos(il, ctx);
2165 2166

out:
2167
	D_MAC80211("leave\n");
S
Stanislaw Gruszka 已提交
2168
	mutex_unlock(&il->mutex);
2169 2170
	return ret;
}
S
Stanislaw Gruszka 已提交
2171
EXPORT_SYMBOL(il_mac_config);
2172

S
Stanislaw Gruszka 已提交
2173
void il_mac_reset_tsf(struct ieee80211_hw *hw,
2174
			      struct ieee80211_vif *vif)
2175
{
S
Stanislaw Gruszka 已提交
2176
	struct il_priv *il = hw->priv;
2177
	unsigned long flags;
2178
	struct il_rxon_context *ctx = &il->ctx;
2179

S
Stanislaw Gruszka 已提交
2180
	if (WARN_ON(!il->cfg->ops->legacy))
2181 2182
		return;

S
Stanislaw Gruszka 已提交
2183
	mutex_lock(&il->mutex);
2184
	D_MAC80211("enter\n");
2185

S
Stanislaw Gruszka 已提交
2186 2187 2188
	spin_lock_irqsave(&il->lock, flags);
	memset(&il->current_ht_config, 0, sizeof(struct il_ht_config));
	spin_unlock_irqrestore(&il->lock, flags);
2189

S
Stanislaw Gruszka 已提交
2190
	spin_lock_irqsave(&il->lock, flags);
2191 2192

	/* new association get rid of ibss beacon skb */
S
Stanislaw Gruszka 已提交
2193 2194
	if (il->beacon_skb)
		dev_kfree_skb(il->beacon_skb);
2195

S
Stanislaw Gruszka 已提交
2196
	il->beacon_skb = NULL;
2197

S
Stanislaw Gruszka 已提交
2198
	il->timestamp = 0;
2199

S
Stanislaw Gruszka 已提交
2200
	spin_unlock_irqrestore(&il->lock, flags);
2201

S
Stanislaw Gruszka 已提交
2202 2203
	il_scan_cancel_timeout(il, 100);
	if (!il_is_ready_rf(il)) {
2204
		D_MAC80211("leave - not ready\n");
S
Stanislaw Gruszka 已提交
2205
		mutex_unlock(&il->mutex);
2206 2207 2208 2209 2210 2211 2212
		return;
	}

	/* we are restarting association process
	 * clear RXON_FILTER_ASSOC_MSK bit
	 */
	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
S
Stanislaw Gruszka 已提交
2213
	il_commit_rxon(il, ctx);
2214

S
Stanislaw Gruszka 已提交
2215
	il_set_rate(il);
2216

S
Stanislaw Gruszka 已提交
2217
	mutex_unlock(&il->mutex);
2218

2219
	D_MAC80211("leave\n");
2220
}
S
Stanislaw Gruszka 已提交
2221
EXPORT_SYMBOL(il_mac_reset_tsf);
2222

S
Stanislaw Gruszka 已提交
2223
static void il_ht_conf(struct il_priv *il,
2224 2225
			struct ieee80211_vif *vif)
{
S
Stanislaw Gruszka 已提交
2226
	struct il_ht_config *ht_conf = &il->current_ht_config;
2227 2228
	struct ieee80211_sta *sta;
	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
S
Stanislaw Gruszka 已提交
2229
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
2230

2231
	D_ASSOC("enter:\n");
2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256

	if (!ctx->ht.enabled)
		return;

	ctx->ht.protection =
		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
	ctx->ht.non_gf_sta_present =
		!!(bss_conf->ht_operation_mode &
				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);

	ht_conf->single_chain_sufficient = false;

	switch (vif->type) {
	case NL80211_IFTYPE_STATION:
		rcu_read_lock();
		sta = ieee80211_find_sta(vif, bss_conf->bssid);
		if (sta) {
			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
			int maxstreams;

			maxstreams = (ht_cap->mcs.tx_params &
			      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
				>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
			maxstreams += 1;

2257 2258
			if (ht_cap->mcs.rx_mask[1] == 0 &&
			    ht_cap->mcs.rx_mask[2] == 0)
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
				ht_conf->single_chain_sufficient = true;
			if (maxstreams <= 1)
				ht_conf->single_chain_sufficient = true;
		} else {
			/*
			 * If at all, this can only happen through a race
			 * when the AP disconnects us while we're still
			 * setting up the connection, in that case mac80211
			 * will soon tell us about that.
			 */
			ht_conf->single_chain_sufficient = true;
		}
		rcu_read_unlock();
		break;
	case NL80211_IFTYPE_ADHOC:
		ht_conf->single_chain_sufficient = true;
		break;
	default:
		break;
	}

2280
	D_ASSOC("leave\n");
2281 2282
}

S
Stanislaw Gruszka 已提交
2283
static inline void il_set_no_assoc(struct il_priv *il,
2284 2285
				    struct ieee80211_vif *vif)
{
S
Stanislaw Gruszka 已提交
2286
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
2287 2288 2289 2290 2291 2292 2293 2294

	/*
	 * inform the ucode that there is no longer an
	 * association and that no more packets should be
	 * sent
	 */
	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
	ctx->staging.assoc_id = 0;
S
Stanislaw Gruszka 已提交
2295
	il_commit_rxon(il, ctx);
2296 2297
}

S
Stanislaw Gruszka 已提交
2298
static void il_beacon_update(struct ieee80211_hw *hw,
2299 2300
				  struct ieee80211_vif *vif)
{
S
Stanislaw Gruszka 已提交
2301
	struct il_priv *il = hw->priv;
2302 2303 2304 2305 2306 2307 2308
	unsigned long flags;
	__le64 timestamp;
	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);

	if (!skb)
		return;

2309
	D_MAC80211("enter\n");
2310

S
Stanislaw Gruszka 已提交
2311
	lockdep_assert_held(&il->mutex);
2312

S
Stanislaw Gruszka 已提交
2313
	if (!il->beacon_ctx) {
2314
		IL_ERR("update beacon but no beacon context!\n");
2315 2316 2317 2318
		dev_kfree_skb(skb);
		return;
	}

S
Stanislaw Gruszka 已提交
2319
	spin_lock_irqsave(&il->lock, flags);
2320

S
Stanislaw Gruszka 已提交
2321 2322
	if (il->beacon_skb)
		dev_kfree_skb(il->beacon_skb);
2323

S
Stanislaw Gruszka 已提交
2324
	il->beacon_skb = skb;
2325 2326

	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
S
Stanislaw Gruszka 已提交
2327
	il->timestamp = le64_to_cpu(timestamp);
2328

2329
	D_MAC80211("leave\n");
S
Stanislaw Gruszka 已提交
2330
	spin_unlock_irqrestore(&il->lock, flags);
2331

S
Stanislaw Gruszka 已提交
2332
	if (!il_is_ready_rf(il)) {
2333
		D_MAC80211("leave - RF not ready\n");
2334 2335 2336
		return;
	}

S
Stanislaw Gruszka 已提交
2337
	il->cfg->ops->legacy->post_associate(il);
2338 2339
}

S
Stanislaw Gruszka 已提交
2340
void il_mac_bss_info_changed(struct ieee80211_hw *hw,
2341 2342 2343 2344
				     struct ieee80211_vif *vif,
				     struct ieee80211_bss_conf *bss_conf,
				     u32 changes)
{
S
Stanislaw Gruszka 已提交
2345
	struct il_priv *il = hw->priv;
S
Stanislaw Gruszka 已提交
2346
	struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif);
2347 2348
	int ret;

S
Stanislaw Gruszka 已提交
2349
	if (WARN_ON(!il->cfg->ops->legacy))
2350 2351
		return;

2352
	D_MAC80211("changes = 0x%X\n", changes);
2353

S
Stanislaw Gruszka 已提交
2354
	mutex_lock(&il->mutex);
2355

S
Stanislaw Gruszka 已提交
2356 2357
	if (!il_is_alive(il)) {
		mutex_unlock(&il->mutex);
2358 2359 2360
		return;
	}

2361 2362 2363
	if (changes & BSS_CHANGED_QOS) {
		unsigned long flags;

S
Stanislaw Gruszka 已提交
2364
		spin_lock_irqsave(&il->lock, flags);
2365
		ctx->qos_data.qos_active = bss_conf->qos;
S
Stanislaw Gruszka 已提交
2366 2367
		il_update_qos(il, ctx);
		spin_unlock_irqrestore(&il->lock, flags);
2368 2369 2370 2371 2372 2373 2374 2375 2376
	}

	if (changes & BSS_CHANGED_BEACON_ENABLED) {
		/*
		 * the add_interface code must make sure we only ever
		 * have a single interface that could be beaconing at
		 * any time.
		 */
		if (vif->bss_conf.enable_beacon)
S
Stanislaw Gruszka 已提交
2377
			il->beacon_ctx = ctx;
2378
		else
S
Stanislaw Gruszka 已提交
2379
			il->beacon_ctx = NULL;
2380 2381 2382
	}

	if (changes & BSS_CHANGED_BSSID) {
2383
		D_MAC80211("BSSID %pM\n", bss_conf->bssid);
2384 2385 2386 2387 2388 2389

		/*
		 * If there is currently a HW scan going on in the
		 * background then we need to cancel it else the RXON
		 * below/in post_associate will fail.
		 */
S
Stanislaw Gruszka 已提交
2390
		if (il_scan_cancel_timeout(il, 100)) {
2391
			IL_WARN(
2392
				"Aborted scan still in progress after 100ms\n");
2393
			D_MAC80211(
2394
				"leaving - scan abort failed.\n");
S
Stanislaw Gruszka 已提交
2395
			mutex_unlock(&il->mutex);
2396 2397 2398 2399 2400 2401 2402 2403 2404
			return;
		}

		/* mac80211 only sets assoc when in STATION mode */
		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
			memcpy(ctx->staging.bssid_addr,
			       bss_conf->bssid, ETH_ALEN);

			/* currently needed in a few places */
S
Stanislaw Gruszka 已提交
2405
			memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417
		} else {
			ctx->staging.filter_flags &=
				~RXON_FILTER_ASSOC_MSK;
		}

	}

	/*
	 * This needs to be after setting the BSSID in case
	 * mac80211 decides to do both changes at once because
	 * it will invoke post_associate.
	 */
2418
	if (vif->type == NL80211_IFTYPE_ADHOC && (changes & BSS_CHANGED_BEACON))
S
Stanislaw Gruszka 已提交
2419
		il_beacon_update(hw, vif);
2420 2421

	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
2422
		D_MAC80211("ERP_PREAMBLE %d\n",
2423 2424 2425 2426 2427 2428 2429 2430
				   bss_conf->use_short_preamble);
		if (bss_conf->use_short_preamble)
			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
		else
			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
	}

	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
2431
		D_MAC80211(
2432
			"ERP_CTS %d\n", bss_conf->use_cts_prot);
2433
		if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ)
2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
		else
			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
		if (bss_conf->use_cts_prot)
			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
		else
			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
	}

	if (changes & BSS_CHANGED_BASIC_RATES) {
		/* XXX use this information
		 *
S
Stanislaw Gruszka 已提交
2446
		 * To do that, remove code from il_set_rate() and put something
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460
		 * like this here:
		 *
		if (A-band)
			ctx->staging.ofdm_basic_rates =
				bss_conf->basic_rates;
		else
			ctx->staging.ofdm_basic_rates =
				bss_conf->basic_rates >> 4;
			ctx->staging.cck_basic_rates =
				bss_conf->basic_rates & 0xF;
		 */
	}

	if (changes & BSS_CHANGED_HT) {
S
Stanislaw Gruszka 已提交
2461
		il_ht_conf(il, vif);
2462

S
Stanislaw Gruszka 已提交
2463 2464
		if (il->cfg->ops->hcmd->set_rxon_chain)
			il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
2465 2466 2467
	}

	if (changes & BSS_CHANGED_ASSOC) {
2468
		D_MAC80211("ASSOC %d\n", bss_conf->assoc);
2469
		if (bss_conf->assoc) {
S
Stanislaw Gruszka 已提交
2470
			il->timestamp = bss_conf->timestamp;
2471

S
Stanislaw Gruszka 已提交
2472 2473
			if (!il_is_rfkill(il))
				il->cfg->ops->legacy->post_associate(il);
2474
		} else
S
Stanislaw Gruszka 已提交
2475
			il_set_no_assoc(il, vif);
2476 2477
	}

S
Stanislaw Gruszka 已提交
2478
	if (changes && il_is_associated_ctx(ctx) && bss_conf->aid) {
2479
		D_MAC80211("Changes (%#x) while associated\n",
2480
				   changes);
S
Stanislaw Gruszka 已提交
2481
		ret = il_send_rxon_assoc(il, ctx);
2482 2483 2484 2485
		if (!ret) {
			/* Sync active_rxon with latest change. */
			memcpy((void *)&ctx->active,
				&ctx->staging,
S
Stanislaw Gruszka 已提交
2486
				sizeof(struct il_rxon_cmd));
2487 2488 2489 2490 2491 2492 2493
		}
	}

	if (changes & BSS_CHANGED_BEACON_ENABLED) {
		if (vif->bss_conf.enable_beacon) {
			memcpy(ctx->staging.bssid_addr,
			       bss_conf->bssid, ETH_ALEN);
S
Stanislaw Gruszka 已提交
2494 2495
			memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
			il->cfg->ops->legacy->config_ap(il);
2496
		} else
S
Stanislaw Gruszka 已提交
2497
			il_set_no_assoc(il, vif);
2498 2499 2500
	}

	if (changes & BSS_CHANGED_IBSS) {
S
Stanislaw Gruszka 已提交
2501
		ret = il->cfg->ops->legacy->manage_ibss_station(il, vif,
2502 2503
							bss_conf->ibss_joined);
		if (ret)
2504
			IL_ERR("failed to %s IBSS station %pM\n",
2505 2506 2507 2508
				bss_conf->ibss_joined ? "add" : "remove",
				bss_conf->bssid);
	}

S
Stanislaw Gruszka 已提交
2509
	mutex_unlock(&il->mutex);
2510

2511
	D_MAC80211("leave\n");
2512
}
S
Stanislaw Gruszka 已提交
2513
EXPORT_SYMBOL(il_mac_bss_info_changed);
2514

S
Stanislaw Gruszka 已提交
2515
irqreturn_t il_isr(int irq, void *data)
2516
{
S
Stanislaw Gruszka 已提交
2517
	struct il_priv *il = data;
2518 2519 2520
	u32 inta, inta_mask;
	u32 inta_fh;
	unsigned long flags;
S
Stanislaw Gruszka 已提交
2521
	if (!il)
2522 2523
		return IRQ_NONE;

S
Stanislaw Gruszka 已提交
2524
	spin_lock_irqsave(&il->lock, flags);
2525 2526 2527 2528 2529

	/* Disable (but don't clear!) interrupts here to avoid
	 *    back-to-back ISRs and sporadic interrupts from our NIC.
	 * If we have something to service, the tasklet will re-enable ints.
	 * If we *don't* have something, we'll re-enable before leaving here. */
2530 2531
	inta_mask = _il_rd(il, CSR_INT_MASK);  /* just for debug */
	_il_wr(il, CSR_INT_MASK, 0x00000000);
2532 2533

	/* Discover which interrupts are active/pending */
2534 2535
	inta = _il_rd(il, CSR_INT);
	inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
2536 2537 2538 2539 2540

	/* Ignore interrupt if there's nothing in NIC to service.
	 * This may be due to IRQ shared with another device,
	 * or due to sporadic interrupts thrown from our NIC. */
	if (!inta && !inta_fh) {
2541
		D_ISR(
2542 2543 2544 2545
			"Ignore interrupt, inta == 0, inta_fh == 0\n");
		goto none;
	}

2546
	if (inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0) {
2547 2548
		/* Hardware disappeared. It might have already raised
		 * an interrupt */
2549
		IL_WARN("HARDWARE GONE?? INTA == 0x%08x\n", inta);
2550 2551 2552
		goto unplugged;
	}

2553
	D_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
2554 2555 2556 2557
		      inta, inta_mask, inta_fh);

	inta &= ~CSR_INT_BIT_SCD;

S
Stanislaw Gruszka 已提交
2558
	/* il_irq_tasklet() will service interrupts and re-enable them */
2559
	if (likely(inta || inta_fh))
S
Stanislaw Gruszka 已提交
2560
		tasklet_schedule(&il->irq_tasklet);
2561 2562

unplugged:
S
Stanislaw Gruszka 已提交
2563
	spin_unlock_irqrestore(&il->lock, flags);
2564 2565 2566 2567
	return IRQ_HANDLED;

none:
	/* re-enable interrupts here since we don't have anything to service. */
2568
	/* only Re-enable if disabled by irq */
S
Stanislaw Gruszka 已提交
2569
	if (test_bit(S_INT_ENABLED, &il->status))
S
Stanislaw Gruszka 已提交
2570 2571
		il_enable_interrupts(il);
	spin_unlock_irqrestore(&il->lock, flags);
2572 2573
	return IRQ_NONE;
}
S
Stanislaw Gruszka 已提交
2574
EXPORT_SYMBOL(il_isr);
2575 2576

/*
S
Stanislaw Gruszka 已提交
2577
 *  il_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
2578 2579
 *  function.
 */
S
Stanislaw Gruszka 已提交
2580
void il_tx_cmd_protection(struct il_priv *il,
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
			       struct ieee80211_tx_info *info,
			       __le16 fc, __le32 *tx_flags)
{
	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
		*tx_flags |= TX_CMD_FLG_RTS_MSK;
		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;

		if (!ieee80211_is_mgmt(fc))
			return;

		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
		case cpu_to_le16(IEEE80211_STYPE_AUTH):
		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
			*tx_flags |= TX_CMD_FLG_CTS_MSK;
			break;
		}
	} else if (info->control.rates[0].flags &
		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
		*tx_flags |= TX_CMD_FLG_CTS_MSK;
		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
	}
}
S
Stanislaw Gruszka 已提交
2608
EXPORT_SYMBOL(il_tx_cmd_protection);