iwl-agn.c 111.7 KB
Newer Older
Z
Zhu Yi 已提交
1 2
/******************************************************************************
 *
R
Reinette Chatre 已提交
3
 * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
Z
Zhu Yi 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * Portions of this file are derived from the ipw3945 project, as well
 * as portions of the ieee80211 subsystem header files.
 *
 * 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.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
Z
Zhu Yi 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>

#include <net/mac80211.h>

#include <asm/div64.h>

47 48
#define DRV_NAME        "iwlagn"

A
Assaf Krauss 已提交
49
#include "iwl-eeprom.h"
50
#include "iwl-dev.h"
51
#include "iwl-core.h"
52
#include "iwl-io.h"
Z
Zhu Yi 已提交
53
#include "iwl-helpers.h"
54
#include "iwl-sta.h"
55
#include "iwl-calib.h"
Z
Zhu Yi 已提交
56

57

Z
Zhu Yi 已提交
58 59 60 61 62 63 64 65 66
/******************************************************************************
 *
 * module boiler plate
 *
 ******************************************************************************/

/*
 * module name, copyright, version, etc.
 */
67
#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link AGN driver for Linux"
Z
Zhu Yi 已提交
68

69
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
70 71 72 73 74
#define VD "d"
#else
#define VD
#endif

T
Tomas Winkler 已提交
75
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
76 77 78 79 80
#define VS "s"
#else
#define VS
#endif

T
Tomas Winkler 已提交
81
#define DRV_VERSION     IWLWIFI_VERSION VD VS
Z
Zhu Yi 已提交
82 83 84 85


MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
86
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
Z
Zhu Yi 已提交
87
MODULE_LICENSE("GPL");
T
Tomas Winkler 已提交
88
MODULE_ALIAS("iwl4965");
Z
Zhu Yi 已提交
89 90

/*************** STATION TABLE MANAGEMENT ****
91
 * mac80211 should be examined to determine if sta_info is duplicating
Z
Zhu Yi 已提交
92 93 94 95 96 97 98
 * the functionality provided here
 */

/**************************************************************/



99
static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
100
{
G
Gregory Greenman 已提交
101
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
102 103 104 105 106 107 108 109

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

}

Z
Zhu Yi 已提交
110
/**
111
 * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
112
 * @priv: staging_rxon is compared to active_rxon
Z
Zhu Yi 已提交
113
 *
114 115 116
 * 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.
Z
Zhu Yi 已提交
117
 */
118
static int iwl_full_rxon_required(struct iwl_priv *priv)
Z
Zhu Yi 已提交
119 120 121
{

	/* These items are only settable from the full RXON command */
122
	if (!(iwl_is_associated(priv)) ||
Z
Zhu Yi 已提交
123 124 125 126 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 153 154 155 156 157
	    compare_ether_addr(priv->staging_rxon.bssid_addr,
			       priv->active_rxon.bssid_addr) ||
	    compare_ether_addr(priv->staging_rxon.node_addr,
			       priv->active_rxon.node_addr) ||
	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
			       priv->active_rxon.wlap_bssid_addr) ||
	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
	    (priv->staging_rxon.air_propagation !=
	     priv->active_rxon.air_propagation) ||
	    (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
		return 1;

	/* 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 */
	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
		return 1;

	/* Check if we are switching association toggle */
	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
		return 1;

	return 0;
}

/**
158
 * iwl_commit_rxon - commit staging_rxon to hardware
Z
Zhu Yi 已提交
159
 *
160
 * The RXON command in staging_rxon is committed to the hardware and
Z
Zhu Yi 已提交
161 162 163 164
 * the active_rxon structure is updated with the new data.  This
 * function correctly transitions out of the RXON_ASSOC_MSK state if
 * a HW tune is required based on the RXON structure changes.
 */
165
static int iwl_commit_rxon(struct iwl_priv *priv)
Z
Zhu Yi 已提交
166 167
{
	/* cast away the const for active_rxon in this function */
G
Gregory Greenman 已提交
168
	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
169 170 171
	int ret;
	bool new_assoc =
		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
Z
Zhu Yi 已提交
172

173
	if (!iwl_is_alive(priv))
174
		return -EBUSY;
Z
Zhu Yi 已提交
175 176 177

	/* always get timestamp with Rx frame */
	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
178 179 180
	/* allow CTS-to-self if possible. this is relevant only for
	 * 5000, but will not damage 4965 */
	priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
Z
Zhu Yi 已提交
181

182
	ret = iwl_agn_check_rxon_cmd(priv);
183
	if (ret) {
184
		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
Z
Zhu Yi 已提交
185 186 187 188
		return -EINVAL;
	}

	/* If we don't need to send a full RXON, we can use
189
	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
Z
Zhu Yi 已提交
190
	 * and other flags for the current radio configuration. */
191
	if (!iwl_full_rxon_required(priv)) {
192 193
		ret = iwl_send_rxon_assoc(priv);
		if (ret) {
194
			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
195
			return ret;
Z
Zhu Yi 已提交
196 197 198 199 200 201 202 203 204 205 206 207 208
		}

		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
		return 0;
	}

	/* station table will be cleared */
	priv->assoc_station_added = 0;

	/* If we are currently associated and the new config requires
	 * an RXON_ASSOC and the new config wants the associated mask enabled,
	 * we must clear the associated from the active configuration
	 * before we apply the new config */
209
	if (iwl_is_associated(priv) && new_assoc) {
Z
Zhu Yi 已提交
210 211 212
		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

213
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
G
Gregory Greenman 已提交
214
				      sizeof(struct iwl_rxon_cmd),
Z
Zhu Yi 已提交
215 216 217 218
				      &priv->active_rxon);

		/* If the mask clearing failed then we set
		 * active_rxon back to what it was previously */
219
		if (ret) {
Z
Zhu Yi 已提交
220
			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
221
			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
222
			return ret;
Z
Zhu Yi 已提交
223 224 225 226 227 228
		}
	}

	IWL_DEBUG_INFO("Sending RXON\n"
		       "* with%s RXON_FILTER_ASSOC_MSK\n"
		       "* channel = %d\n"
J
Johannes Berg 已提交
229
		       "* bssid = %pM\n",
230
		       (new_assoc ? "" : "out"),
Z
Zhu Yi 已提交
231
		       le16_to_cpu(priv->staging_rxon.channel),
J
Johannes Berg 已提交
232
		       priv->staging_rxon.bssid_addr);
Z
Zhu Yi 已提交
233

234
	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
235 236 237 238 239 240 241 242

	/* Apply the new configuration
	 * RXON unassoc clears the station table in uCode, send it before
	 * we add the bcast station. If assoc bit is set, we will send RXON
	 * after having added the bcast and bssid station.
	 */
	if (!new_assoc) {
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
G
Gregory Greenman 已提交
243
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
244
		if (ret) {
245
			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
246 247 248
			return ret;
		}
		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
Z
Zhu Yi 已提交
249 250
	}

251
	iwl_clear_stations_table(priv);
252

Z
Zhu Yi 已提交
253 254 255 256
	if (!priv->error_recovering)
		priv->start_calib = 0;

	/* Add the broadcast address so we can send broadcast frames */
257
	if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
258
						IWL_INVALID_STATION) {
259
		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
Z
Zhu Yi 已提交
260 261 262 263 264
		return -EIO;
	}

	/* If we have set the ASSOC_MSK and we are in BSS mode then
	 * add the IWL_AP_ID to the station rate table */
265
	if (new_assoc) {
266
		if (priv->iw_mode == NL80211_IFTYPE_STATION) {
267 268 269
			ret = iwl_rxon_add_station(priv,
					   priv->active_rxon.bssid_addr, 1);
			if (ret == IWL_INVALID_STATION) {
270 271
				IWL_ERR(priv,
					"Error adding AP address for TX.\n");
272 273 274 275 276
				return -EIO;
			}
			priv->assoc_station_added = 1;
			if (priv->default_wep_key &&
			    iwl_send_static_wepkey_cmd(priv, 0))
277 278
				IWL_ERR(priv,
					"Could not send WEP static key.\n");
Z
Zhu Yi 已提交
279
		}
280 281 282 283 284 285 286

		/* Apply the new configuration
		 * RXON assoc doesn't clear the station table in uCode,
		 */
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
		if (ret) {
287
			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
288 289 290
			return ret;
		}
		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
Z
Zhu Yi 已提交
291 292
	}

293 294 295 296 297 298
	iwl_init_sensitivity(priv);

	/* If we issue a new RXON command which required a tune then we must
	 * send a new TXPOWER command or we won't be able to Tx any frames */
	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
	if (ret) {
299
		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
300 301 302
		return ret;
	}

Z
Zhu Yi 已提交
303 304 305
	return 0;
}

306
void iwl_update_chain_flags(struct iwl_priv *priv)
M
Mohamed Abbas 已提交
307 308
{

R
Ron Rindjunsky 已提交
309
	iwl_set_rxon_chain(priv);
310
	iwl_commit_rxon(priv);
M
Mohamed Abbas 已提交
311 312
}

313
static int iwl_send_bt_config(struct iwl_priv *priv)
Z
Zhu Yi 已提交
314
{
315
	struct iwl_bt_cmd bt_cmd = {
Z
Zhu Yi 已提交
316 317 318 319 320 321 322
		.flags = 3,
		.lead_time = 0xAA,
		.max_kill = 1,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

323
	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
324
				sizeof(struct iwl_bt_cmd), &bt_cmd);
Z
Zhu Yi 已提交
325 326
}

327
static void iwl_clear_free_frames(struct iwl_priv *priv)
Z
Zhu Yi 已提交
328 329 330 331 332 333 334 335 336
{
	struct list_head *element;

	IWL_DEBUG_INFO("%d frames on pre-allocated heap on clear.\n",
		       priv->frames_count);

	while (!list_empty(&priv->free_frames)) {
		element = priv->free_frames.next;
		list_del(element);
337
		kfree(list_entry(element, struct iwl_frame, list));
Z
Zhu Yi 已提交
338 339 340 341
		priv->frames_count--;
	}

	if (priv->frames_count) {
342
		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
Z
Zhu Yi 已提交
343 344 345 346 347
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

348
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
Z
Zhu Yi 已提交
349
{
350
	struct iwl_frame *frame;
Z
Zhu Yi 已提交
351 352 353 354
	struct list_head *element;
	if (list_empty(&priv->free_frames)) {
		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
		if (!frame) {
355
			IWL_ERR(priv, "Could not allocate frame!\n");
Z
Zhu Yi 已提交
356 357 358 359 360 361 362 363 364
			return NULL;
		}

		priv->frames_count++;
		return frame;
	}

	element = priv->free_frames.next;
	list_del(element);
365
	return list_entry(element, struct iwl_frame, list);
Z
Zhu Yi 已提交
366 367
}

368
static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
Z
Zhu Yi 已提交
369 370 371 372 373
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

374 375
static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
					  struct ieee80211_hdr *hdr,
376
					  int left)
Z
Zhu Yi 已提交
377
{
378
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
379 380
	    ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
	     (priv->iw_mode != NL80211_IFTYPE_AP)))
Z
Zhu Yi 已提交
381 382 383 384 385 386 387 388 389 390
		return 0;

	if (priv->ibss_beacon->len > left)
		return 0;

	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);

	return priv->ibss_beacon->len;
}

391
static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
Z
Zhu Yi 已提交
392
{
G
Guy Cohen 已提交
393 394 395 396 397
	int i;
	int rate_mask;

	/* Set rate mask*/
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
398
		rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
G
Guy Cohen 已提交
399
	else
400
		rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
Z
Zhu Yi 已提交
401

G
Guy Cohen 已提交
402
	/* Find lowest valid rate */
Z
Zhu Yi 已提交
403
	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
404
					i = iwl_rates[i].next_ieee) {
Z
Zhu Yi 已提交
405
		if (rate_mask & (1 << i))
406
			return iwl_rates[i].plcp;
Z
Zhu Yi 已提交
407 408
	}

G
Guy Cohen 已提交
409 410 411 412 413
	/* No valid rate was found. Assign the lowest one */
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
		return IWL_RATE_1M_PLCP;
	else
		return IWL_RATE_6M_PLCP;
Z
Zhu Yi 已提交
414 415
}

416
static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
				       struct iwl_frame *frame, u8 rate)
{
	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
	unsigned int frame_size;

	tx_beacon_cmd = &frame->u.beacon;
	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));

	tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

	frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
				sizeof(frame->u) - sizeof(*tx_beacon_cmd));

	BUG_ON(frame_size > MAX_MPDU_SIZE);
	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);

	if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
		tx_beacon_cmd->tx.rate_n_flags =
			iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
	else
		tx_beacon_cmd->tx.rate_n_flags =
			iwl_hw_set_rate_n_flags(rate, 0);

	tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
				     TX_CMD_FLG_TSF_MSK |
				     TX_CMD_FLG_STA_RATE_MSK;

	return sizeof(*tx_beacon_cmd) + frame_size;
}
447
static int iwl_send_beacon_cmd(struct iwl_priv *priv)
Z
Zhu Yi 已提交
448
{
449
	struct iwl_frame *frame;
Z
Zhu Yi 已提交
450 451 452 453
	unsigned int frame_size;
	int rc;
	u8 rate;

454
	frame = iwl_get_free_frame(priv);
Z
Zhu Yi 已提交
455 456

	if (!frame) {
457
		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
Z
Zhu Yi 已提交
458 459 460 461
			  "command.\n");
		return -ENOMEM;
	}

462
	rate = iwl_rate_get_lowest_plcp(priv);
Z
Zhu Yi 已提交
463

464
	frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
Z
Zhu Yi 已提交
465

466
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
Z
Zhu Yi 已提交
467 468
			      &frame->u.cmd[0]);

469
	iwl_free_frame(priv, frame);
Z
Zhu Yi 已提交
470 471 472 473 474 475 476 477 478 479

	return rc;
}

/******************************************************************************
 *
 * Misc. internal state and helper functions
 *
 ******************************************************************************/

480
static void iwl_ht_conf(struct iwl_priv *priv,
481 482
			    struct ieee80211_bss_conf *bss_conf)
{
J
Johannes Berg 已提交
483
	struct ieee80211_sta_ht_cap *ht_conf;
484
	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
J
Johannes Berg 已提交
485
	struct ieee80211_sta *sta;
486 487 488 489 490 491

	IWL_DEBUG_MAC80211("enter: \n");

	if (!iwl_conf->is_ht)
		return;

J
Johannes Berg 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

	/*
	 * It is totally wrong to base global information on something
	 * that is valid only when associated, alas, this driver works
	 * that way and I don't know how to fix it.
	 */

	rcu_read_lock();
	sta = ieee80211_find_sta(priv->hw, priv->bssid);
	if (!sta) {
		rcu_read_unlock();
		return;
	}
	ht_conf = &sta->ht_cap;

507
	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
508
		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
509
	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
510
		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
511 512 513 514 515 516

	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
	iwl_conf->max_amsdu_size =
		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);

	iwl_conf->supported_chan_width =
J
Johannes Berg 已提交
517
		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
J
Johannes Berg 已提交
518

S
Sujith 已提交
519 520 521 522 523 524
	/*
	 * XXX: The HT configuration needs to be moved into iwl_mac_config()
	 *	to be done there correctly.
	 */

	iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
525
	if (conf_is_ht40_minus(&priv->hw->conf))
S
Sujith 已提交
526
		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
527
	else if (conf_is_ht40_plus(&priv->hw->conf))
S
Sujith 已提交
528 529
		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;

530
	/* If no above or below channel supplied disable FAT channel */
J
Johannes Berg 已提交
531
	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
S
Sujith 已提交
532
	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
533 534
		iwl_conf->supported_chan_width = 0;

535 536
	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);

J
Johannes Berg 已提交
537
	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
538

S
Sujith 已提交
539
	iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
540
	iwl_conf->ht_protection =
J
Johannes Berg 已提交
541
		bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
542
	iwl_conf->non_GF_STA_present =
J
Johannes Berg 已提交
543 544 545
		!!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);

	rcu_read_unlock();
546 547 548 549

	IWL_DEBUG_MAC80211("leave\n");
}

Z
Zhu Yi 已提交
550 551 552
/*
 * QoS  support
*/
553
static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
Z
Zhu Yi 已提交
554 555 556 557 558 559 560 561 562 563 564 565 566 567
{
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	priv->qos_data.def_qos_parm.qos_flags = 0;

	if (priv->qos_data.qos_cap.q_AP.queue_request &&
	    !priv->qos_data.qos_cap.q_AP.txop_request)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_TXOP_TYPE_MSK;
	if (priv->qos_data.qos_active)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_UPDATE_EDCA_MSK;

568
	if (priv->current_ht_config.is_ht)
569 570
		priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;

571
	if (force || iwl_is_associated(priv)) {
572 573 574
		IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
				priv->qos_data.qos_active,
				priv->qos_data.def_qos_parm.qos_flags);
Z
Zhu Yi 已提交
575

576 577 578
		iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
				       sizeof(struct iwl_qosparam_cmd),
				       &priv->qos_data.def_qos_parm, NULL);
Z
Zhu Yi 已提交
579 580 581 582 583
	}
}

#define MAX_UCODE_BEACON_INTERVAL	4096

584
static u16 iwl_adjust_beacon_interval(u16 beacon_val)
Z
Zhu Yi 已提交
585 586 587 588
{
	u16 new_val = 0;
	u16 beacon_factor = 0;

589 590
	beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL)
					/ MAX_UCODE_BEACON_INTERVAL;
Z
Zhu Yi 已提交
591 592
	new_val = beacon_val / beacon_factor;

593
	return new_val;
Z
Zhu Yi 已提交
594 595
}

596
static void iwl_setup_rxon_timing(struct iwl_priv *priv)
Z
Zhu Yi 已提交
597
{
598 599
	u64 tsf;
	s32 interval_tm, rem;
Z
Zhu Yi 已提交
600 601 602 603 604 605 606
	unsigned long flags;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int = 0;

	conf = ieee80211_get_hw_conf(priv->hw);

	spin_lock_irqsave(&priv->lock, flags);
607
	priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
608
	priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
Z
Zhu Yi 已提交
609

610
	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
611
		beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
Z
Zhu Yi 已提交
612 613
		priv->rxon_timing.atim_window = 0;
	} else {
614 615
		beacon_int = iwl_adjust_beacon_interval(conf->beacon_int);

Z
Zhu Yi 已提交
616 617 618 619 620
		/* TODO: we need to get atim_window from upper stack
		 * for now we set to 0 */
		priv->rxon_timing.atim_window = 0;
	}

621
	priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
Z
Zhu Yi 已提交
622

623 624 625 626 627 628 629 630 631 632
	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
	interval_tm = beacon_int * 1024;
	rem = do_div(tsf, interval_tm);
	priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);

	spin_unlock_irqrestore(&priv->lock, flags);
	IWL_DEBUG_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n",
			le16_to_cpu(priv->rxon_timing.beacon_interval),
			le32_to_cpu(priv->rxon_timing.beacon_init_val),
			le16_to_cpu(priv->rxon_timing.atim_window));
Z
Zhu Yi 已提交
633 634
}

635 636
static void iwl_set_flags_for_band(struct iwl_priv *priv,
				   enum ieee80211_band band)
Z
Zhu Yi 已提交
637
{
638
	if (band == IEEE80211_BAND_5GHZ) {
Z
Zhu Yi 已提交
639 640 641 642 643
		priv->staging_rxon.flags &=
		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
		      | RXON_FLG_CCK_MSK);
		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
	} else {
644
		/* Copied from iwl_post_associate() */
Z
Zhu Yi 已提交
645 646 647 648 649
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

650
		if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
Z
Zhu Yi 已提交
651 652 653 654 655 656 657 658 659
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
		priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
	}
}

/*
660
 * initialize rxon structure with default values from eeprom
Z
Zhu Yi 已提交
661
 */
662
static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
Z
Zhu Yi 已提交
663
{
664
	const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
665 666 667

	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));

668
	switch (mode) {
669
	case NL80211_IFTYPE_AP:
Z
Zhu Yi 已提交
670 671 672
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
		break;

673
	case NL80211_IFTYPE_STATION:
Z
Zhu Yi 已提交
674 675 676 677
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
		break;

678
	case NL80211_IFTYPE_ADHOC:
Z
Zhu Yi 已提交
679 680 681 682 683 684
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
						  RXON_FILTER_ACCEPT_GRP_MSK;
		break;

685
	case NL80211_IFTYPE_MONITOR:
Z
Zhu Yi 已提交
686 687 688 689
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
		break;
690
	default:
691
		IWL_ERR(priv, "Unsupported interface type %d\n", mode);
692
		break;
Z
Zhu Yi 已提交
693 694 695 696 697 698 699 700 701 702 703
	}

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

704
	ch_info = iwl_get_channel_info(priv, priv->band,
705
				       le16_to_cpu(priv->active_rxon.channel));
Z
Zhu Yi 已提交
706 707 708 709 710 711 712 713

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

	/*
	 * in some case A channels are all non IBSS
	 * in this case force B/G channel
	 */
714
	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
Z
Zhu Yi 已提交
715 716 717 718
	    !(is_channel_ibss(ch_info)))
		ch_info = &priv->channel_info[0];

	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
719
	priv->band = ch_info->band;
Z
Zhu Yi 已提交
720

721
	iwl_set_flags_for_band(priv, priv->band);
Z
Zhu Yi 已提交
722 723 724 725 726 727 728 729 730 731 732 733

	priv->staging_rxon.ofdm_basic_rates =
	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
	priv->staging_rxon.cck_basic_rates =
	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
					RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
	memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
R
Ron Rindjunsky 已提交
734
	iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
735 736
}

737
static int iwl_set_mode(struct iwl_priv *priv, int mode)
Z
Zhu Yi 已提交
738
{
739
	iwl_connection_init_rx_config(priv, mode);
Z
Zhu Yi 已提交
740 741
	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);

742
	iwl_clear_stations_table(priv);
Z
Zhu Yi 已提交
743

744
	/* dont commit rxon if rf-kill is on*/
745
	if (!iwl_is_ready_rf(priv))
746 747 748
		return -EAGAIN;

	cancel_delayed_work(&priv->scan_check);
749
	if (iwl_scan_cancel_timeout(priv, 100)) {
750
		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
751 752 753 754
		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
		return -EAGAIN;
	}

755
	iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
756 757 758 759

	return 0;
}

760
static void iwl_set_rate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
761
{
762
	const struct ieee80211_supported_band *hw = NULL;
Z
Zhu Yi 已提交
763 764 765
	struct ieee80211_rate *rate;
	int i;

766
	hw = iwl_get_hw_mode(priv, priv->band);
767
	if (!hw) {
768
		IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
769 770
		return;
	}
Z
Zhu Yi 已提交
771 772 773 774

	priv->active_rate = 0;
	priv->active_rate_basic = 0;

775 776 777 778
	for (i = 0; i < hw->n_bitrates; i++) {
		rate = &(hw->bitrates[i]);
		if (rate->hw_value < IWL_RATE_COUNT)
			priv->active_rate |= (1 << rate->hw_value);
Z
Zhu Yi 已提交
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
	}

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

	/*
	 * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
	 * otherwise set it to the default of all CCK rates and 6, 12, 24 for
	 * OFDM
	 */
	if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
		priv->staging_rxon.cck_basic_rates =
		    ((priv->active_rate_basic &
		      IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
	else
		priv->staging_rxon.cck_basic_rates =
		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;

	if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
		priv->staging_rxon.ofdm_basic_rates =
		    ((priv->active_rate_basic &
		      (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
		      IWL_FIRST_OFDM_RATE) & 0xFF;
	else
		priv->staging_rxon.ofdm_basic_rates =
		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}


/******************************************************************************
 *
 * Generic RX handler implementations
 *
 ******************************************************************************/
813 814
static void iwl_rx_reply_alive(struct iwl_priv *priv,
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
815
{
816
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
817
	struct iwl_alive_resp *palive;
Z
Zhu Yi 已提交
818 819 820 821 822 823 824 825 826 827 828 829 830
	struct delayed_work *pwork;

	palive = &pkt->u.alive_frame;

	IWL_DEBUG_INFO("Alive ucode status 0x%08X revision "
		       "0x%01X 0x%01X\n",
		       palive->is_valid, palive->ver_type,
		       palive->ver_subtype);

	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
		IWL_DEBUG_INFO("Initialization Alive received.\n");
		memcpy(&priv->card_alive_init,
		       &pkt->u.alive_frame,
831
		       sizeof(struct iwl_init_alive_resp));
Z
Zhu Yi 已提交
832 833 834 835
		pwork = &priv->init_alive_start;
	} else {
		IWL_DEBUG_INFO("Runtime Alive received.\n");
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
836
		       sizeof(struct iwl_alive_resp));
Z
Zhu Yi 已提交
837 838 839 840 841 842 843 844 845
		pwork = &priv->alive_start;
	}

	/* We delay the ALIVE response by 5ms to
	 * give the HW RF Kill time to activate... */
	if (palive->is_valid == UCODE_VALID_OK)
		queue_delayed_work(priv->workqueue, pwork,
				   msecs_to_jiffies(5));
	else
846
		IWL_WARN(priv, "uCode did not respond OK.\n");
Z
Zhu Yi 已提交
847 848
}

849
static void iwl_rx_reply_error(struct iwl_priv *priv,
850
				   struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
851
{
852
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
853

854
	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
Z
Zhu Yi 已提交
855 856 857 858 859 860 861 862 863 864
		"seq 0x%04X ser 0x%08X\n",
		le32_to_cpu(pkt->u.err_resp.error_type),
		get_cmd_string(pkt->u.err_resp.cmd_id),
		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));
}

#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x

865
static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
866
{
867
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
G
Gregory Greenman 已提交
868
	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
869
	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
Z
Zhu Yi 已提交
870 871 872 873 874 875
	IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
		      le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
	rxon->channel = csa->channel;
	priv->staging_rxon.channel = csa->channel;
}

876
static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
877
				      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
878
{
879
#ifdef CONFIG_IWLWIFI_DEBUG
880
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
881
	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
Z
Zhu Yi 已提交
882 883 884 885 886
	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}

887
static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
888
					     struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
889
{
890
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
891 892 893
	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
			"notification for %s:\n",
			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
894
	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
Z
Zhu Yi 已提交
895 896
}

897
static void iwl_bg_beacon_update(struct work_struct *work)
Z
Zhu Yi 已提交
898
{
899 900
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
Z
Zhu Yi 已提交
901 902 903
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
904
	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
Z
Zhu Yi 已提交
905 906

	if (!beacon) {
907
		IWL_ERR(priv, "update beacon failed\n");
Z
Zhu Yi 已提交
908 909 910 911 912 913 914 915 916 917 918
		return;
	}

	mutex_lock(&priv->mutex);
	/* new beacon skb is allocated every time; dispose previous.*/
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = beacon;
	mutex_unlock(&priv->mutex);

919
	iwl_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
920 921
}

922
/**
923
 * iwl_bg_statistics_periodic - Timer callback to queue statistics
924 925 926 927 928 929 930 931
 *
 * This callback is provided in order to send a statistics request.
 *
 * This timer function is continually reset to execute within
 * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
 * was received.  We need to ensure we receive the statistics in order
 * to update the temperature used for calibrating the TXPOWER.
 */
932
static void iwl_bg_statistics_periodic(unsigned long data)
933 934 935 936 937 938
{
	struct iwl_priv *priv = (struct iwl_priv *)data;

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

939 940 941 942
	/* dont send host command if rf-kill is on */
	if (!iwl_is_ready_rf(priv))
		return;

943 944 945
	iwl_send_statistics_request(priv, CMD_ASYNC);
}

946
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
947
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
948
{
949
#ifdef CONFIG_IWLWIFI_DEBUG
950
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
951 952
	struct iwl4965_beacon_notif *beacon =
		(struct iwl4965_beacon_notif *)pkt->u.raw;
953
	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
Z
Zhu Yi 已提交
954 955 956

	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
		"tsf %d %d rate %d\n",
957
		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
Z
Zhu Yi 已提交
958 959 960 961 962 963
		beacon->beacon_notify_hdr.failure_frame,
		le32_to_cpu(beacon->ibss_mgr_status),
		le32_to_cpu(beacon->high_tsf),
		le32_to_cpu(beacon->low_tsf), rate);
#endif

964
	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
Z
Zhu Yi 已提交
965 966 967 968 969 970
	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
		queue_work(priv->workqueue, &priv->beacon_update);
}

/* Handle notification from uCode that card's power state is changing
 * due to software, hardware, or critical temperature RFKILL */
971
static void iwl_rx_card_state_notif(struct iwl_priv *priv,
972
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
973
{
974
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
975 976 977 978 979 980 981 982 983 984
	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
	unsigned long status = priv->status;

	IWL_DEBUG_RF_KILL("Card state received: HW:%s SW:%s\n",
			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");

	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
		     RF_CARD_DISABLED)) {

985
		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
986 987
			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

988 989
		if (!iwl_grab_nic_access(priv)) {
			iwl_write_direct32(
Z
Zhu Yi 已提交
990 991 992
				priv, HBUS_TARG_MBX_C,
				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

993
			iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
994 995 996
		}

		if (!(flags & RXON_CARD_DISABLED)) {
997
			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
Z
Zhu Yi 已提交
998
				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
999 1000
			if (!iwl_grab_nic_access(priv)) {
				iwl_write_direct32(
Z
Zhu Yi 已提交
1001 1002 1003
					priv, HBUS_TARG_MBX_C,
					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

1004
				iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
1005 1006 1007 1008
			}
		}

		if (flags & RF_CARD_DISABLED) {
1009
			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
1010
				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
1011 1012 1013
			iwl_read32(priv, CSR_UCODE_DRV_GP1);
			if (!iwl_grab_nic_access(priv))
				iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
		}
	}

	if (flags & HW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_HW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_HW, &priv->status);


	if (flags & SW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_SW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_SW, &priv->status);

	if (!(flags & RXON_CARD_DISABLED))
1029
		iwl_scan_cancel(priv);
Z
Zhu Yi 已提交
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039

	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
	    (test_bit(STATUS_RF_KILL_SW, &status) !=
	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
		queue_work(priv->workqueue, &priv->rf_kill);
	else
		wake_up_interruptible(&priv->wait_command_queue);
}

1040
int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
{
	int ret;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
	ret = iwl_grab_nic_access(priv);
	if (ret)
		goto err;

	if (src == IWL_PWR_SRC_VAUX) {
		u32 val;
1052
		ret = pci_read_config_dword(priv->pci_dev, PCI_CFG_POWER_SOURCE,
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
					    &val);

		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
					       ~APMG_PS_CTRL_MSK_PWR_SRC);
	} else {
		iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
				       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
				       ~APMG_PS_CTRL_MSK_PWR_SRC);
	}

	iwl_release_nic_access(priv);
err:
	spin_unlock_irqrestore(&priv->lock, flags);
	return ret;
}

Z
Zhu Yi 已提交
1071
/**
1072
 * iwl_setup_rx_handlers - Initialize Rx handler callbacks
Z
Zhu Yi 已提交
1073 1074 1075 1076 1077 1078 1079
 *
 * Setup the RX handlers for each of the reply types sent from the uCode
 * to the host.
 *
 * This function chains into the hardware specific files for them to setup
 * any hardware specific handlers as well.
 */
1080
static void iwl_setup_rx_handlers(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1081
{
1082
	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
1083 1084 1085
	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
Z
Zhu Yi 已提交
1086
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
1087 1088
	    iwl_rx_pm_debug_statistics_notif;
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
Z
Zhu Yi 已提交
1089

1090 1091 1092 1093
	/*
	 * The same handler is used for both the REPLY to a discrete
	 * statistics request from the host as well as for the periodic
	 * statistics notifications (after received beacons) from the uCode.
Z
Zhu Yi 已提交
1094
	 */
1095 1096
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
1097

1098
	iwl_setup_spectrum_handlers(priv);
1099 1100
	iwl_setup_rx_scan_handlers(priv);

1101
	/* status change handler */
1102
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
Z
Zhu Yi 已提交
1103

1104 1105
	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
	    iwl_rx_missed_beacon_notif;
1106
	/* Rx handlers */
1107 1108
	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
1109 1110
	/* block ack */
	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
1111
	/* Set up hardware specific Rx handlers */
1112
	priv->cfg->ops->lib->rx_handler_setup(priv);
Z
Zhu Yi 已提交
1113 1114 1115
}

/**
1116
 * iwl_rx_handle - Main entry function for receiving responses from uCode
Z
Zhu Yi 已提交
1117 1118 1119 1120 1121
 *
 * Uses the priv->rx_handlers callback function array to invoke
 * the appropriate handlers, including command responses,
 * frame-received notifications, and other notifications.
 */
1122
void iwl_rx_handle(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1123
{
1124
	struct iwl_rx_mem_buffer *rxb;
1125
	struct iwl_rx_packet *pkt;
1126
	struct iwl_rx_queue *rxq = &priv->rxq;
Z
Zhu Yi 已提交
1127 1128 1129
	u32 r, i;
	int reclaim;
	unsigned long flags;
1130
	u8 fill_rx = 0;
M
Mohamed Abbas 已提交
1131
	u32 count = 8;
Z
Zhu Yi 已提交
1132

1133 1134
	/* uCode's read index (stored in shared DRAM) indicates the last Rx
	 * buffer that the driver may process (last buffer filled by ucode). */
1135
	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
Z
Zhu Yi 已提交
1136 1137 1138 1139
	i = rxq->read;

	/* Rx interrupt, but nothing sent from uCode */
	if (i == r)
1140
		IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d\n", r, i);
Z
Zhu Yi 已提交
1141

1142
	if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
1143 1144
		fill_rx = 1;

Z
Zhu Yi 已提交
1145 1146 1147
	while (i != r) {
		rxb = rxq->queue[i];

1148
		/* If an RXB doesn't have a Rx queue slot associated with it,
Z
Zhu Yi 已提交
1149 1150 1151 1152 1153 1154
		 * then a bug has been introduced in the queue refilling
		 * routines -- catch it here */
		BUG_ON(rxb == NULL);

		rxq->queue[i] = NULL;

J
Johannes Berg 已提交
1155 1156 1157 1158 1159
		dma_sync_single_range_for_cpu(
				&priv->pci_dev->dev, rxb->real_dma_addr,
				rxb->aligned_dma_addr - rxb->real_dma_addr,
				priv->hw_params.rx_buf_size,
				PCI_DMA_FROMDEVICE);
1160
		pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
1161 1162 1163 1164 1165 1166 1167 1168 1169

		/* Reclaim a command buffer only if this packet is a response
		 *   to a (driver-originated) command.
		 * If the packet (e.g. Rx frame) originated from uCode,
		 *   there is no command buffer to reclaim.
		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
		 *   but apparently a few don't get set; catch them here. */
		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
1170
			(pkt->hdr.cmd != REPLY_RX) &&
D
Daniel Halperin 已提交
1171
			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
1172
			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
Z
Zhu Yi 已提交
1173 1174 1175 1176 1177
			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
			(pkt->hdr.cmd != REPLY_TX);

		/* Based on type of command response or notification,
		 *   handle those that need handling via function in
1178
		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
Z
Zhu Yi 已提交
1179
		if (priv->rx_handlers[pkt->hdr.cmd]) {
1180 1181
			IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r,
				i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
Z
Zhu Yi 已提交
1182 1183 1184
			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
		} else {
			/* No handling needed */
1185
			IWL_DEBUG(IWL_DL_RX,
Z
Zhu Yi 已提交
1186 1187 1188 1189 1190 1191
				"r %d i %d No handler needed for %s, 0x%02x\n",
				r, i, get_cmd_string(pkt->hdr.cmd),
				pkt->hdr.cmd);
		}

		if (reclaim) {
1192
			/* Invoke any callbacks, transfer the skb to caller, and
1193
			 * fire off the (possibly) blocking iwl_send_cmd()
Z
Zhu Yi 已提交
1194 1195
			 * as we reclaim the driver command queue */
			if (rxb && rxb->skb)
1196
				iwl_tx_cmd_complete(priv, rxb);
Z
Zhu Yi 已提交
1197
			else
1198
				IWL_WARN(priv, "Claim null rxb?\n");
Z
Zhu Yi 已提交
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
		}

		/* For now we just don't re-use anything.  We can tweak this
		 * later to try and re-use notification packets and SKBs that
		 * fail to Rx correctly */
		if (rxb->skb != NULL) {
			priv->alloc_rxb_skb--;
			dev_kfree_skb_any(rxb->skb);
			rxb->skb = NULL;
		}

J
Johannes Berg 已提交
1210 1211
		pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
				 priv->hw_params.rx_buf_size + 256,
1212
				 PCI_DMA_FROMDEVICE);
Z
Zhu Yi 已提交
1213 1214 1215 1216
		spin_lock_irqsave(&rxq->lock, flags);
		list_add_tail(&rxb->list, &priv->rxq.rx_used);
		spin_unlock_irqrestore(&rxq->lock, flags);
		i = (i + 1) & RX_QUEUE_MASK;
1217 1218 1219 1220 1221 1222
		/* If there are a lot of unused frames,
		 * restock the Rx queue so ucode wont assert. */
		if (fill_rx) {
			count++;
			if (count >= 8) {
				priv->rxq.read = i;
1223
				iwl_rx_queue_restock(priv);
1224 1225 1226
				count = 0;
			}
		}
Z
Zhu Yi 已提交
1227 1228 1229 1230
	}

	/* Backtrack one entry */
	priv->rxq.read = i;
1231 1232 1233
	iwl_rx_queue_restock(priv);
}

1234
#ifdef CONFIG_IWLWIFI_DEBUG
1235
static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1236
{
G
Gregory Greenman 已提交
1237
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
1238

Z
Zhu Yi 已提交
1239
	IWL_DEBUG_RADIO("RX CONFIG:\n");
1240
	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
Z
Zhu Yi 已提交
1241 1242 1243 1244 1245 1246 1247 1248
	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
	IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
	IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
			le32_to_cpu(rxon->filter_flags));
	IWL_DEBUG_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type);
	IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
			rxon->ofdm_basic_rates);
	IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
J
Johannes Berg 已提交
1249 1250
	IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
	IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
Z
Zhu Yi 已提交
1251 1252 1253 1254
	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif

1255 1256 1257
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
T
Tomas Winkler 已提交
1258
	/* wait to make sure we flush pending tasklet*/
1259 1260 1261 1262
	synchronize_irq(priv->pci_dev->irq);
	tasklet_kill(&priv->irq_tasklet);
}

Z
Zhu Yi 已提交
1263
/**
1264
 * iwl_irq_handle_error - called for HW or SW error interrupt from card
Z
Zhu Yi 已提交
1265
 */
1266
static void iwl_irq_handle_error(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1267
{
1268
	/* Set the FW error flag -- cleared on iwl_down */
Z
Zhu Yi 已提交
1269 1270 1271 1272 1273
	set_bit(STATUS_FW_ERROR, &priv->status);

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

1274
#ifdef CONFIG_IWLWIFI_DEBUG
1275
	if (priv->debug_level & IWL_DL_FW_ERRORS) {
1276
		iwl_dump_nic_error_log(priv);
1277
		iwl_dump_nic_event_log(priv);
1278
		iwl_print_rx_config_cmd(priv);
Z
Zhu Yi 已提交
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
	}
#endif

	wake_up_interruptible(&priv->wait_command_queue);

	/* Keep the restart process from trying to send host
	 * commands by clearing the INIT status bit */
	clear_bit(STATUS_READY, &priv->status);

	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
1289
		IWL_DEBUG(IWL_DL_FW_ERRORS,
Z
Zhu Yi 已提交
1290 1291
			  "Restarting adapter due to uCode error.\n");

1292
		if (iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
1293 1294 1295 1296
			memcpy(&priv->recovery_rxon, &priv->active_rxon,
			       sizeof(priv->recovery_rxon));
			priv->error_recovering = 1;
		}
1297 1298
		if (priv->cfg->mod_params->restart_fw)
			queue_work(priv->workqueue, &priv->restart);
Z
Zhu Yi 已提交
1299 1300 1301
	}
}

1302
static void iwl_error_recovery(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1303 1304 1305 1306 1307 1308
{
	unsigned long flags;

	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
	       sizeof(priv->staging_rxon));
	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
1309
	iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
1310

1311
	iwl_rxon_add_station(priv, priv->bssid, 1);
Z
Zhu Yi 已提交
1312 1313 1314 1315 1316 1317 1318

	spin_lock_irqsave(&priv->lock, flags);
	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
	priv->error_recovering = 0;
	spin_unlock_irqrestore(&priv->lock, flags);
}

1319
static void iwl_irq_tasklet(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1320 1321 1322 1323
{
	u32 inta, handled = 0;
	u32 inta_fh;
	unsigned long flags;
1324
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
1325 1326 1327 1328 1329 1330 1331 1332
	u32 inta_mask;
#endif

	spin_lock_irqsave(&priv->lock, flags);

	/* Ack/clear/reset pending uCode interrupts.
	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
1333 1334
	inta = iwl_read32(priv, CSR_INT);
	iwl_write32(priv, CSR_INT, inta);
Z
Zhu Yi 已提交
1335 1336 1337 1338

	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
	 * Any new interrupts that happen after this, either while we're
	 * in this tasklet, or later, will show up in next ISR/tasklet. */
1339 1340
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
Z
Zhu Yi 已提交
1341

1342
#ifdef CONFIG_IWLWIFI_DEBUG
1343
	if (priv->debug_level & IWL_DL_ISR) {
1344
		/* just for debug */
1345
		inta_mask = iwl_read32(priv, CSR_INT_MASK);
Z
Zhu Yi 已提交
1346 1347 1348 1349 1350 1351 1352 1353 1354
		IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
			      inta, inta_mask, inta_fh);
	}
#endif

	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
	 * atomic, make sure that inta covers all the interrupts that
	 * we've discovered, even if FH interrupt came in just after
	 * reading CSR_INT. */
T
Tomas Winkler 已提交
1355
	if (inta_fh & CSR49_FH_INT_RX_MASK)
Z
Zhu Yi 已提交
1356
		inta |= CSR_INT_BIT_FH_RX;
T
Tomas Winkler 已提交
1357
	if (inta_fh & CSR49_FH_INT_TX_MASK)
Z
Zhu Yi 已提交
1358 1359 1360 1361
		inta |= CSR_INT_BIT_FH_TX;

	/* Now service all interrupt bits discovered above. */
	if (inta & CSR_INT_BIT_HW_ERR) {
1362
		IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
Z
Zhu Yi 已提交
1363 1364

		/* Tell the device to stop sending interrupts */
1365
		iwl_disable_interrupts(priv);
Z
Zhu Yi 已提交
1366

1367
		iwl_irq_handle_error(priv);
Z
Zhu Yi 已提交
1368 1369 1370 1371 1372 1373 1374 1375

		handled |= CSR_INT_BIT_HW_ERR;

		spin_unlock_irqrestore(&priv->lock, flags);

		return;
	}

1376
#ifdef CONFIG_IWLWIFI_DEBUG
1377
	if (priv->debug_level & (IWL_DL_ISR)) {
Z
Zhu Yi 已提交
1378
		/* NIC fires this, but we don't use it, redundant with WAKEUP */
1379 1380 1381
		if (inta & CSR_INT_BIT_SCD)
			IWL_DEBUG_ISR("Scheduler finished to transmit "
				      "the frame/frames.\n");
Z
Zhu Yi 已提交
1382 1383 1384 1385 1386 1387 1388

		/* Alive notification via Rx interrupt will do the real work */
		if (inta & CSR_INT_BIT_ALIVE)
			IWL_DEBUG_ISR("Alive interrupt\n");
	}
#endif
	/* Safely ignore these bits for debug checks below */
1389
	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
Z
Zhu Yi 已提交
1390

1391
	/* HW RF KILL switch toggled */
Z
Zhu Yi 已提交
1392 1393
	if (inta & CSR_INT_BIT_RF_KILL) {
		int hw_rf_kill = 0;
1394
		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
Z
Zhu Yi 已提交
1395 1396 1397
				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
			hw_rf_kill = 1;

1398
		IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
1399
				hw_rf_kill ? "disable radio" : "enable radio");
Z
Zhu Yi 已提交
1400

1401 1402 1403 1404
		/* driver only loads ucode once setting the interface up.
		 * the driver as well won't allow loading if RFKILL is set
		 * therefore no need to restart the driver from this handler
		 */
1405
		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
1406
			clear_bit(STATUS_RF_KILL_HW, &priv->status);
1407 1408 1409
			if (priv->is_open && !iwl_is_rfkill(priv))
				queue_work(priv->workqueue, &priv->up);
		}
Z
Zhu Yi 已提交
1410 1411 1412 1413

		handled |= CSR_INT_BIT_RF_KILL;
	}

1414
	/* Chip got too hot and stopped itself */
Z
Zhu Yi 已提交
1415
	if (inta & CSR_INT_BIT_CT_KILL) {
1416
		IWL_ERR(priv, "Microcode CT kill error detected.\n");
Z
Zhu Yi 已提交
1417 1418 1419 1420 1421
		handled |= CSR_INT_BIT_CT_KILL;
	}

	/* Error detected by uCode */
	if (inta & CSR_INT_BIT_SW_ERR) {
1422 1423
		IWL_ERR(priv, "Microcode SW error detected. "
			" Restarting 0x%X.\n", inta);
1424
		iwl_irq_handle_error(priv);
Z
Zhu Yi 已提交
1425 1426 1427 1428 1429 1430
		handled |= CSR_INT_BIT_SW_ERR;
	}

	/* uCode wakes up after power-down sleep */
	if (inta & CSR_INT_BIT_WAKEUP) {
		IWL_DEBUG_ISR("Wakeup interrupt\n");
1431
		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
1432 1433 1434 1435 1436 1437
		iwl_txq_update_write_ptr(priv, &priv->txq[0]);
		iwl_txq_update_write_ptr(priv, &priv->txq[1]);
		iwl_txq_update_write_ptr(priv, &priv->txq[2]);
		iwl_txq_update_write_ptr(priv, &priv->txq[3]);
		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
Z
Zhu Yi 已提交
1438 1439 1440 1441 1442 1443 1444 1445

		handled |= CSR_INT_BIT_WAKEUP;
	}

	/* All uCode command responses, including Tx command responses,
	 * Rx "responses" (frame-received notification), and other
	 * notifications from uCode come through here*/
	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
1446
		iwl_rx_handle(priv);
Z
Zhu Yi 已提交
1447 1448 1449 1450 1451 1452
		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
	}

	if (inta & CSR_INT_BIT_FH_TX) {
		IWL_DEBUG_ISR("Tx interrupt\n");
		handled |= CSR_INT_BIT_FH_TX;
1453 1454 1455
		/* FH finished to write, send event */
		priv->ucode_write_complete = 1;
		wake_up_interruptible(&priv->wait_command_queue);
Z
Zhu Yi 已提交
1456 1457 1458
	}

	if (inta & ~handled)
1459
		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
Z
Zhu Yi 已提交
1460 1461

	if (inta & ~CSR_INI_SET_MASK) {
1462
		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
Z
Zhu Yi 已提交
1463
			 inta & ~CSR_INI_SET_MASK);
1464
		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
Z
Zhu Yi 已提交
1465 1466 1467
	}

	/* Re-enable all interrupts */
1468 1469
	/* only Re-enable if diabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
1470
		iwl_enable_interrupts(priv);
Z
Zhu Yi 已提交
1471

1472
#ifdef CONFIG_IWLWIFI_DEBUG
1473
	if (priv->debug_level & (IWL_DL_ISR)) {
1474 1475 1476
		inta = iwl_read32(priv, CSR_INT);
		inta_mask = iwl_read32(priv, CSR_INT_MASK);
		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
Z
Zhu Yi 已提交
1477 1478 1479 1480 1481 1482 1483
		IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
	}
#endif
	spin_unlock_irqrestore(&priv->lock, flags);
}

1484
static irqreturn_t iwl_isr(int irq, void *data)
Z
Zhu Yi 已提交
1485
{
1486
	struct iwl_priv *priv = data;
Z
Zhu Yi 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
	u32 inta, inta_mask;
	u32 inta_fh;
	if (!priv)
		return IRQ_NONE;

	spin_lock(&priv->lock);

	/* 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. */
1498 1499
	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
Z
Zhu Yi 已提交
1500 1501

	/* Discover which interrupts are active/pending */
1502 1503
	inta = iwl_read32(priv, CSR_INT);
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
Z
Zhu Yi 已提交
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513

	/* 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) {
		IWL_DEBUG_ISR("Ignore interrupt, inta == 0, inta_fh == 0\n");
		goto none;
	}

	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
1514 1515
		/* Hardware disappeared. It might have already raised
		 * an interrupt */
1516
		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
1517
		goto unplugged;
Z
Zhu Yi 已提交
1518 1519 1520 1521 1522
	}

	IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
		      inta, inta_mask, inta_fh);

1523 1524
	inta &= ~CSR_INT_BIT_SCD;

1525
	/* iwl_irq_tasklet() will service interrupts and re-enable them */
1526 1527
	if (likely(inta || inta_fh))
		tasklet_schedule(&priv->irq_tasklet);
Z
Zhu Yi 已提交
1528

1529 1530
 unplugged:
	spin_unlock(&priv->lock);
Z
Zhu Yi 已提交
1531 1532 1533 1534
	return IRQ_HANDLED;

 none:
	/* re-enable interrupts here since we don't have anything to service. */
1535 1536
	/* only Re-enable if diabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
1537
		iwl_enable_interrupts(priv);
Z
Zhu Yi 已提交
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547
	spin_unlock(&priv->lock);
	return IRQ_NONE;
}

/******************************************************************************
 *
 * uCode download functions
 *
 ******************************************************************************/

1548
static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1549
{
1550 1551 1552 1553 1554 1555
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
Z
Zhu Yi 已提交
1556 1557
}

1558
static void iwl_nic_start(struct iwl_priv *priv)
1559 1560 1561 1562 1563 1564
{
	/* Remove all resets to allow NIC to operate */
	iwl_write32(priv, CSR_RESET, 0);
}


Z
Zhu Yi 已提交
1565
/**
1566
 * iwl_read_ucode - Read uCode images from disk file.
Z
Zhu Yi 已提交
1567 1568 1569
 *
 * Copy into buffers for card to fetch via bus-mastering
 */
1570
static int iwl_read_ucode(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1571
{
1572
	struct iwl_ucode *ucode;
1573
	int ret = -EINVAL, index;
Z
Zhu Yi 已提交
1574
	const struct firmware *ucode_raw;
1575 1576 1577 1578
	const char *name_pre = priv->cfg->fw_name_pre;
	const unsigned int api_max = priv->cfg->ucode_api_max;
	const unsigned int api_min = priv->cfg->ucode_api_min;
	char buf[25];
Z
Zhu Yi 已提交
1579 1580
	u8 *src;
	size_t len;
1581
	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
Z
Zhu Yi 已提交
1582 1583 1584

	/* Ask kernel firmware_class module to get the boot firmware off disk.
	 * request_firmware() is synchronous, file is in memory on return. */
1585 1586 1587 1588
	for (index = api_max; index >= api_min; index--) {
		sprintf(buf, "%s%d%s", name_pre, index, ".ucode");
		ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
		if (ret < 0) {
1589
			IWL_ERR(priv, "%s firmware file req failed: %d\n",
1590 1591 1592 1593 1594 1595 1596
				  buf, ret);
			if (ret == -ENOENT)
				continue;
			else
				goto error;
		} else {
			if (index < api_max)
1597 1598 1599
				IWL_ERR(priv, "Loaded firmware %s, "
					"which is deprecated. "
					"Please use API v%u instead.\n",
1600
					  buf, api_max);
1601

1602 1603 1604 1605
			IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
				       buf, ucode_raw->size);
			break;
		}
Z
Zhu Yi 已提交
1606 1607
	}

1608 1609
	if (ret < 0)
		goto error;
Z
Zhu Yi 已提交
1610 1611 1612

	/* Make sure that we got at least our header! */
	if (ucode_raw->size < sizeof(*ucode)) {
1613
		IWL_ERR(priv, "File size way too small!\n");
1614
		ret = -EINVAL;
Z
Zhu Yi 已提交
1615 1616 1617 1618 1619 1620
		goto err_release;
	}

	/* Data from ucode file:  header followed by uCode images */
	ucode = (void *)ucode_raw->data;

1621
	priv->ucode_ver = le32_to_cpu(ucode->ver);
1622
	api_ver = IWL_UCODE_API(priv->ucode_ver);
Z
Zhu Yi 已提交
1623 1624 1625 1626 1627 1628
	inst_size = le32_to_cpu(ucode->inst_size);
	data_size = le32_to_cpu(ucode->data_size);
	init_size = le32_to_cpu(ucode->init_size);
	init_data_size = le32_to_cpu(ucode->init_data_size);
	boot_size = le32_to_cpu(ucode->boot_size);

1629 1630 1631 1632 1633
	/* api_ver should match the api version forming part of the
	 * firmware filename ... but we don't check for that and only rely
	 * on the API version read from firware header from here on forward */

	if (api_ver < api_min || api_ver > api_max) {
1634
		IWL_ERR(priv, "Driver unable to support your firmware API. "
1635 1636 1637 1638 1639 1640 1641
			  "Driver supports v%u, firmware is v%u.\n",
			  api_max, api_ver);
		priv->ucode_ver = 0;
		ret = -EINVAL;
		goto err_release;
	}
	if (api_ver != api_max)
T
Tomas Winkler 已提交
1642
		IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
1643 1644 1645 1646
			  "got v%u. New firmware can be obtained "
			  "from http://www.intellinuxwireless.org.\n",
			  api_max, api_ver);

T
Tomas Winkler 已提交
1647 1648 1649 1650 1651
	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
	       IWL_UCODE_MAJOR(priv->ucode_ver),
	       IWL_UCODE_MINOR(priv->ucode_ver),
	       IWL_UCODE_API(priv->ucode_ver),
	       IWL_UCODE_SERIAL(priv->ucode_ver));
1652 1653 1654

	IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
		       priv->ucode_ver);
Z
Zhu Yi 已提交
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
	IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
		       inst_size);
	IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
		       data_size);
	IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n",
		       init_size);
	IWL_DEBUG_INFO("f/w package hdr init data size = %u\n",
		       init_data_size);
	IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n",
		       boot_size);

	/* Verify size of file vs. image size info in file's header */
	if (ucode_raw->size < sizeof(*ucode) +
		inst_size + data_size + init_size +
		init_data_size + boot_size) {

		IWL_DEBUG_INFO("uCode file size %d too small\n",
			       (int)ucode_raw->size);
1673
		ret = -EINVAL;
Z
Zhu Yi 已提交
1674 1675 1676 1677
		goto err_release;
	}

	/* Verify that uCode images will fit in card's SRAM */
1678
	if (inst_size > priv->hw_params.max_inst_size) {
1679 1680 1681
		IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
			       inst_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
1682 1683 1684
		goto err_release;
	}

1685
	if (data_size > priv->hw_params.max_data_size) {
1686 1687 1688
		IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
				data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
1689 1690
		goto err_release;
	}
1691
	if (init_size > priv->hw_params.max_inst_size) {
Z
Zhu Yi 已提交
1692
		IWL_DEBUG_INFO
1693 1694 1695
		    ("uCode init instr len %d too large to fit in\n",
		      init_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
1696 1697
		goto err_release;
	}
1698
	if (init_data_size > priv->hw_params.max_data_size) {
Z
Zhu Yi 已提交
1699
		IWL_DEBUG_INFO
1700 1701 1702
		    ("uCode init data len %d too large to fit in\n",
		      init_data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
1703 1704
		goto err_release;
	}
1705
	if (boot_size > priv->hw_params.max_bsm_size) {
Z
Zhu Yi 已提交
1706
		IWL_DEBUG_INFO
1707 1708 1709
		    ("uCode boot instr len %d too large to fit in\n",
		      boot_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
1710 1711 1712 1713 1714 1715 1716 1717 1718
		goto err_release;
	}

	/* Allocate ucode buffers for card's bus-master loading ... */

	/* Runtime instructions and 2 copies of data:
	 * 1) unmodified from disk
	 * 2) backup cache for save/restore during power-downs */
	priv->ucode_code.len = inst_size;
1719
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
Z
Zhu Yi 已提交
1720 1721

	priv->ucode_data.len = data_size;
1722
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
Z
Zhu Yi 已提交
1723 1724

	priv->ucode_data_backup.len = data_size;
1725
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
Z
Zhu Yi 已提交
1726 1727

	/* Initialization instructions and data */
1728 1729
	if (init_size && init_data_size) {
		priv->ucode_init.len = init_size;
1730
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
1731 1732

		priv->ucode_init_data.len = init_data_size;
1733
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
1734 1735 1736 1737

		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
			goto err_pci_alloc;
	}
Z
Zhu Yi 已提交
1738 1739

	/* Bootstrap (instructions only, no data) */
1740 1741
	if (boot_size) {
		priv->ucode_boot.len = boot_size;
1742
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
Z
Zhu Yi 已提交
1743

1744 1745 1746
		if (!priv->ucode_boot.v_addr)
			goto err_pci_alloc;
	}
Z
Zhu Yi 已提交
1747 1748 1749 1750 1751 1752

	/* Copy images into buffers for card's bus-master reads ... */

	/* Runtime instructions (first block of data in file) */
	src = &ucode->data[0];
	len = priv->ucode_code.len;
1753
	IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len);
Z
Zhu Yi 已提交
1754 1755 1756 1757 1758
	memcpy(priv->ucode_code.v_addr, src, len);
	IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);

	/* Runtime data (2nd block)
1759
	 * NOTE:  Copy into backup buffer will be done in iwl_up()  */
Z
Zhu Yi 已提交
1760 1761
	src = &ucode->data[inst_size];
	len = priv->ucode_data.len;
1762
	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
Z
Zhu Yi 已提交
1763 1764 1765 1766 1767 1768 1769
	memcpy(priv->ucode_data.v_addr, src, len);
	memcpy(priv->ucode_data_backup.v_addr, src, len);

	/* Initialization instructions (3rd block) */
	if (init_size) {
		src = &ucode->data[inst_size + data_size];
		len = priv->ucode_init.len;
1770 1771
		IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n",
				len);
Z
Zhu Yi 已提交
1772 1773 1774 1775 1776 1777 1778
		memcpy(priv->ucode_init.v_addr, src, len);
	}

	/* Initialization data (4th block) */
	if (init_data_size) {
		src = &ucode->data[inst_size + data_size + init_size];
		len = priv->ucode_init_data.len;
1779 1780
		IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n",
			       len);
Z
Zhu Yi 已提交
1781 1782 1783 1784 1785 1786
		memcpy(priv->ucode_init_data.v_addr, src, len);
	}

	/* Bootstrap instructions (5th block) */
	src = &ucode->data[inst_size + data_size + init_size + init_data_size];
	len = priv->ucode_boot.len;
1787
	IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len);
Z
Zhu Yi 已提交
1788 1789 1790 1791 1792 1793 1794
	memcpy(priv->ucode_boot.v_addr, src, len);

	/* We have our copies now, allow OS release its copies */
	release_firmware(ucode_raw);
	return 0;

 err_pci_alloc:
1795
	IWL_ERR(priv, "failed to allocate pci memory\n");
1796
	ret = -ENOMEM;
1797
	iwl_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
1798 1799 1800 1801 1802

 err_release:
	release_firmware(ucode_raw);

 error:
1803
	return ret;
Z
Zhu Yi 已提交
1804 1805
}

1806 1807 1808 1809
/* temporary */
static int iwl_mac_beacon_update(struct ieee80211_hw *hw,
				 struct sk_buff *skb);

Z
Zhu Yi 已提交
1810
/**
1811
 * iwl_alive_start - called after REPLY_ALIVE notification received
Z
Zhu Yi 已提交
1812
 *                   from protocol/runtime uCode (initialization uCode's
1813
 *                   Alive gets handled by iwl_init_alive_start()).
Z
Zhu Yi 已提交
1814
 */
1815
static void iwl_alive_start(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1816
{
1817
	int ret = 0;
Z
Zhu Yi 已提交
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830

	IWL_DEBUG_INFO("Runtime Alive received.\n");

	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
		/* We had an error bringing up the hardware, so take it
		 * all the way back down so we can try again */
		IWL_DEBUG_INFO("Alive failed.\n");
		goto restart;
	}

	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
	 * This is a paranoid check, because we would not have gotten the
	 * "runtime" alive if code weren't properly loaded.  */
1831
	if (iwl_verify_ucode(priv)) {
Z
Zhu Yi 已提交
1832 1833 1834 1835 1836 1837
		/* Runtime instruction load was bad;
		 * take it all the way back down so we can try again */
		IWL_DEBUG_INFO("Bad runtime uCode load.\n");
		goto restart;
	}

1838
	iwl_clear_stations_table(priv);
1839 1840
	ret = priv->cfg->ops->lib->alive_notify(priv);
	if (ret) {
1841 1842
		IWL_WARN(priv,
			"Could not complete ALIVE transition [ntf]: %d\n", ret);
Z
Zhu Yi 已提交
1843 1844 1845
		goto restart;
	}

1846
	/* After the ALIVE response, we can send host commands to the uCode */
Z
Zhu Yi 已提交
1847 1848
	set_bit(STATUS_ALIVE, &priv->status);

1849
	if (iwl_is_rfkill(priv))
Z
Zhu Yi 已提交
1850 1851
		return;

1852
	ieee80211_wake_queues(priv->hw);
Z
Zhu Yi 已提交
1853 1854 1855 1856

	priv->active_rate = priv->rates_mask;
	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;

1857
	if (iwl_is_associated(priv)) {
G
Gregory Greenman 已提交
1858 1859
		struct iwl_rxon_cmd *active_rxon =
				(struct iwl_rxon_cmd *)&priv->active_rxon;
Z
Zhu Yi 已提交
1860 1861 1862 1863 1864 1865

		memcpy(&priv->staging_rxon, &priv->active_rxon,
		       sizeof(priv->staging_rxon));
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
	} else {
		/* Initialize our rx_config data */
1866
		iwl_connection_init_rx_config(priv, priv->iw_mode);
Z
Zhu Yi 已提交
1867 1868 1869
		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
	}

1870
	/* Configure Bluetooth device coexistence support */
1871
	iwl_send_bt_config(priv);
Z
Zhu Yi 已提交
1872

1873 1874
	iwl_reset_run_time_calib(priv);

Z
Zhu Yi 已提交
1875
	/* Configure the adapter for unassociated operation */
1876
	iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
1877 1878

	/* At this point, the NIC is initialized and operational */
1879
	iwl_rf_kill_ct_config(priv);
1880

1881 1882
	iwl_leds_register(priv);

Z
Zhu Yi 已提交
1883
	IWL_DEBUG_INFO("ALIVE processing complete.\n");
1884
	set_bit(STATUS_READY, &priv->status);
1885
	wake_up_interruptible(&priv->wait_command_queue);
Z
Zhu Yi 已提交
1886 1887

	if (priv->error_recovering)
1888
		iwl_error_recovery(priv);
Z
Zhu Yi 已提交
1889

1890
	iwl_power_update_mode(priv, 1);
1891

1892 1893 1894 1895 1896 1897 1898 1899 1900
	/* reassociate for ADHOC mode */
	if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
		struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
								priv->vif);
		if (beacon)
			iwl_mac_beacon_update(priv->hw, beacon);
	}


1901
	if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
1902
		iwl_set_mode(priv, priv->iw_mode);
1903

Z
Zhu Yi 已提交
1904 1905 1906 1907 1908 1909
	return;

 restart:
	queue_work(priv->workqueue, &priv->restart);
}

1910
static void iwl_cancel_deferred_work(struct iwl_priv *priv);
Z
Zhu Yi 已提交
1911

1912
static void __iwl_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1913 1914 1915 1916 1917 1918 1919 1920 1921
{
	unsigned long flags;
	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);

	IWL_DEBUG_INFO(DRV_NAME " is going down\n");

	if (!exit_pending)
		set_bit(STATUS_EXIT_PENDING, &priv->status);

M
Mohamed Abbas 已提交
1922 1923
	iwl_leds_unregister(priv);

1924
	iwl_clear_stations_table(priv);
Z
Zhu Yi 已提交
1925 1926 1927 1928 1929 1930 1931 1932 1933 1934

	/* Unblock any waiting calls */
	wake_up_interruptible_all(&priv->wait_command_queue);

	/* Wipe out the EXIT_PENDING status bit if we are not actually
	 * exiting the module */
	if (!exit_pending)
		clear_bit(STATUS_EXIT_PENDING, &priv->status);

	/* stop and reset the on-board processor */
1935
	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Z
Zhu Yi 已提交
1936 1937

	/* tell the device to stop sending interrupts */
1938
	spin_lock_irqsave(&priv->lock, flags);
1939
	iwl_disable_interrupts(priv);
1940 1941
	spin_unlock_irqrestore(&priv->lock, flags);
	iwl_synchronize_irq(priv);
Z
Zhu Yi 已提交
1942 1943 1944 1945

	if (priv->mac80211_registered)
		ieee80211_stop_queues(priv->hw);

1946
	/* If we have not previously called iwl_init() then
Z
Zhu Yi 已提交
1947
	 * clear all bits but the RF Kill and SUSPEND bits and return */
1948
	if (!iwl_is_init(priv)) {
Z
Zhu Yi 已提交
1949 1950 1951 1952
		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
					STATUS_RF_KILL_HW |
			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
					STATUS_RF_KILL_SW |
1953 1954
			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
					STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
1955
			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
1956 1957 1958
					STATUS_IN_SUSPEND |
			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
					STATUS_EXIT_PENDING;
Z
Zhu Yi 已提交
1959 1960 1961 1962 1963 1964 1965 1966 1967
		goto exit;
	}

	/* ...otherwise clear out all the status bits but the RF Kill and
	 * SUSPEND bits and continue taking the NIC down. */
	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
				STATUS_RF_KILL_HW |
			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
				STATUS_RF_KILL_SW |
1968 1969
			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
				STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
1970 1971 1972
			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
				STATUS_IN_SUSPEND |
			test_bit(STATUS_FW_ERROR, &priv->status) <<
1973 1974 1975
				STATUS_FW_ERROR |
		       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
				STATUS_EXIT_PENDING;
Z
Zhu Yi 已提交
1976 1977

	spin_lock_irqsave(&priv->lock, flags);
1978
	iwl_clear_bit(priv, CSR_GP_CNTRL,
1979
			 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Z
Zhu Yi 已提交
1980 1981
	spin_unlock_irqrestore(&priv->lock, flags);

1982
	iwl_txq_ctx_stop(priv);
1983
	iwl_rxq_stop(priv);
Z
Zhu Yi 已提交
1984 1985

	spin_lock_irqsave(&priv->lock, flags);
1986 1987
	if (!iwl_grab_nic_access(priv)) {
		iwl_write_prph(priv, APMG_CLK_DIS_REG,
Z
Zhu Yi 已提交
1988
					 APMG_CLK_VAL_DMA_CLK_RQT);
1989
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
1990 1991 1992 1993 1994
	}
	spin_unlock_irqrestore(&priv->lock, flags);

	udelay(5);

1995
	/* FIXME: apm_ops.suspend(priv) */
1996 1997 1998 1999
	if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
		priv->cfg->ops->lib->apm_ops.stop(priv);
	else
		priv->cfg->ops->lib->apm_ops.reset(priv);
Z
Zhu Yi 已提交
2000
 exit:
2001
	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
Z
Zhu Yi 已提交
2002 2003 2004 2005 2006 2007

	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);
	priv->ibss_beacon = NULL;

	/* clear out any free frames */
2008
	iwl_clear_free_frames(priv);
Z
Zhu Yi 已提交
2009 2010
}

2011
static void iwl_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2012 2013
{
	mutex_lock(&priv->mutex);
2014
	__iwl_down(priv);
Z
Zhu Yi 已提交
2015
	mutex_unlock(&priv->mutex);
2016

2017
	iwl_cancel_deferred_work(priv);
Z
Zhu Yi 已提交
2018 2019 2020 2021
}

#define MAX_HW_RESTARTS 5

2022
static int __iwl_up(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2023
{
2024 2025
	int i;
	int ret;
Z
Zhu Yi 已提交
2026 2027

	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
2028
		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
Z
Zhu Yi 已提交
2029 2030 2031
		return -EIO;
	}

2032
	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
2033
		IWL_ERR(priv, "ucode not available for device bringup\n");
2034 2035 2036
		return -EIO;
	}

2037
	/* If platform's RF_KILL switch is NOT set to KILL */
2038
	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
2039
		clear_bit(STATUS_RF_KILL_HW, &priv->status);
2040
	else
2041
		set_bit(STATUS_RF_KILL_HW, &priv->status);
2042

2043
	if (iwl_is_rfkill(priv)) {
2044
		iwl_enable_interrupts(priv);
2045
		IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
2046
		    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
2047
		return 0;
Z
Zhu Yi 已提交
2048 2049
	}

2050
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
Z
Zhu Yi 已提交
2051

2052
	ret = iwl_hw_nic_init(priv);
2053
	if (ret) {
2054
		IWL_ERR(priv, "Unable to init nic\n");
2055
		return ret;
Z
Zhu Yi 已提交
2056 2057 2058
	}

	/* make sure rfkill handshake bits are cleared */
2059 2060
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
Z
Zhu Yi 已提交
2061 2062 2063
		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

	/* clear (again), then enable host interrupts */
2064
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
2065
	iwl_enable_interrupts(priv);
Z
Zhu Yi 已提交
2066 2067

	/* really make sure rfkill handshake bits are cleared */
2068 2069
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Z
Zhu Yi 已提交
2070 2071 2072 2073 2074

	/* Copy original ucode data image from disk into backup cache.
	 * This will be used to initialize the on-board processor's
	 * data SRAM for a clean start when the runtime program first loads. */
	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
2075
	       priv->ucode_data.len);
Z
Zhu Yi 已提交
2076 2077 2078

	for (i = 0; i < MAX_HW_RESTARTS; i++) {

2079
		iwl_clear_stations_table(priv);
Z
Zhu Yi 已提交
2080 2081 2082 2083

		/* load bootstrap state machine,
		 * load bootstrap program into processor's memory,
		 * prepare to load the "initialize" uCode */
2084
		ret = priv->cfg->ops->lib->load_ucode(priv);
Z
Zhu Yi 已提交
2085

2086
		if (ret) {
2087 2088
			IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
				ret);
Z
Zhu Yi 已提交
2089 2090 2091
			continue;
		}

2092 2093 2094
		/* Clear out the uCode error bit if it is set */
		clear_bit(STATUS_FW_ERROR, &priv->status);

Z
Zhu Yi 已提交
2095
		/* start card; "initialize" will load runtime ucode */
2096
		iwl_nic_start(priv);
Z
Zhu Yi 已提交
2097 2098 2099 2100 2101 2102 2103

		IWL_DEBUG_INFO(DRV_NAME " is coming up\n");

		return 0;
	}

	set_bit(STATUS_EXIT_PENDING, &priv->status);
2104
	__iwl_down(priv);
M
Mohamed Abbas 已提交
2105
	clear_bit(STATUS_EXIT_PENDING, &priv->status);
Z
Zhu Yi 已提交
2106 2107 2108

	/* tried to restart and config the device for as long as our
	 * patience could withstand */
2109
	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
Z
Zhu Yi 已提交
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119
	return -EIO;
}


/*****************************************************************************
 *
 * Workqueue callbacks
 *
 *****************************************************************************/

2120
static void iwl_bg_init_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
2121
{
2122 2123
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, init_alive_start.work);
Z
Zhu Yi 已提交
2124 2125 2126 2127 2128

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

	mutex_lock(&priv->mutex);
2129
	priv->cfg->ops->lib->init_alive_start(priv);
Z
Zhu Yi 已提交
2130 2131 2132
	mutex_unlock(&priv->mutex);
}

2133
static void iwl_bg_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
2134
{
2135 2136
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, alive_start.work);
Z
Zhu Yi 已提交
2137 2138 2139 2140 2141

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

	mutex_lock(&priv->mutex);
2142
	iwl_alive_start(priv);
Z
Zhu Yi 已提交
2143 2144 2145
	mutex_unlock(&priv->mutex);
}

2146
static void iwl_bg_rf_kill(struct work_struct *work)
Z
Zhu Yi 已提交
2147
{
2148
	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
Z
Zhu Yi 已提交
2149 2150 2151 2152 2153 2154 2155 2156

	wake_up_interruptible(&priv->wait_command_queue);

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

	mutex_lock(&priv->mutex);

2157
	if (!iwl_is_rfkill(priv)) {
2158
		IWL_DEBUG(IWL_DL_RF_KILL,
Z
Zhu Yi 已提交
2159 2160 2161 2162 2163
			  "HW and/or SW RF Kill no longer active, restarting "
			  "device\n");
		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
			queue_work(priv->workqueue, &priv->restart);
	} else {
2164 2165 2166
		/* make sure mac80211 stop sending Tx frame */
		if (priv->mac80211_registered)
			ieee80211_stop_queues(priv->hw);
Z
Zhu Yi 已提交
2167 2168 2169 2170 2171

		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
			IWL_DEBUG_RF_KILL("Can not turn radio back on - "
					  "disabled by SW switch\n");
		else
2172
			IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
Z
Zhu Yi 已提交
2173 2174 2175 2176
				    "Kill switch must be turned off for "
				    "wireless networking to work.\n");
	}
	mutex_unlock(&priv->mutex);
2177
	iwl_rfkill_set_hw_state(priv);
Z
Zhu Yi 已提交
2178 2179
}

2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202
static void iwl_bg_run_time_calib_work(struct work_struct *work)
{
	struct iwl_priv *priv = container_of(work, struct iwl_priv,
			run_time_calib_work);

	mutex_lock(&priv->mutex);

	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
	    test_bit(STATUS_SCANNING, &priv->status)) {
		mutex_unlock(&priv->mutex);
		return;
	}

	if (priv->start_calib) {
		iwl_chain_noise_calibration(priv, &priv->statistics);

		iwl_sensitivity_calibration(priv, &priv->statistics);
	}

	mutex_unlock(&priv->mutex);
	return;
}

2203
static void iwl_bg_up(struct work_struct *data)
Z
Zhu Yi 已提交
2204
{
2205
	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
Z
Zhu Yi 已提交
2206 2207 2208 2209 2210

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

	mutex_lock(&priv->mutex);
2211
	__iwl_up(priv);
Z
Zhu Yi 已提交
2212
	mutex_unlock(&priv->mutex);
2213
	iwl_rfkill_set_hw_state(priv);
Z
Zhu Yi 已提交
2214 2215
}

2216
static void iwl_bg_restart(struct work_struct *data)
Z
Zhu Yi 已提交
2217
{
2218
	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
Z
Zhu Yi 已提交
2219 2220 2221 2222

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

2223
	iwl_down(priv);
Z
Zhu Yi 已提交
2224 2225 2226
	queue_work(priv->workqueue, &priv->up);
}

2227
static void iwl_bg_rx_replenish(struct work_struct *data)
Z
Zhu Yi 已提交
2228
{
2229 2230
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, rx_replenish);
Z
Zhu Yi 已提交
2231 2232 2233 2234 2235

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

	mutex_lock(&priv->mutex);
2236
	iwl_rx_replenish(priv);
Z
Zhu Yi 已提交
2237 2238 2239
	mutex_unlock(&priv->mutex);
}

2240 2241
#define IWL_DELAY_NEXT_SCAN (HZ*2)

2242
static void iwl_post_associate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2243 2244
{
	struct ieee80211_conf *conf = NULL;
2245
	int ret = 0;
2246
	unsigned long flags;
Z
Zhu Yi 已提交
2247

2248
	if (priv->iw_mode == NL80211_IFTYPE_AP) {
2249
		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
Z
Zhu Yi 已提交
2250 2251 2252
		return;
	}

J
Johannes Berg 已提交
2253 2254
	IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
			priv->assoc_id, priv->active_rxon.bssid_addr);
Z
Zhu Yi 已提交
2255 2256 2257 2258 2259 2260


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


2261
	if (!priv->vif || !priv->is_open)
M
Mohamed Abbas 已提交
2262
		return;
2263

2264
	iwl_power_cancel_timeout(priv);
2265
	iwl_scan_cancel_timeout(priv, 200);
2266

Z
Zhu Yi 已提交
2267 2268 2269
	conf = ieee80211_get_hw_conf(priv->hw);

	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2270
	iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
2271

2272
	iwl_setup_rxon_timing(priv);
2273
	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
Z
Zhu Yi 已提交
2274
			      sizeof(priv->rxon_timing), &priv->rxon_timing);
2275
	if (ret)
2276
		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
Z
Zhu Yi 已提交
2277 2278 2279 2280
			    "Attempting to continue.\n");

	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;

2281
	iwl_set_rxon_ht(priv, &priv->current_ht_config);
2282

R
Ron Rindjunsky 已提交
2283
	iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);

	IWL_DEBUG_ASSOC("assoc id %d beacon interval %d\n",
			priv->assoc_id, priv->beacon_int);

	if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
	else
		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;

	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

2300
		if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
Z
Zhu Yi 已提交
2301 2302 2303 2304
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

	}

2305
	iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
2306 2307

	switch (priv->iw_mode) {
2308
	case NL80211_IFTYPE_STATION:
Z
Zhu Yi 已提交
2309 2310
		break;

2311
	case NL80211_IFTYPE_ADHOC:
Z
Zhu Yi 已提交
2312

2313 2314
		/* assume default assoc id */
		priv->assoc_id = 1;
Z
Zhu Yi 已提交
2315

2316
		iwl_rxon_add_station(priv, priv->bssid, 0);
2317
		iwl_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
2318 2319 2320 2321

		break;

	default:
2322
		IWL_ERR(priv, "%s Should not be called in %d mode\n",
2323
			  __func__, priv->iw_mode);
Z
Zhu Yi 已提交
2324 2325 2326
		break;
	}

2327
	if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
Z
Zhu Yi 已提交
2328 2329
		priv->assoc_station_added = 1;

2330 2331 2332
	spin_lock_irqsave(&priv->lock, flags);
	iwl_activate_qos(priv, 0);
	spin_unlock_irqrestore(&priv->lock, flags);
2333

2334 2335 2336 2337 2338
	/* the chain noise calibration will enabled PM upon completion
	 * If chain noise has already been run, then we need to enable
	 * power management here */
	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
		iwl_power_enable_management(priv);
2339 2340 2341 2342 2343

	/* Enable Rx differential gain and sensitivity calibrations */
	iwl_chain_noise_reset(priv);
	priv->start_calib = 1;

2344 2345
}

Z
Zhu Yi 已提交
2346 2347 2348 2349 2350 2351
/*****************************************************************************
 *
 * mac80211 entry point functions
 *
 *****************************************************************************/

2352
#define UCODE_READY_TIMEOUT	(4 * HZ)
2353

2354
static int iwl_mac_start(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
2355
{
2356
	struct iwl_priv *priv = hw->priv;
2357
	int ret;
2358
	u16 pci_cmd;
Z
Zhu Yi 已提交
2359 2360 2361

	IWL_DEBUG_MAC80211("enter\n");

2362
	if (pci_enable_device(priv->pci_dev)) {
2363
		IWL_ERR(priv, "Fail to pci_enable_device\n");
2364 2365 2366 2367 2368
		return -ENODEV;
	}
	pci_restore_state(priv->pci_dev);
	pci_enable_msi(priv->pci_dev);

2369 2370 2371 2372 2373 2374 2375
	/* enable interrupts if needed: hw bug w/a */
	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
	}

2376
	ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
2377 2378
			  DRV_NAME, priv);
	if (ret) {
2379
		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
2380 2381 2382
		goto out_disable_msi;
	}

Z
Zhu Yi 已提交
2383 2384 2385
	/* we should be verifying the device is ready to be opened */
	mutex_lock(&priv->mutex);

G
Gregory Greenman 已提交
2386
	memset(&priv->staging_rxon, 0, sizeof(struct iwl_rxon_cmd));
2387 2388
	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
	 * ucode filename and max sizes are card-specific. */
Z
Zhu Yi 已提交
2389

2390
	if (!priv->ucode_code.len) {
2391
		ret = iwl_read_ucode(priv);
2392
		if (ret) {
2393
			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
2394 2395 2396 2397
			mutex_unlock(&priv->mutex);
			goto out_release_irq;
		}
	}
Z
Zhu Yi 已提交
2398

2399
	ret = __iwl_up(priv);
2400

Z
Zhu Yi 已提交
2401
	mutex_unlock(&priv->mutex);
2402

2403 2404
	iwl_rfkill_set_hw_state(priv);

2405 2406 2407
	if (ret)
		goto out_release_irq;

2408 2409 2410
	if (iwl_is_rfkill(priv))
		goto out;

2411 2412 2413 2414 2415
	IWL_DEBUG_INFO("Start UP work done.\n");

	if (test_bit(STATUS_IN_SUSPEND, &priv->status))
		return 0;

2416
	/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
2417
	 * mac80211 will not be run successfully. */
2418 2419 2420 2421 2422
	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
			test_bit(STATUS_READY, &priv->status),
			UCODE_READY_TIMEOUT);
	if (!ret) {
		if (!test_bit(STATUS_READY, &priv->status)) {
2423
			IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
2424 2425 2426
				jiffies_to_msecs(UCODE_READY_TIMEOUT));
			ret = -ETIMEDOUT;
			goto out_release_irq;
2427
		}
2428
	}
T
Tomas Winkler 已提交
2429

2430
out:
T
Tomas Winkler 已提交
2431
	priv->is_open = 1;
Z
Zhu Yi 已提交
2432 2433
	IWL_DEBUG_MAC80211("leave\n");
	return 0;
2434 2435 2436 2437 2438

out_release_irq:
	free_irq(priv->pci_dev->irq, priv);
out_disable_msi:
	pci_disable_msi(priv->pci_dev);
2439 2440 2441
	pci_disable_device(priv->pci_dev);
	priv->is_open = 0;
	IWL_DEBUG_MAC80211("leave - failed\n");
2442
	return ret;
Z
Zhu Yi 已提交
2443 2444
}

2445
static void iwl_mac_stop(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
2446
{
2447
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
2448 2449

	IWL_DEBUG_MAC80211("enter\n");
M
Mohamed Abbas 已提交
2450

2451 2452 2453 2454 2455
	if (!priv->is_open) {
		IWL_DEBUG_MAC80211("leave - skip\n");
		return;
	}

Z
Zhu Yi 已提交
2456
	priv->is_open = 0;
2457

2458
	if (iwl_is_ready_rf(priv)) {
2459 2460 2461
		/* stop mac, cancel any scan request and clear
		 * RXON_FILTER_ASSOC_MSK BIT
		 */
2462
		mutex_lock(&priv->mutex);
2463
		iwl_scan_cancel_timeout(priv, 100);
2464 2465 2466
		mutex_unlock(&priv->mutex);
	}

2467
	iwl_down(priv);
2468 2469 2470 2471 2472 2473

	flush_workqueue(priv->workqueue);
	free_irq(priv->pci_dev->irq, priv);
	pci_disable_msi(priv->pci_dev);
	pci_save_state(priv->pci_dev);
	pci_disable_device(priv->pci_dev);
M
Mohamed Abbas 已提交
2474

Z
Zhu Yi 已提交
2475 2476 2477
	IWL_DEBUG_MAC80211("leave\n");
}

2478
static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Z
Zhu Yi 已提交
2479
{
2480
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
2481

T
Tomas Winkler 已提交
2482
	IWL_DEBUG_MACDUMP("enter\n");
Z
Zhu Yi 已提交
2483 2484

	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
2485
		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
Z
Zhu Yi 已提交
2486

2487
	if (iwl_tx_skb(priv, skb))
Z
Zhu Yi 已提交
2488 2489
		dev_kfree_skb_any(skb);

T
Tomas Winkler 已提交
2490
	IWL_DEBUG_MACDUMP("leave\n");
2491
	return NETDEV_TX_OK;
Z
Zhu Yi 已提交
2492 2493
}

2494
static int iwl_mac_add_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
2495 2496
				 struct ieee80211_if_init_conf *conf)
{
2497
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
2498 2499
	unsigned long flags;

2500
	IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
Z
Zhu Yi 已提交
2501

2502 2503
	if (priv->vif) {
		IWL_DEBUG_MAC80211("leave - vif != NULL\n");
2504
		return -EOPNOTSUPP;
Z
Zhu Yi 已提交
2505 2506 2507
	}

	spin_lock_irqsave(&priv->lock, flags);
2508
	priv->vif = conf->vif;
2509
	priv->iw_mode = conf->type;
Z
Zhu Yi 已提交
2510 2511 2512 2513

	spin_unlock_irqrestore(&priv->lock, flags);

	mutex_lock(&priv->mutex);
2514 2515

	if (conf->mac_addr) {
J
Johannes Berg 已提交
2516
		IWL_DEBUG_MAC80211("Set %pM\n", conf->mac_addr);
2517 2518
		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
	}
Z
Zhu Yi 已提交
2519

2520
	if (iwl_set_mode(priv, conf->type) == -EAGAIN)
2521 2522
		/* we are not ready, will run again when ready */
		set_bit(STATUS_MODE_PENDING, &priv->status);
2523

Z
Zhu Yi 已提交
2524 2525
	mutex_unlock(&priv->mutex);

2526
	IWL_DEBUG_MAC80211("leave\n");
Z
Zhu Yi 已提交
2527 2528 2529 2530
	return 0;
}

/**
2531
 * iwl_mac_config - mac80211 config callback
Z
Zhu Yi 已提交
2532 2533 2534 2535 2536
 *
 * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
 * be set inappropriately and the driver currently sets the hardware up to
 * use it whenever needed.
 */
2537
static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
Z
Zhu Yi 已提交
2538
{
2539
	struct iwl_priv *priv = hw->priv;
2540
	const struct iwl_channel_info *ch_info;
2541
	struct ieee80211_conf *conf = &hw->conf;
Z
Zhu Yi 已提交
2542
	unsigned long flags;
2543
	int ret = 0;
2544
	u16 channel;
Z
Zhu Yi 已提交
2545 2546

	mutex_lock(&priv->mutex);
2547
	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
Z
Zhu Yi 已提交
2548

2549
	priv->current_ht_config.is_ht = conf_is_ht(conf);
J
Johannes Berg 已提交
2550

2551
	if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
M
Mohamed Abbas 已提交
2552
		IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
2553
		goto out;
M
Mohamed Abbas 已提交
2554 2555
	}

2556 2557 2558
	if (!conf->radio_enabled)
		iwl_radio_kill_sw_disable_radio(priv);

2559
	if (!iwl_is_ready(priv)) {
Z
Zhu Yi 已提交
2560
		IWL_DEBUG_MAC80211("leave - not ready\n");
2561 2562
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
2563 2564
	}

2565
	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
Z
Zhu Yi 已提交
2566
		     test_bit(STATUS_SCANNING, &priv->status))) {
2567
		IWL_DEBUG_MAC80211("leave - scanning\n");
Z
Zhu Yi 已提交
2568
		mutex_unlock(&priv->mutex);
2569
		return 0;
Z
Zhu Yi 已提交
2570 2571
	}

2572 2573
	channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
	ch_info = iwl_get_channel_info(priv, conf->channel->band, channel);
Z
Zhu Yi 已提交
2574 2575
	if (!is_channel_valid(ch_info)) {
		IWL_DEBUG_MAC80211("leave - invalid channel\n");
2576 2577
		ret = -EINVAL;
		goto out;
Z
Zhu Yi 已提交
2578 2579
	}

2580
	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
2581
	    !is_channel_ibss(ch_info)) {
2582
		IWL_ERR(priv, "channel %d in band %d not IBSS channel\n",
2583 2584 2585 2586 2587
			conf->channel->hw_value, conf->channel->band);
		ret = -EINVAL;
		goto out;
	}

2588 2589
	spin_lock_irqsave(&priv->lock, flags);

2590

2591
	/* if we are switching from ht to 2.4 clear flags
Z
Zhu Yi 已提交
2592 2593
	 * from any ht related info since 2.4 does not
	 * support ht */
2594
	if ((le16_to_cpu(priv->staging_rxon.channel) != channel)
Z
Zhu Yi 已提交
2595 2596 2597 2598 2599 2600
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
	    && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
#endif
	)
		priv->staging_rxon.flags = 0;

2601
	iwl_set_rxon_channel(priv, conf->channel);
Z
Zhu Yi 已提交
2602

2603
	iwl_set_flags_for_band(priv, conf->channel->band);
Z
Zhu Yi 已提交
2604 2605

	/* The list of supported rates and rate mask can be different
2606
	 * for each band; since the band may have changed, reset
Z
Zhu Yi 已提交
2607
	 * the rate mask to what mac80211 lists */
2608
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
2609 2610 2611 2612 2613

	spin_unlock_irqrestore(&priv->lock, flags);

#ifdef IEEE80211_CONF_CHANNEL_SWITCH
	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
2614
		iwl_hw_channel_switch(priv, conf->channel);
2615
		goto out;
Z
Zhu Yi 已提交
2616 2617 2618 2619 2620
	}
#endif

	if (!conf->radio_enabled) {
		IWL_DEBUG_MAC80211("leave - radio disabled\n");
2621
		goto out;
Z
Zhu Yi 已提交
2622 2623
	}

2624
	if (iwl_is_rfkill(priv)) {
Z
Zhu Yi 已提交
2625
		IWL_DEBUG_MAC80211("leave - RF kill\n");
2626 2627
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
2628 2629
	}

2630 2631 2632 2633 2634 2635 2636
	if (conf->flags & IEEE80211_CONF_PS)
		ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3);
	else
		ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM);
	if (ret)
		IWL_DEBUG_MAC80211("Error setting power level\n");

2637 2638 2639 2640 2641
	IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n",
			   priv->tx_power_user_lmt, conf->power_level);

	iwl_set_tx_power(priv, conf->power_level, false);

2642
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
2643 2644 2645

	if (memcmp(&priv->active_rxon,
		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
2646
		iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
2647 2648 2649 2650 2651
	else
		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");

	IWL_DEBUG_MAC80211("leave\n");

2652
out:
2653
	mutex_unlock(&priv->mutex);
2654
	return ret;
Z
Zhu Yi 已提交
2655 2656
}

2657
static void iwl_config_ap(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2658
{
2659
	int ret = 0;
2660
	unsigned long flags;
Z
Zhu Yi 已提交
2661

2662
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Z
Zhu Yi 已提交
2663 2664 2665
		return;

	/* The following should be done only at AP bring up */
2666
	if (!iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
2667 2668 2669

		/* RXON - unassoc (to set timing command) */
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2670
		iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
2671 2672

		/* RXON Timing */
2673
		iwl_setup_rxon_timing(priv);
2674
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
Z
Zhu Yi 已提交
2675
				sizeof(priv->rxon_timing), &priv->rxon_timing);
2676
		if (ret)
2677
			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
Z
Zhu Yi 已提交
2678 2679
					"Attempting to continue.\n");

R
Ron Rindjunsky 已提交
2680
		iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699

		/* FIXME: what should be the assoc_id for AP? */
		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
			priv->staging_rxon.flags |=
				RXON_FLG_SHORT_PREAMBLE_MSK;
		else
			priv->staging_rxon.flags &=
				~RXON_FLG_SHORT_PREAMBLE_MSK;

		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
			if (priv->assoc_capability &
				WLAN_CAPABILITY_SHORT_SLOT_TIME)
				priv->staging_rxon.flags |=
					RXON_FLG_SHORT_SLOT_MSK;
			else
				priv->staging_rxon.flags &=
					~RXON_FLG_SHORT_SLOT_MSK;

2700
			if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
Z
Zhu Yi 已提交
2701 2702 2703 2704 2705
				priv->staging_rxon.flags &=
					~RXON_FLG_SHORT_SLOT_MSK;
		}
		/* restore RXON assoc */
		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
2706
		iwl_commit_rxon(priv);
2707 2708 2709
		spin_lock_irqsave(&priv->lock, flags);
		iwl_activate_qos(priv, 1);
		spin_unlock_irqrestore(&priv->lock, flags);
2710
		iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
2711
	}
2712
	iwl_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
2713 2714 2715 2716 2717 2718

	/* FIXME - we need to add code here to detect a totally new
	 * configuration, reset the AP, unassoc, rxon timing, assoc,
	 * clear sta table, add BCAST sta... */
}

2719

2720
static int iwl_mac_config_interface(struct ieee80211_hw *hw,
2721
					struct ieee80211_vif *vif,
Z
Zhu Yi 已提交
2722 2723
				    struct ieee80211_if_conf *conf)
{
2724
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
2725 2726 2727 2728 2729
	int rc;

	if (conf == NULL)
		return -EIO;

2730 2731 2732 2733 2734
	if (priv->vif != vif) {
		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
		return 0;
	}

2735
	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
2736 2737 2738 2739
	    conf->changed & IEEE80211_IFCC_BEACON) {
		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
		if (!beacon)
			return -ENOMEM;
2740
		mutex_lock(&priv->mutex);
2741
		rc = iwl_mac_beacon_update(hw, beacon);
2742
		mutex_unlock(&priv->mutex);
2743 2744 2745 2746
		if (rc)
			return rc;
	}

2747
	if (!iwl_is_alive(priv))
2748 2749
		return -EAGAIN;

Z
Zhu Yi 已提交
2750 2751 2752
	mutex_lock(&priv->mutex);

	if (conf->bssid)
J
Johannes Berg 已提交
2753
		IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
Z
Zhu Yi 已提交
2754

2755 2756 2757
/*
 * very dubious code was here; the probe filtering flag is never set:
 *
Z
Zhu Yi 已提交
2758 2759
	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
2760
 */
Z
Zhu Yi 已提交
2761

2762
	if (priv->iw_mode == NL80211_IFTYPE_AP) {
Z
Zhu Yi 已提交
2763 2764 2765
		if (!conf->bssid) {
			conf->bssid = priv->mac_addr;
			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
J
Johannes Berg 已提交
2766 2767
			IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
					   conf->bssid);
Z
Zhu Yi 已提交
2768 2769 2770 2771
		}
		if (priv->ibss_beacon)
			dev_kfree_skb(priv->ibss_beacon);

2772
		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
Z
Zhu Yi 已提交
2773 2774
	}

2775
	if (iwl_is_rfkill(priv))
2776 2777
		goto done;

Z
Zhu Yi 已提交
2778 2779 2780 2781
	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
	    !is_multicast_ether_addr(conf->bssid)) {
		/* If there is currently a HW scan going on in the background
		 * then we need to cancel it else the RXON below will fail. */
2782
		if (iwl_scan_cancel_timeout(priv, 100)) {
2783
			IWL_WARN(priv, "Aborted scan still in progress "
Z
Zhu Yi 已提交
2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796
				    "after 100ms\n");
			IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
			mutex_unlock(&priv->mutex);
			return -EAGAIN;
		}
		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);

		/* TODO: Audit driver for usage of these members and see
		 * if mac80211 deprecates them (priv->bssid looks like it
		 * shouldn't be there, but I haven't scanned the IBSS code
		 * to verify) - jpk */
		memcpy(priv->bssid, conf->bssid, ETH_ALEN);

2797
		if (priv->iw_mode == NL80211_IFTYPE_AP)
2798
			iwl_config_ap(priv);
Z
Zhu Yi 已提交
2799
		else {
2800
			rc = iwl_commit_rxon(priv);
2801
			if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
2802
				iwl_rxon_add_station(
Z
Zhu Yi 已提交
2803 2804 2805 2806
					priv, priv->active_rxon.bssid_addr, 1);
		}

	} else {
2807
		iwl_scan_cancel_timeout(priv, 100);
Z
Zhu Yi 已提交
2808
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2809
		iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
2810 2811
	}

2812
 done:
Z
Zhu Yi 已提交
2813 2814 2815 2816 2817 2818
	IWL_DEBUG_MAC80211("leave\n");
	mutex_unlock(&priv->mutex);

	return 0;
}

2819
static void iwl_configure_filter(struct ieee80211_hw *hw,
2820 2821 2822 2823
				 unsigned int changed_flags,
				 unsigned int *total_flags,
				 int mc_count, struct dev_addr_list *mc_list)
{
2824
	struct iwl_priv *priv = hw->priv;
Z
Zhu, Yi 已提交
2825 2826 2827 2828
	__le32 *filter_flags = &priv->staging_rxon.filter_flags;

	IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
			changed_flags, *total_flags);
2829

Z
Zhu, Yi 已提交
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852
	if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
		if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
			*filter_flags |= RXON_FILTER_PROMISC_MSK;
		else
			*filter_flags &= ~RXON_FILTER_PROMISC_MSK;
	}
	if (changed_flags & FIF_ALLMULTI) {
		if (*total_flags & FIF_ALLMULTI)
			*filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
		else
			*filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
	}
	if (changed_flags & FIF_CONTROL) {
		if (*total_flags & FIF_CONTROL)
			*filter_flags |= RXON_FILTER_CTL2HOST_MSK;
		else
			*filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
	}
	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
			*filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
		else
			*filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
2853
	}
Z
Zhu, Yi 已提交
2854 2855 2856 2857 2858 2859 2860 2861

	/* We avoid iwl_commit_rxon here to commit the new filter flags
	 * since mac80211 will call ieee80211_hw_config immediately.
	 * (mc_list is not supported at this time). Otherwise, we need to
	 * queue a background iwl_commit_rxon work.
	 */

	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
2862
			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
2863 2864
}

2865
static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
2866 2867
				     struct ieee80211_if_init_conf *conf)
{
2868
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
2869 2870 2871 2872

	IWL_DEBUG_MAC80211("enter\n");

	mutex_lock(&priv->mutex);
M
Mohamed Abbas 已提交
2873

2874
	if (iwl_is_ready_rf(priv)) {
2875
		iwl_scan_cancel_timeout(priv, 100);
2876
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2877
		iwl_commit_rxon(priv);
2878
	}
2879 2880
	if (priv->vif == conf->vif) {
		priv->vif = NULL;
Z
Zhu Yi 已提交
2881 2882 2883 2884 2885 2886 2887
		memset(priv->bssid, 0, ETH_ALEN);
	}
	mutex_unlock(&priv->mutex);

	IWL_DEBUG_MAC80211("leave\n");

}
2888

2889
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
2890
static void iwl_bss_info_changed(struct ieee80211_hw *hw,
2891 2892 2893
				     struct ieee80211_vif *vif,
				     struct ieee80211_bss_conf *bss_conf,
				     u32 changes)
2894
{
2895
	struct iwl_priv *priv = hw->priv;
2896

2897 2898
	IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);

2899
	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
2900 2901
		IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
				   bss_conf->use_short_preamble);
2902
		if (bss_conf->use_short_preamble)
2903 2904 2905 2906 2907
			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
	}

2908
	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
2909
		IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
2910
		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
2911 2912 2913 2914 2915
			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
	}

T
Tomas Winkler 已提交
2916
	if (changes & BSS_CHANGED_HT) {
2917
		iwl_ht_conf(priv, bss_conf);
R
Ron Rindjunsky 已提交
2918
		iwl_set_rxon_chain(priv);
T
Tomas Winkler 已提交
2919 2920
	}

2921
	if (changes & BSS_CHANGED_ASSOC) {
2922
		IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
2923 2924 2925 2926
		/* This should never happen as this function should
		 * never be called from interrupt context. */
		if (WARN_ON_ONCE(in_interrupt()))
			return;
2927 2928 2929
		if (bss_conf->assoc) {
			priv->assoc_id = bss_conf->aid;
			priv->beacon_int = bss_conf->beacon_int;
2930
			priv->power_data.dtim_period = bss_conf->dtim_period;
2931 2932
			priv->timestamp = bss_conf->timestamp;
			priv->assoc_capability = bss_conf->assoc_capability;
2933 2934 2935 2936

			/* we have just associated, don't start scan too early
			 * leave time for EAPOL exchange to complete
			 */
2937 2938
			priv->next_scan_jiffies = jiffies +
					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
2939
			mutex_lock(&priv->mutex);
2940
			iwl_post_associate(priv);
2941
			mutex_unlock(&priv->mutex);
2942 2943 2944 2945 2946 2947
		} else {
			priv->assoc_id = 0;
			IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
		}
	} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
			IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
2948
			iwl_send_rxon_assoc(priv);
2949 2950
	}

2951
}
Z
Zhu Yi 已提交
2952

2953
static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
Z
Zhu Yi 已提交
2954 2955
{
	unsigned long flags;
2956
	struct iwl_priv *priv = hw->priv;
2957
	int ret;
Z
Zhu Yi 已提交
2958 2959 2960

	IWL_DEBUG_MAC80211("enter\n");

2961
	mutex_lock(&priv->mutex);
Z
Zhu Yi 已提交
2962 2963
	spin_lock_irqsave(&priv->lock, flags);

2964
	if (!iwl_is_ready_rf(priv)) {
2965
		ret = -EIO;
Z
Zhu Yi 已提交
2966 2967 2968 2969
		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
		goto out_unlock;
	}

2970 2971 2972 2973
	/* We don't schedule scan within next_scan_jiffies period.
	 * Avoid scanning during possible EAPOL exchange, return
	 * success immediately.
	 */
2974
	if (priv->next_scan_jiffies &&
2975
	    time_after(priv->next_scan_jiffies, jiffies)) {
2976
		IWL_DEBUG_SCAN("scan rejected: within next scan period\n");
2977 2978
		queue_work(priv->workqueue, &priv->scan_completed);
		ret = 0;
2979 2980
		goto out_unlock;
	}
2981

Z
Zhu Yi 已提交
2982
	/* if we just finished scan ask for delay */
2983
	if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
2984
	    time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
2985
		IWL_DEBUG_SCAN("scan rejected: within previous scan period\n");
2986 2987
		queue_work(priv->workqueue, &priv->scan_completed);
		ret = 0;
Z
Zhu Yi 已提交
2988 2989
		goto out_unlock;
	}
2990

2991
	if (ssid_len) {
Z
Zhu Yi 已提交
2992
		priv->one_direct_scan = 1;
2993
		priv->direct_ssid_len =  min_t(u8, ssid_len, IW_ESSID_MAX_SIZE);
Z
Zhu Yi 已提交
2994
		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
2995
	} else {
M
Mohamed Abbas 已提交
2996
		priv->one_direct_scan = 0;
2997
	}
Z
Zhu Yi 已提交
2998

2999
	ret = iwl_scan_initiate(priv);
Z
Zhu Yi 已提交
3000 3001 3002 3003 3004

	IWL_DEBUG_MAC80211("leave\n");

out_unlock:
	spin_unlock_irqrestore(&priv->lock, flags);
3005
	mutex_unlock(&priv->mutex);
Z
Zhu Yi 已提交
3006

3007
	return ret;
Z
Zhu Yi 已提交
3008 3009
}

3010
static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
3011 3012 3013 3014
			struct ieee80211_key_conf *keyconf, const u8 *addr,
			u32 iv32, u16 *phase1key)
{

3015
	struct iwl_priv *priv = hw->priv;
3016 3017
	IWL_DEBUG_MAC80211("enter\n");

3018
	iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
3019 3020 3021 3022

	IWL_DEBUG_MAC80211("leave\n");
}

3023
static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Z
Zhu Yi 已提交
3024 3025 3026
			   const u8 *local_addr, const u8 *addr,
			   struct ieee80211_key_conf *key)
{
3027
	struct iwl_priv *priv = hw->priv;
3028 3029
	int ret = 0;
	u8 sta_id = IWL_INVALID_STATION;
3030
	u8 is_default_wep_key = 0;
Z
Zhu Yi 已提交
3031 3032 3033

	IWL_DEBUG_MAC80211("enter\n");

3034
	if (priv->hw_params.sw_crypto) {
Z
Zhu Yi 已提交
3035 3036 3037 3038 3039 3040 3041 3042
		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
		return -EOPNOTSUPP;
	}

	if (is_zero_ether_addr(addr))
		/* only support pairwise keys */
		return -EOPNOTSUPP;

3043
	sta_id = iwl_find_station(priv, addr);
3044
	if (sta_id == IWL_INVALID_STATION) {
J
Johannes Berg 已提交
3045 3046
		IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
				   addr);
3047
		return -EINVAL;
Z
Zhu Yi 已提交
3048

3049
	}
Z
Zhu Yi 已提交
3050

3051
	mutex_lock(&priv->mutex);
3052
	iwl_scan_cancel_timeout(priv, 100);
3053 3054 3055 3056 3057 3058
	mutex_unlock(&priv->mutex);

	/* If we are getting WEP group key and we didn't receive any key mapping
	 * so far, we are in legacy wep mode (group key only), otherwise we are
	 * in 1X mode.
	 * In legacy wep mode, we use another host command to the uCode */
T
Tomas Winkler 已提交
3059
	if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
3060
		priv->iw_mode != NL80211_IFTYPE_AP) {
3061 3062 3063
		if (cmd == SET_KEY)
			is_default_wep_key = !priv->key_mapping_key;
		else
3064 3065
			is_default_wep_key =
					(key->hw_key_idx == HW_KEY_DEFAULT);
3066
	}
3067

Z
Zhu Yi 已提交
3068
	switch (cmd) {
3069
	case SET_KEY:
3070 3071
		if (is_default_wep_key)
			ret = iwl_set_default_wep_key(priv, key);
3072
		else
3073
			ret = iwl_set_dynamic_key(priv, key, sta_id);
3074 3075

		IWL_DEBUG_MAC80211("enable hwcrypto key\n");
Z
Zhu Yi 已提交
3076 3077
		break;
	case DISABLE_KEY:
3078 3079
		if (is_default_wep_key)
			ret = iwl_remove_default_wep_key(priv, key);
3080
		else
3081
			ret = iwl_remove_dynamic_key(priv, key, sta_id);
3082 3083

		IWL_DEBUG_MAC80211("disable hwcrypto key\n");
Z
Zhu Yi 已提交
3084 3085
		break;
	default:
3086
		ret = -EINVAL;
Z
Zhu Yi 已提交
3087 3088 3089 3090
	}

	IWL_DEBUG_MAC80211("leave\n");

3091
	return ret;
Z
Zhu Yi 已提交
3092 3093
}

3094
static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
Z
Zhu Yi 已提交
3095 3096
			   const struct ieee80211_tx_queue_params *params)
{
3097
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
3098 3099 3100 3101 3102
	unsigned long flags;
	int q;

	IWL_DEBUG_MAC80211("enter\n");

3103
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
		IWL_DEBUG_MAC80211("leave - RF not ready\n");
		return -EIO;
	}

	if (queue >= AC_NUM) {
		IWL_DEBUG_MAC80211("leave - queue >= AC_NUM %d\n", queue);
		return 0;
	}

	q = AC_NUM - 1 - queue;

	spin_lock_irqsave(&priv->lock, flags);

	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
	priv->qos_data.def_qos_parm.ac[q].edca_txop =
3121
			cpu_to_le16((params->txop * 32));
Z
Zhu Yi 已提交
3122 3123 3124 3125

	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
	priv->qos_data.qos_active = 1;

3126
	if (priv->iw_mode == NL80211_IFTYPE_AP)
3127
		iwl_activate_qos(priv, 1);
3128
	else if (priv->assoc_id && iwl_is_associated(priv))
3129
		iwl_activate_qos(priv, 0);
Z
Zhu Yi 已提交
3130

3131
	spin_unlock_irqrestore(&priv->lock, flags);
Z
Zhu Yi 已提交
3132 3133 3134 3135 3136

	IWL_DEBUG_MAC80211("leave\n");
	return 0;
}

3137
static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3138
			     enum ieee80211_ampdu_mlme_action action,
3139
			     struct ieee80211_sta *sta, u16 tid, u16 *ssn)
3140 3141 3142
{
	struct iwl_priv *priv = hw->priv;

J
Johannes Berg 已提交
3143 3144
	IWL_DEBUG_HT("A-MPDU action on addr %pM tid %d\n",
		     sta->addr, tid);
3145 3146 3147 3148 3149 3150 3151

	if (!(priv->cfg->sku & IWL_SKU_N))
		return -EACCES;

	switch (action) {
	case IEEE80211_AMPDU_RX_START:
		IWL_DEBUG_HT("start Rx\n");
3152
		return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn);
3153 3154
	case IEEE80211_AMPDU_RX_STOP:
		IWL_DEBUG_HT("stop Rx\n");
3155
		return iwl_sta_rx_agg_stop(priv, sta->addr, tid);
3156 3157
	case IEEE80211_AMPDU_TX_START:
		IWL_DEBUG_HT("start Tx\n");
3158
		return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
3159 3160
	case IEEE80211_AMPDU_TX_STOP:
		IWL_DEBUG_HT("stop Tx\n");
3161
		return iwl_tx_agg_stop(priv, sta->addr, tid);
3162 3163 3164 3165 3166 3167 3168
	default:
		IWL_DEBUG_HT("unknown\n");
		return -EINVAL;
		break;
	}
	return 0;
}
3169

3170
static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
3171 3172
				struct ieee80211_tx_queue_stats *stats)
{
3173
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
3174
	int i, avail;
3175
	struct iwl_tx_queue *txq;
3176
	struct iwl_queue *q;
Z
Zhu Yi 已提交
3177 3178 3179 3180
	unsigned long flags;

	IWL_DEBUG_MAC80211("enter\n");

3181
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
3182 3183 3184 3185 3186 3187 3188 3189 3190
		IWL_DEBUG_MAC80211("leave - RF not ready\n");
		return -EIO;
	}

	spin_lock_irqsave(&priv->lock, flags);

	for (i = 0; i < AC_NUM; i++) {
		txq = &priv->txq[i];
		q = &txq->q;
3191
		avail = iwl_queue_space(q);
Z
Zhu Yi 已提交
3192

3193 3194 3195
		stats[i].len = q->n_window - avail;
		stats[i].limit = q->n_window - q->high_mark;
		stats[i].count = q->n_window;
Z
Zhu Yi 已提交
3196 3197 3198 3199 3200 3201 3202 3203 3204

	}
	spin_unlock_irqrestore(&priv->lock, flags);

	IWL_DEBUG_MAC80211("leave\n");

	return 0;
}

3205
static int iwl_mac_get_stats(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
3206 3207
			     struct ieee80211_low_level_stats *stats)
{
3208 3209 3210
	struct iwl_priv *priv = hw->priv;

	priv = hw->priv;
Z
Zhu Yi 已提交
3211 3212 3213 3214 3215 3216
	IWL_DEBUG_MAC80211("enter\n");
	IWL_DEBUG_MAC80211("leave\n");

	return 0;
}

3217
static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
3218
{
3219
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
3220 3221 3222 3223 3224 3225
	unsigned long flags;

	mutex_lock(&priv->mutex);
	IWL_DEBUG_MAC80211("enter\n");

	spin_lock_irqsave(&priv->lock, flags);
3226
	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
Z
Zhu Yi 已提交
3227 3228
	spin_unlock_irqrestore(&priv->lock, flags);

R
Ron Rindjunsky 已提交
3229
	iwl_reset_qos(priv);
Z
Zhu Yi 已提交
3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242

	spin_lock_irqsave(&priv->lock, flags);
	priv->assoc_id = 0;
	priv->assoc_capability = 0;
	priv->assoc_station_added = 0;

	/* new association get rid of ibss beacon skb */
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = NULL;

	priv->beacon_int = priv->hw->conf.beacon_int;
3243
	priv->timestamp = 0;
3244
	if ((priv->iw_mode == NL80211_IFTYPE_STATION))
Z
Zhu Yi 已提交
3245 3246 3247 3248
		priv->beacon_int = 0;

	spin_unlock_irqrestore(&priv->lock, flags);

3249
	if (!iwl_is_ready_rf(priv)) {
3250 3251 3252 3253 3254
		IWL_DEBUG_MAC80211("leave - not ready\n");
		mutex_unlock(&priv->mutex);
		return;
	}

3255 3256 3257
	/* we are restarting association process
	 * clear RXON_FILTER_ASSOC_MSK bit
	 */
3258
	if (priv->iw_mode != NL80211_IFTYPE_AP) {
3259
		iwl_scan_cancel_timeout(priv, 100);
3260
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
3261
		iwl_commit_rxon(priv);
3262 3263
	}

M
Mohamed Abbas 已提交
3264 3265
	iwl_power_update_mode(priv, 0);

Z
Zhu Yi 已提交
3266
	/* Per mac80211.h: This is only used in IBSS mode... */
3267
	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
3268

3269 3270 3271 3272 3273 3274 3275 3276 3277 3278
		/* switch to CAM during association period.
		 * the ucode will block any association/authentication
		 * frome during assiciation period if it can not hear
		 * the AP because of PM. the timer enable PM back is
		 * association do not complete
		 */
		if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN |
						     IEEE80211_CHAN_RADAR))
				iwl_power_disable_management(priv, 3000);

Z
Zhu Yi 已提交
3279 3280 3281 3282 3283
		IWL_DEBUG_MAC80211("leave - not in IBSS\n");
		mutex_unlock(&priv->mutex);
		return;
	}

3284
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
3285 3286 3287 3288 3289 3290

	mutex_unlock(&priv->mutex);

	IWL_DEBUG_MAC80211("leave\n");
}

3291
static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
Z
Zhu Yi 已提交
3292
{
3293
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
3294
	unsigned long flags;
A
Assaf Krauss 已提交
3295
	__le64 timestamp;
Z
Zhu Yi 已提交
3296 3297 3298

	IWL_DEBUG_MAC80211("enter\n");

3299
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
3300 3301 3302 3303
		IWL_DEBUG_MAC80211("leave - RF not ready\n");
		return -EIO;
	}

3304
	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
Z
Zhu Yi 已提交
3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
		IWL_DEBUG_MAC80211("leave - not IBSS\n");
		return -EIO;
	}

	spin_lock_irqsave(&priv->lock, flags);

	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = skb;

	priv->assoc_id = 0;
A
Assaf Krauss 已提交
3317
	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
3318
	priv->timestamp = le64_to_cpu(timestamp);
Z
Zhu Yi 已提交
3319 3320 3321 3322

	IWL_DEBUG_MAC80211("leave\n");
	spin_unlock_irqrestore(&priv->lock, flags);

R
Ron Rindjunsky 已提交
3323
	iwl_reset_qos(priv);
Z
Zhu Yi 已提交
3324

3325
	iwl_post_associate(priv);
Z
Zhu Yi 已提交
3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336


	return 0;
}

/*****************************************************************************
 *
 * sysfs attributes
 *
 *****************************************************************************/

3337
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
3338 3339 3340

/*
 * The following adds a new attribute to the sysfs representation
3341
 * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
Z
Zhu Yi 已提交
3342 3343 3344 3345 3346
 * used for controlling the debug level.
 *
 * See the level definitions in iwl for details.
 */

3347 3348
static ssize_t show_debug_level(struct device *d,
				struct device_attribute *attr, char *buf)
Z
Zhu Yi 已提交
3349
{
3350 3351 3352
	struct iwl_priv *priv = d->driver_data;

	return sprintf(buf, "0x%08X\n", priv->debug_level);
Z
Zhu Yi 已提交
3353
}
3354 3355
static ssize_t store_debug_level(struct device *d,
				struct device_attribute *attr,
Z
Zhu Yi 已提交
3356 3357
				 const char *buf, size_t count)
{
3358
	struct iwl_priv *priv = d->driver_data;
3359 3360
	unsigned long val;
	int ret;
Z
Zhu Yi 已提交
3361

3362 3363
	ret = strict_strtoul(buf, 0, &val);
	if (ret)
T
Tomas Winkler 已提交
3364
		IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
Z
Zhu Yi 已提交
3365
	else
3366
		priv->debug_level = val;
Z
Zhu Yi 已提交
3367 3368 3369 3370

	return strnlen(buf, count);
}

3371 3372 3373
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
			show_debug_level, store_debug_level);

Z
Zhu Yi 已提交
3374

3375
#endif /* CONFIG_IWLWIFI_DEBUG */
Z
Zhu Yi 已提交
3376 3377


3378 3379 3380 3381
static ssize_t show_version(struct device *d,
				struct device_attribute *attr, char *buf)
{
	struct iwl_priv *priv = d->driver_data;
3382
	struct iwl_alive_resp *palive = &priv->card_alive;
3383 3384
	ssize_t pos = 0;
	u16 eeprom_ver;
3385 3386

	if (palive->is_valid)
3387 3388 3389
		pos += sprintf(buf + pos,
				"fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
				"fw type: 0x%01X 0x%01X\n",
3390 3391 3392 3393
				palive->ucode_major, palive->ucode_minor,
				palive->sw_rev[0], palive->sw_rev[1],
				palive->ver_type, palive->ver_subtype);
	else
3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404
		pos += sprintf(buf + pos, "fw not loaded\n");

	if (priv->eeprom) {
		eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
		pos += sprintf(buf + pos, "EEPROM version: 0x%x\n",
				 eeprom_ver);
	} else {
		pos += sprintf(buf + pos, "EEPROM not initialzed\n");
	}

	return pos;
3405 3406 3407 3408
}

static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);

Z
Zhu Yi 已提交
3409 3410 3411
static ssize_t show_temperature(struct device *d,
				struct device_attribute *attr, char *buf)
{
3412
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
3413

3414
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
3415 3416
		return -EAGAIN;

3417
	return sprintf(buf, "%d\n", priv->temperature);
Z
Zhu Yi 已提交
3418 3419 3420 3421 3422 3423 3424
}

static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);

static ssize_t show_tx_power(struct device *d,
			     struct device_attribute *attr, char *buf)
{
3425
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
3426 3427 3428 3429 3430

	if (!iwl_is_ready_rf(priv))
		return sprintf(buf, "off\n");
	else
		return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
Z
Zhu Yi 已提交
3431 3432 3433 3434 3435 3436
}

static ssize_t store_tx_power(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
3437
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
3438 3439
	unsigned long val;
	int ret;
Z
Zhu Yi 已提交
3440

3441 3442
	ret = strict_strtoul(buf, 10, &val);
	if (ret)
T
Tomas Winkler 已提交
3443
		IWL_INFO(priv, "%s is not in decimal form.\n", buf);
Z
Zhu Yi 已提交
3444
	else
3445
		iwl_set_tx_power(priv, val, false);
Z
Zhu Yi 已提交
3446 3447 3448 3449 3450 3451 3452 3453 3454

	return count;
}

static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);

static ssize_t show_flags(struct device *d,
			  struct device_attribute *attr, char *buf)
{
3455
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
3456 3457 3458 3459 3460 3461 3462 3463

	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
}

static ssize_t store_flags(struct device *d,
			   struct device_attribute *attr,
			   const char *buf, size_t count)
{
3464
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
3465 3466 3467
	unsigned long val;
	u32 flags;
	int ret = strict_strtoul(buf, 0, &val);
3468
	if (ret)
3469 3470
		return ret;
	flags = (u32)val;
Z
Zhu Yi 已提交
3471 3472 3473 3474

	mutex_lock(&priv->mutex);
	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
		/* Cancel any currently running scans... */
3475
		if (iwl_scan_cancel_timeout(priv, 100))
3476
			IWL_WARN(priv, "Could not cancel scan.\n");
Z
Zhu Yi 已提交
3477
		else {
3478
			IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags);
Z
Zhu Yi 已提交
3479
			priv->staging_rxon.flags = cpu_to_le32(flags);
3480
			iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492
		}
	}
	mutex_unlock(&priv->mutex);

	return count;
}

static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);

static ssize_t show_filter_flags(struct device *d,
				 struct device_attribute *attr, char *buf)
{
3493
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
3494 3495 3496 3497 3498 3499 3500 3501 3502

	return sprintf(buf, "0x%04X\n",
		le32_to_cpu(priv->active_rxon.filter_flags));
}

static ssize_t store_filter_flags(struct device *d,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
3503
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
3504 3505 3506
	unsigned long val;
	u32 filter_flags;
	int ret = strict_strtoul(buf, 0, &val);
3507
	if (ret)
3508 3509
		return ret;
	filter_flags = (u32)val;
Z
Zhu Yi 已提交
3510 3511 3512 3513

	mutex_lock(&priv->mutex);
	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
		/* Cancel any currently running scans... */
3514
		if (iwl_scan_cancel_timeout(priv, 100))
3515
			IWL_WARN(priv, "Could not cancel scan.\n");
Z
Zhu Yi 已提交
3516 3517 3518 3519 3520
		else {
			IWL_DEBUG_INFO("Committing rxon.filter_flags = "
				       "0x%04X\n", filter_flags);
			priv->staging_rxon.filter_flags =
				cpu_to_le32(filter_flags);
3521
			iwl_commit_rxon(priv);
Z
Zhu Yi 已提交
3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535
		}
	}
	mutex_unlock(&priv->mutex);

	return count;
}

static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
		   store_filter_flags);

static ssize_t store_power_level(struct device *d,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
3536
	struct iwl_priv *priv = dev_get_drvdata(d);
3537
	int ret;
3538 3539
	unsigned long mode;

Z
Zhu Yi 已提交
3540 3541 3542

	mutex_lock(&priv->mutex);

3543
	if (!iwl_is_ready(priv)) {
3544
		ret = -EAGAIN;
Z
Zhu Yi 已提交
3545 3546 3547
		goto out;
	}

3548
	ret = strict_strtoul(buf, 10, &mode);
3549
	if (ret)
3550 3551
		goto out;

3552 3553
	ret = iwl_power_set_user_mode(priv, mode);
	if (ret) {
M
Mohamed Abbas 已提交
3554 3555
		IWL_DEBUG_MAC80211("failed setting power mode.\n");
		goto out;
Z
Zhu Yi 已提交
3556
	}
3557
	ret = count;
Z
Zhu Yi 已提交
3558 3559 3560

 out:
	mutex_unlock(&priv->mutex);
3561
	return ret;
Z
Zhu Yi 已提交
3562 3563 3564 3565 3566
}

static ssize_t show_power_level(struct device *d,
				struct device_attribute *attr, char *buf)
{
3567
	struct iwl_priv *priv = dev_get_drvdata(d);
3568 3569
	int mode = priv->power_data.user_power_setting;
	int system = priv->power_data.system_power_setting;
M
Mohamed Abbas 已提交
3570
	int level = priv->power_data.power_mode;
Z
Zhu Yi 已提交
3571 3572
	char *p = buf;

3573 3574 3575
	switch (system) {
	case IWL_POWER_SYS_AUTO:
		p += sprintf(p, "SYSTEM:auto");
Z
Zhu Yi 已提交
3576
		break;
3577 3578 3579 3580 3581
	case IWL_POWER_SYS_AC:
		p += sprintf(p, "SYSTEM:ac");
		break;
	case IWL_POWER_SYS_BATTERY:
		p += sprintf(p, "SYSTEM:battery");
Z
Zhu Yi 已提交
3582 3583
		break;
	}
3584

3585 3586
	p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
			"fixed" : "auto");
3587 3588
	p += sprintf(p, "\tINDEX:%d", level);
	p += sprintf(p, "\n");
3589
	return p - buf + 1;
Z
Zhu Yi 已提交
3590 3591 3592 3593 3594 3595 3596 3597 3598
}

static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
		   store_power_level);


static ssize_t show_statistics(struct device *d,
			       struct device_attribute *attr, char *buf)
{
3599
	struct iwl_priv *priv = dev_get_drvdata(d);
3600
	u32 size = sizeof(struct iwl_notif_statistics);
Z
Zhu Yi 已提交
3601
	u32 len = 0, ofs = 0;
3602
	u8 *data = (u8 *)&priv->statistics;
Z
Zhu Yi 已提交
3603 3604
	int rc = 0;

3605
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
3606 3607 3608
		return -EAGAIN;

	mutex_lock(&priv->mutex);
3609
	rc = iwl_send_statistics_request(priv, 0);
Z
Zhu Yi 已提交
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640
	mutex_unlock(&priv->mutex);

	if (rc) {
		len = sprintf(buf,
			      "Error sending statistics request: 0x%08X\n", rc);
		return len;
	}

	while (size && (PAGE_SIZE - len)) {
		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
				   PAGE_SIZE - len, 1);
		len = strlen(buf);
		if (PAGE_SIZE - len)
			buf[len++] = '\n';

		ofs += 16;
		size -= min(size, 16U);
	}

	return len;
}

static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);


/*****************************************************************************
 *
 * driver setup and teardown
 *
 *****************************************************************************/

3641
static void iwl_setup_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3642 3643 3644 3645 3646
{
	priv->workqueue = create_workqueue(DRV_NAME);

	init_waitqueue_head(&priv->wait_command_queue);

3647 3648 3649 3650 3651
	INIT_WORK(&priv->up, iwl_bg_up);
	INIT_WORK(&priv->restart, iwl_bg_restart);
	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
3652
	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
3653 3654
	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
3655 3656

	iwl_setup_scan_deferred_work(priv);
3657
	iwl_setup_power_deferred_work(priv);
C
Christoph Hellwig 已提交
3658

3659 3660 3661 3662 3663
	if (priv->cfg->ops->lib->setup_deferred_work)
		priv->cfg->ops->lib->setup_deferred_work(priv);

	init_timer(&priv->statistics_periodic);
	priv->statistics_periodic.data = (unsigned long)priv;
3664
	priv->statistics_periodic.function = iwl_bg_statistics_periodic;
Z
Zhu Yi 已提交
3665 3666

	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
3667
		     iwl_irq_tasklet, (unsigned long)priv);
Z
Zhu Yi 已提交
3668 3669
}

3670
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3671
{
3672 3673
	if (priv->cfg->ops->lib->cancel_deferred_work)
		priv->cfg->ops->lib->cancel_deferred_work(priv);
Z
Zhu Yi 已提交
3674

3675
	cancel_delayed_work_sync(&priv->init_alive_start);
Z
Zhu Yi 已提交
3676
	cancel_delayed_work(&priv->scan_check);
3677
	cancel_delayed_work_sync(&priv->set_power_save);
Z
Zhu Yi 已提交
3678 3679
	cancel_delayed_work(&priv->alive_start);
	cancel_work_sync(&priv->beacon_update);
3680
	del_timer_sync(&priv->statistics_periodic);
Z
Zhu Yi 已提交
3681 3682
}

3683
static struct attribute *iwl_sysfs_entries[] = {
Z
Zhu Yi 已提交
3684 3685 3686 3687 3688 3689
	&dev_attr_flags.attr,
	&dev_attr_filter_flags.attr,
	&dev_attr_power_level.attr,
	&dev_attr_statistics.attr,
	&dev_attr_temperature.attr,
	&dev_attr_tx_power.attr,
3690 3691 3692
#ifdef CONFIG_IWLWIFI_DEBUG
	&dev_attr_debug_level.attr,
#endif
3693
	&dev_attr_version.attr,
Z
Zhu Yi 已提交
3694 3695 3696 3697

	NULL
};

3698
static struct attribute_group iwl_attribute_group = {
Z
Zhu Yi 已提交
3699
	.name = NULL,		/* put in device directory */
3700
	.attrs = iwl_sysfs_entries,
Z
Zhu Yi 已提交
3701 3702
};

3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719
static struct ieee80211_ops iwl_hw_ops = {
	.tx = iwl_mac_tx,
	.start = iwl_mac_start,
	.stop = iwl_mac_stop,
	.add_interface = iwl_mac_add_interface,
	.remove_interface = iwl_mac_remove_interface,
	.config = iwl_mac_config,
	.config_interface = iwl_mac_config_interface,
	.configure_filter = iwl_configure_filter,
	.set_key = iwl_mac_set_key,
	.update_tkip_key = iwl_mac_update_tkip_key,
	.get_stats = iwl_mac_get_stats,
	.get_tx_stats = iwl_mac_get_tx_stats,
	.conf_tx = iwl_mac_conf_tx,
	.reset_tsf = iwl_mac_reset_tsf,
	.bss_info_changed = iwl_bss_info_changed,
	.ampdu_action = iwl_mac_ampdu_action,
3720
	.hw_scan = iwl_mac_hw_scan
Z
Zhu Yi 已提交
3721 3722
};

3723
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Z
Zhu Yi 已提交
3724 3725
{
	int err = 0;
3726
	struct iwl_priv *priv;
Z
Zhu Yi 已提交
3727
	struct ieee80211_hw *hw;
T
Tomas Winkler 已提交
3728
	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
3729
	unsigned long flags;
Z
Zhu Yi 已提交
3730

3731 3732 3733 3734
	/************************
	 * 1. Allocating HW data
	 ************************/

3735 3736
	/* Disabling hardware scan means that mac80211 will perform scans
	 * "the hard way", rather than using device's scan. */
3737
	if (cfg->mod_params->disable_hw_scan) {
3738 3739 3740
		if (cfg->mod_params->debug & IWL_DL_INFO)
			dev_printk(KERN_DEBUG, &(pdev->dev),
				   "Disabling hw_scan\n");
3741
		iwl_hw_ops.hw_scan = NULL;
Z
Zhu Yi 已提交
3742 3743
	}

3744
	hw = iwl_alloc_all(cfg, &iwl_hw_ops);
3745
	if (!hw) {
Z
Zhu Yi 已提交
3746 3747 3748
		err = -ENOMEM;
		goto out;
	}
3749 3750 3751
	priv = hw->priv;
	/* At this point both hw and priv are allocated. */

Z
Zhu Yi 已提交
3752 3753 3754
	SET_IEEE80211_DEV(hw, &pdev->dev);

	IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
T
Tomas Winkler 已提交
3755
	priv->cfg = cfg;
Z
Zhu Yi 已提交
3756
	priv->pci_dev = pdev;
3757

3758
#ifdef CONFIG_IWLWIFI_DEBUG
3759
	priv->debug_level = priv->cfg->mod_params->debug;
Z
Zhu Yi 已提交
3760 3761 3762
	atomic_set(&priv->restrict_refcnt, 0);
#endif

3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
	/**************************
	 * 2. Initializing PCI bus
	 **************************/
	if (pci_enable_device(pdev)) {
		err = -ENODEV;
		goto out_ieee80211_free_hw;
	}

	pci_set_master(pdev);

W
Winkler, Tomas 已提交
3773
	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
3774
	if (!err)
W
Winkler, Tomas 已提交
3775
		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
3776
	if (err) {
W
Winkler, Tomas 已提交
3777
		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
3778
		if (!err)
W
Winkler, Tomas 已提交
3779
			err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
3780
		/* both attempts failed: */
3781
		if (err) {
T
Tomas Winkler 已提交
3782
			IWL_WARN(priv, "No suitable DMA available.\n");
3783
			goto out_pci_disable_device;
3784
		}
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806
	}

	err = pci_request_regions(pdev, DRV_NAME);
	if (err)
		goto out_pci_disable_device;

	pci_set_drvdata(pdev, priv);


	/***********************
	 * 3. Read REV register
	 ***********************/
	priv->hw_base = pci_iomap(pdev, 0, 0);
	if (!priv->hw_base) {
		err = -ENODEV;
		goto out_pci_release_regions;
	}

	IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
		(unsigned long long) pci_resource_len(pdev, 0));
	IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);

3807
	iwl_hw_detect(priv);
T
Tomas Winkler 已提交
3808
	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
3809
		priv->cfg->name, priv->hw_rev);
3810

3811 3812 3813 3814
	/* 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);

T
Tomas Winkler 已提交
3815 3816
	/* amp init */
	err = priv->cfg->ops->lib->apm_ops.init(priv);
3817
	if (err < 0) {
T
Tomas Winkler 已提交
3818
		IWL_DEBUG_INFO("Failed to init APMG\n");
3819 3820
		goto out_iounmap;
	}
T
Tomas Winkler 已提交
3821 3822 3823
	/*****************
	 * 4. Read EEPROM
	 *****************/
3824 3825 3826
	/* Read the EEPROM */
	err = iwl_eeprom_init(priv);
	if (err) {
3827
		IWL_ERR(priv, "Unable to init EEPROM\n");
3828 3829
		goto out_iounmap;
	}
3830 3831 3832 3833
	err = iwl_eeprom_check_version(priv);
	if (err)
		goto out_iounmap;

3834
	/* extract MAC Address */
3835
	iwl_eeprom_get_mac(priv, priv->mac_addr);
J
Johannes Berg 已提交
3836
	IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
3837 3838 3839 3840 3841
	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);

	/************************
	 * 5. Setup HW constants
	 ************************/
3842
	if (iwl_set_hw_params(priv)) {
3843
		IWL_ERR(priv, "failed to set hw parameters\n");
3844
		goto out_free_eeprom;
3845 3846 3847
	}

	/*******************
T
Tomas Winkler 已提交
3848
	 * 6. Setup priv
3849
	 *******************/
Z
Zhu Yi 已提交
3850

T
Tomas Winkler 已提交
3851
	err = iwl_init_drv(priv);
3852
	if (err)
R
Ron Rindjunsky 已提交
3853
		goto out_free_eeprom;
3854
	/* At this point both hw and priv are initialized. */
3855 3856 3857 3858 3859 3860

	/**********************************
	 * 7. Initialize module parameters
	 **********************************/

	/* Disable radio (SW RF KILL) via parameter when loading driver */
3861
	if (priv->cfg->mod_params->disable) {
3862 3863 3864 3865 3866 3867 3868
		set_bit(STATUS_RF_KILL_SW, &priv->status);
		IWL_DEBUG_INFO("Radio disabled.\n");
	}

	/********************
	 * 8. Setup services
	 ********************/
3869
	spin_lock_irqsave(&priv->lock, flags);
3870
	iwl_disable_interrupts(priv);
3871
	spin_unlock_irqrestore(&priv->lock, flags);
3872

3873
	err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
3874
	if (err) {
3875
		IWL_ERR(priv, "failed to create sysfs device attributes\n");
T
Tomas Winkler 已提交
3876
		goto out_uninit_drv;
3877 3878 3879
	}


3880
	iwl_setup_deferred_work(priv);
3881
	iwl_setup_rx_handlers(priv);
3882 3883 3884 3885

	/********************
	 * 9. Conclude
	 ********************/
3886 3887
	pci_save_state(pdev);
	pci_disable_device(pdev);
Z
Zhu Yi 已提交
3888

T
Tomas Winkler 已提交
3889 3890 3891 3892 3893 3894 3895 3896 3897 3898
	/**********************************
	 * 10. Setup and register mac80211
	 **********************************/

	err = iwl_setup_mac(priv);
	if (err)
		goto out_remove_sysfs;

	err = iwl_dbgfs_register(priv, DRV_NAME);
	if (err)
3899
		IWL_ERR(priv, "failed to create debugfs files\n");
T
Tomas Winkler 已提交
3900

3901 3902
	err = iwl_rfkill_init(priv);
	if (err)
3903
		IWL_ERR(priv, "Unable to initialize RFKILL system. "
3904 3905
				  "Ignoring error: %d\n", err);
	iwl_power_initialize(priv);
Z
Zhu Yi 已提交
3906 3907
	return 0;

3908
 out_remove_sysfs:
3909
	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
T
Tomas Winkler 已提交
3910 3911
 out_uninit_drv:
	iwl_uninit_drv(priv);
3912 3913
 out_free_eeprom:
	iwl_eeprom_free(priv);
Z
Zhu Yi 已提交
3914 3915 3916 3917
 out_iounmap:
	pci_iounmap(pdev, priv->hw_base);
 out_pci_release_regions:
	pci_release_regions(pdev);
3918
	pci_set_drvdata(pdev, NULL);
Z
Zhu Yi 已提交
3919 3920 3921 3922 3923 3924 3925 3926
 out_pci_disable_device:
	pci_disable_device(pdev);
 out_ieee80211_free_hw:
	ieee80211_free_hw(priv->hw);
 out:
	return err;
}

3927
static void __devexit iwl_pci_remove(struct pci_dev *pdev)
Z
Zhu Yi 已提交
3928
{
3929
	struct iwl_priv *priv = pci_get_drvdata(pdev);
3930
	unsigned long flags;
Z
Zhu Yi 已提交
3931 3932 3933 3934 3935 3936

	if (!priv)
		return;

	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");

3937
	iwl_dbgfs_unregister(priv);
3938
	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
3939

3940 3941
	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
	 * to be called and iwl_down since we are removing the device
3942 3943 3944
	 * we need to set STATUS_EXIT_PENDING bit.
	 */
	set_bit(STATUS_EXIT_PENDING, &priv->status);
3945 3946 3947
	if (priv->mac80211_registered) {
		ieee80211_unregister_hw(priv->hw);
		priv->mac80211_registered = 0;
3948
	} else {
3949
		iwl_down(priv);
3950 3951
	}

3952 3953 3954 3955
	/* make sure we flush any pending irq or
	 * tasklet for the driver
	 */
	spin_lock_irqsave(&priv->lock, flags);
3956
	iwl_disable_interrupts(priv);
3957 3958 3959 3960
	spin_unlock_irqrestore(&priv->lock, flags);

	iwl_synchronize_irq(priv);

3961
	iwl_rfkill_unregister(priv);
3962
	iwl_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
3963 3964

	if (priv->rxq.bd)
3965
		iwl_rx_queue_free(priv, &priv->rxq);
3966
	iwl_hw_txq_ctx_free(priv);
Z
Zhu Yi 已提交
3967

3968
	iwl_clear_stations_table(priv);
3969
	iwl_eeprom_free(priv);
Z
Zhu Yi 已提交
3970 3971


M
Mohamed Abbas 已提交
3972 3973 3974
	/*netif_stop_queue(dev); */
	flush_workqueue(priv->workqueue);

3975
	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
Z
Zhu Yi 已提交
3976 3977 3978 3979 3980 3981 3982 3983 3984 3985
	 * priv->workqueue... so we can't take down the workqueue
	 * until now... */
	destroy_workqueue(priv->workqueue);
	priv->workqueue = NULL;

	pci_iounmap(pdev, priv->hw_base);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);

T
Tomas Winkler 已提交
3986
	iwl_uninit_drv(priv);
Z
Zhu Yi 已提交
3987 3988 3989 3990 3991 3992 3993 3994 3995

	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	ieee80211_free_hw(priv->hw);
}

#ifdef CONFIG_PM

3996
static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
Z
Zhu Yi 已提交
3997
{
3998
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
3999

4000 4001
	if (priv->is_open) {
		set_bit(STATUS_IN_SUSPEND, &priv->status);
4002
		iwl_mac_stop(priv->hw);
4003 4004
		priv->is_open = 1;
	}
Z
Zhu Yi 已提交
4005 4006 4007 4008 4009 4010

	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

4011
static int iwl_pci_resume(struct pci_dev *pdev)
Z
Zhu Yi 已提交
4012
{
4013
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
4014 4015 4016

	pci_set_power_state(pdev, PCI_D0);

4017
	if (priv->is_open)
4018
		iwl_mac_start(priv->hw);
Z
Zhu Yi 已提交
4019

4020
	clear_bit(STATUS_IN_SUSPEND, &priv->status);
Z
Zhu Yi 已提交
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031
	return 0;
}

#endif /* CONFIG_PM */

/*****************************************************************************
 *
 * driver and module entry point
 *
 *****************************************************************************/

4032 4033
/* Hardware specific file defines the PCI IDs table for that hardware module */
static struct pci_device_id iwl_hw_card_ids[] = {
T
Tomas Winkler 已提交
4034
#ifdef CONFIG_IWL4965
4035 4036
	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
T
Tomas Winkler 已提交
4037
#endif /* CONFIG_IWL4965 */
4038
#ifdef CONFIG_IWL5000
4039 4040 4041 4042 4043 4044
	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
4045
	{IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
4046 4047 4048
	{IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
	{IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
	{IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
4049 4050 4051 4052
/* 5350 WiFi/WiMax */
	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
T
Tomas Winkler 已提交
4053 4054 4055
/* 5150 Wifi/WiMax */
	{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
	{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
4056
#endif /* CONFIG_IWL5000 */
T
Tomas Winkler 已提交
4057

4058 4059 4060 4061 4062
	{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);

static struct pci_driver iwl_driver = {
Z
Zhu Yi 已提交
4063
	.name = DRV_NAME,
4064
	.id_table = iwl_hw_card_ids,
4065 4066
	.probe = iwl_pci_probe,
	.remove = __devexit_p(iwl_pci_remove),
Z
Zhu Yi 已提交
4067
#ifdef CONFIG_PM
4068 4069
	.suspend = iwl_pci_suspend,
	.resume = iwl_pci_resume,
Z
Zhu Yi 已提交
4070 4071 4072
#endif
};

4073
static int __init iwl_init(void)
Z
Zhu Yi 已提交
4074 4075 4076 4077 4078
{

	int ret;
	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
4079

4080
	ret = iwlagn_rate_control_register();
4081
	if (ret) {
4082 4083
		printk(KERN_ERR DRV_NAME
		       "Unable to register rate control algorithm: %d\n", ret);
4084 4085 4086
		return ret;
	}

4087
	ret = pci_register_driver(&iwl_driver);
Z
Zhu Yi 已提交
4088
	if (ret) {
4089
		printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
4090
		goto error_register;
Z
Zhu Yi 已提交
4091 4092 4093
	}

	return ret;
4094 4095

error_register:
4096
	iwlagn_rate_control_unregister();
4097
	return ret;
Z
Zhu Yi 已提交
4098 4099
}

4100
static void __exit iwl_exit(void)
Z
Zhu Yi 已提交
4101
{
4102
	pci_unregister_driver(&iwl_driver);
4103
	iwlagn_rate_control_unregister();
Z
Zhu Yi 已提交
4104 4105
}

4106 4107
module_exit(iwl_exit);
module_init(iwl_init);