iwl4965-base.c 184.4 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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 *
 * 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:
 * James P. Ketrenos <ipw2100-admin@linux.intel.com>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.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>

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

56
static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
57
				  struct iwl_tx_queue *txq);
58

Z
Zhu Yi 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71
/******************************************************************************
 *
 * module boiler plate
 *
 ******************************************************************************/

/*
 * module name, copyright, version, etc.
 * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
 */

#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link 4965AGN driver for Linux"

72
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
73 74 75 76 77
#define VD "d"
#else
#define VD
#endif

78
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
79 80 81 82 83
#define VS "s"
#else
#define VS
#endif

T
Tomas Winkler 已提交
84
#define DRV_VERSION     IWLWIFI_VERSION VD VS
Z
Zhu Yi 已提交
85 86 87 88 89 90 91


MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");

92
static const struct ieee80211_supported_band *iwl_get_hw_mode(
93
		struct iwl_priv *priv, enum ieee80211_band band)
Z
Zhu Yi 已提交
94
{
95
	return priv->hw->wiphy->bands[band];
Z
Zhu Yi 已提交
96 97
}

C
Christoph Hellwig 已提交
98
static int iwl4965_is_empty_essid(const char *essid, int essid_len)
Z
Zhu Yi 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
{
	/* Single white space is for Linksys APs */
	if (essid_len == 1 && essid[0] == ' ')
		return 1;

	/* Otherwise, if the entire essid is 0, we assume it is hidden */
	while (essid_len) {
		essid_len--;
		if (essid[essid_len] != '\0')
			return 0;
	}

	return 1;
}

C
Christoph Hellwig 已提交
114
static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
Z
Zhu Yi 已提交
115 116 117 118 119
{
	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
	const char *s = essid;
	char *d = escaped;

C
Christoph Hellwig 已提交
120
	if (iwl4965_is_empty_essid(essid, essid_len)) {
Z
Zhu Yi 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
		return escaped;
	}

	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
	while (essid_len--) {
		if (*s == '\0') {
			*d++ = '\\';
			*d++ = '0';
			s++;
		} else
			*d++ = *s++;
	}
	*d = '\0';
	return escaped;
}

138

Z
Zhu Yi 已提交
139 140 141 142 143
/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
 * DMA services
 *
 * Theory of operation
 *
144 145 146 147 148 149 150 151 152
 * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
 * of buffer descriptors, each of which points to one or more data buffers for
 * the device to read from or fill.  Driver and device exchange status of each
 * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
 * entries in each circular buffer, to protect against confusing empty and full
 * queue states.
 *
 * The device reads or writes the data in the queues via the device's several
 * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
Z
Zhu Yi 已提交
153 154 155 156 157 158
 *
 * For Tx queue, there are low mark and high mark limits. If, after queuing
 * the packet for Tx, free space become < low mark, Tx queue stopped. When
 * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
 * Tx queue resumed.
 *
159 160 161
 * The 4965 operates with up to 17 queues:  One receive queue, one transmit
 * queue (#4) for sending commands to the device firmware, and 15 other
 * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels.
B
Ben Cahill 已提交
162 163
 *
 * See more detailed info in iwl-4965-hw.h.
Z
Zhu Yi 已提交
164 165
 ***************************************************/

166
int iwl_queue_space(const struct iwl_queue *q)
Z
Zhu Yi 已提交
167
{
168
	int s = q->read_ptr - q->write_ptr;
Z
Zhu Yi 已提交
169

170
	if (q->read_ptr > q->write_ptr)
Z
Zhu Yi 已提交
171 172 173 174 175 176 177 178 179 180 181 182
		s -= q->n_bd;

	if (s <= 0)
		s += q->n_window;
	/* keep some reserve to not confuse empty and full situations */
	s -= 2;
	if (s < 0)
		s = 0;
	return s;
}


183
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
Z
Zhu Yi 已提交
184
{
185 186 187
	return q->write_ptr > q->read_ptr ?
		(i >= q->read_ptr && i < q->write_ptr) :
		!(i < q->read_ptr && i >= q->write_ptr);
Z
Zhu Yi 已提交
188 189
}

190
static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
Z
Zhu Yi 已提交
191
{
192
	/* This is for scan command, the big buffer at end of command array */
Z
Zhu Yi 已提交
193
	if (is_huge)
194
		return q->n_window;	/* must be power of 2 */
Z
Zhu Yi 已提交
195

196
	/* Otherwise, use normal size buffers */
Z
Zhu Yi 已提交
197 198 199 200 201
	return index & (q->n_window - 1);
}


/*************** STATION TABLE MANAGEMENT ****
202
 * mac80211 should be examined to determine if sta_info is duplicating
Z
Zhu Yi 已提交
203 204 205 206 207
 * the functionality provided here
 */

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

208
#if 0 /* temporary disable till we add real remove station */
209 210 211 212 213
/**
 * iwl4965_remove_station - Remove driver's knowledge of station.
 *
 * NOTE:  This does not remove station from device's station table.
 */
214
static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
Z
Zhu Yi 已提交
215 216 217 218 219 220 221 222 223 224
{
	int index = IWL_INVALID_STATION;
	int i;
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);

	if (is_ap)
		index = IWL_AP_ID;
	else if (is_broadcast_ether_addr(addr))
T
Tomas Winkler 已提交
225
		index = priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
226
	else
T
Tomas Winkler 已提交
227
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
Z
Zhu Yi 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
			if (priv->stations[i].used &&
			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
						addr)) {
				index = i;
				break;
			}

	if (unlikely(index == IWL_INVALID_STATION))
		goto out;

	if (priv->stations[index].used) {
		priv->stations[index].used = 0;
		priv->num_stations--;
	}

	BUG_ON(priv->num_stations < 0);

out:
	spin_unlock_irqrestore(&priv->sta_lock, flags);
	return 0;
}
249
#endif
Z
Zhu Yi 已提交
250 251 252 253 254 255



/*************** HOST COMMAND QUEUE FUNCTIONS   *****/

/**
C
Christoph Hellwig 已提交
256
 * iwl4965_enqueue_hcmd - enqueue a uCode command
Z
Zhu Yi 已提交
257 258 259 260 261 262 263
 * @priv: device private data point
 * @cmd: a point to the ucode command structure
 *
 * The function returns < 0 values to indicate the operation is
 * failed. On success, it turns the index (> 0) of command in the
 * command queue.
 */
264
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
Z
Zhu Yi 已提交
265
{
266
	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
267
	struct iwl_queue *q = &txq->q;
268
	struct iwl_tfd_frame *tfd;
Z
Zhu Yi 已提交
269
	u32 *control_flags;
270
	struct iwl_cmd *out_cmd;
Z
Zhu Yi 已提交
271
	u32 idx;
G
Gregory Greenman 已提交
272
	u16 fix_size;
Z
Zhu Yi 已提交
273 274 275 276
	dma_addr_t phys_addr;
	int ret;
	unsigned long flags;

G
Gregory Greenman 已提交
277 278 279
	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));

Z
Zhu Yi 已提交
280 281 282 283 284 285
	/* If any of the command structures end up being larger than
	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
	 * we will need to increase the size of the TFD entries */
	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
	       !(cmd->meta.flags & CMD_SIZE_HUGE));

286
	if (iwl_is_rfkill(priv)) {
287 288 289 290
		IWL_DEBUG_INFO("Not sending command - RF KILL");
		return -EIO;
	}

291
	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
Z
Zhu Yi 已提交
292 293 294 295 296 297
		IWL_ERROR("No space for Tx\n");
		return -ENOSPC;
	}

	spin_lock_irqsave(&priv->hcmd_lock, flags);

298
	tfd = &txq->bd[q->write_ptr];
Z
Zhu Yi 已提交
299 300 301 302
	memset(tfd, 0, sizeof(*tfd));

	control_flags = (u32 *) tfd;

303
	idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
Z
Zhu Yi 已提交
304 305 306 307 308 309 310 311 312 313 314
	out_cmd = &txq->cmd[idx];

	out_cmd->hdr.cmd = cmd->id;
	memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);

	/* At this point, the out_cmd now has all of the incoming cmd
	 * information */

	out_cmd->hdr.flags = 0;
	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
315
			INDEX_TO_SEQ(q->write_ptr));
Z
Zhu Yi 已提交
316 317 318 319
	if (out_cmd->meta.flags & CMD_SIZE_HUGE)
		out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);

	phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
320
			offsetof(struct iwl_cmd, hdr);
C
Christoph Hellwig 已提交
321
	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
Z
Zhu Yi 已提交
322 323 324 325 326

	IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
		     "%d bytes at %d[%d]:%d\n",
		     get_cmd_string(out_cmd->hdr.cmd),
		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
327
		     fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
Z
Zhu Yi 已提交
328 329

	txq->need_update = 1;
330 331

	/* Set up entry in queue's byte count circular buffer */
332
	priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
333 334

	/* Increment and update queue's write index */
T
Tomas Winkler 已提交
335
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
336
	ret = iwl_txq_update_write_ptr(priv, txq);
Z
Zhu Yi 已提交
337 338 339 340 341

	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
	return ret ? ret : idx;
}

342 343
static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
G
Gregory Greenman 已提交
344
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
345 346 347 348 349 350 351 352

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

}

Z
Zhu Yi 已提交
353
/**
C
Christoph Hellwig 已提交
354
 * iwl4965_check_rxon_cmd - validate RXON structure is valid
Z
Zhu Yi 已提交
355 356 357 358 359
 *
 * NOTE:  This is really only useful during development and can eventually
 * be #ifdef'd out once the driver is stable and folks aren't actively
 * making changes
 */
G
Gregory Greenman 已提交
360
static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
Z
Zhu Yi 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
{
	int error = 0;
	int counter = 1;

	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
		error |= le32_to_cpu(rxon->flags &
				(RXON_FLG_TGJ_NARROW_BAND_MSK |
				 RXON_FLG_RADAR_DETECT_MSK));
		if (error)
			IWL_WARNING("check 24G fields %d | %d\n",
				    counter++, error);
	} else {
		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
		if (error)
			IWL_WARNING("check 52 fields %d | %d\n",
				    counter++, error);
		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
		if (error)
			IWL_WARNING("check 52 CCK %d | %d\n",
				    counter++, error);
	}
	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
	if (error)
		IWL_WARNING("check mac addr %d | %d\n", counter++, error);

	/* make sure basic rates 6Mbps and 1Mbps are supported */
	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
	if (error)
		IWL_WARNING("check basic rate %d | %d\n", counter++, error);

	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
	if (error)
		IWL_WARNING("check assoc id %d | %d\n", counter++, error);

	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
	if (error)
		IWL_WARNING("check CCK and short slot %d | %d\n",
			    counter++, error);

	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
	if (error)
		IWL_WARNING("check CCK & auto detect %d | %d\n",
			    counter++, error);

	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
	if (error)
		IWL_WARNING("check TGG and auto detect %d | %d\n",
			    counter++, error);

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

	if (error) {
C
Christoph Hellwig 已提交
420
		IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
Z
Zhu Yi 已提交
421 422 423 424 425 426
		return -1;
	}
	return 0;
}

/**
427
 * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
428
 * @priv: staging_rxon is compared to active_rxon
Z
Zhu Yi 已提交
429
 *
430 431 432
 * 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 已提交
433
 */
434
static int iwl4965_full_rxon_required(struct iwl_priv *priv)
Z
Zhu Yi 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
{

	/* These items are only settable from the full RXON command */
	if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
	    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.rx_chain != priv->active_rxon.rx_chain) ||
	    (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;
}

/**
C
Christoph Hellwig 已提交
475
 * iwl4965_commit_rxon - commit staging_rxon to hardware
Z
Zhu Yi 已提交
476
 *
477
 * The RXON command in staging_rxon is committed to the hardware and
Z
Zhu Yi 已提交
478 479 480 481
 * 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.
 */
482
static int iwl4965_commit_rxon(struct iwl_priv *priv)
Z
Zhu Yi 已提交
483 484
{
	/* cast away the const for active_rxon in this function */
G
Gregory Greenman 已提交
485
	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
486
	DECLARE_MAC_BUF(mac);
Z
Zhu Yi 已提交
487 488
	int rc = 0;

489
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
490 491 492 493 494
		return -1;

	/* always get timestamp with Rx frame */
	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;

C
Christoph Hellwig 已提交
495
	rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
Z
Zhu Yi 已提交
496 497 498 499 500 501
	if (rc) {
		IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
		return -EINVAL;
	}

	/* If we don't need to send a full RXON, we can use
C
Christoph Hellwig 已提交
502
	 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
Z
Zhu Yi 已提交
503
	 * and other flags for the current radio configuration. */
C
Christoph Hellwig 已提交
504
	if (!iwl4965_full_rxon_required(priv)) {
505
		rc = iwl_send_rxon_assoc(priv);
Z
Zhu Yi 已提交
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
		if (rc) {
			IWL_ERROR("Error setting RXON_ASSOC "
				  "configuration (%d).\n", rc);
			return rc;
		}

		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 */
524
	if (iwl_is_associated(priv) &&
Z
Zhu Yi 已提交
525 526 527 528
	    (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

529
		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
G
Gregory Greenman 已提交
530
				      sizeof(struct iwl_rxon_cmd),
Z
Zhu Yi 已提交
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
				      &priv->active_rxon);

		/* If the mask clearing failed then we set
		 * active_rxon back to what it was previously */
		if (rc) {
			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
			IWL_ERROR("Error clearing ASSOC_MSK on current "
				  "configuration (%d).\n", rc);
			return rc;
		}
	}

	IWL_DEBUG_INFO("Sending RXON\n"
		       "* with%s RXON_FILTER_ASSOC_MSK\n"
		       "* channel = %d\n"
546
		       "* bssid = %s\n",
Z
Zhu Yi 已提交
547 548 549
		       ((priv->staging_rxon.filter_flags &
			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
		       le16_to_cpu(priv->staging_rxon.channel),
550
		       print_mac(mac, priv->staging_rxon.bssid_addr));
Z
Zhu Yi 已提交
551

552
	iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
Z
Zhu Yi 已提交
553
	/* Apply the new configuration */
554
	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
G
Gregory Greenman 已提交
555
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
Z
Zhu Yi 已提交
556 557 558 559 560
	if (rc) {
		IWL_ERROR("Error setting new configuration (%d).\n", rc);
		return rc;
	}

561
	iwlcore_clear_stations_table(priv);
562

Z
Zhu Yi 已提交
563 564 565
	if (!priv->error_recovering)
		priv->start_calib = 0;

566
	iwl_init_sensitivity(priv);
Z
Zhu Yi 已提交
567 568 569 570 571

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

	/* 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 */
C
Christoph Hellwig 已提交
572
	rc = iwl4965_hw_reg_send_txpower(priv);
Z
Zhu Yi 已提交
573 574 575 576 577 578
	if (rc) {
		IWL_ERROR("Error setting Tx power (%d).\n", rc);
		return rc;
	}

	/* Add the broadcast address so we can send broadcast frames */
579
	if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
Z
Zhu Yi 已提交
580 581 582 583 584 585 586
	    IWL_INVALID_STATION) {
		IWL_ERROR("Error adding BROADCAST address for transmit.\n");
		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 */
587
	if (iwl_is_associated(priv) &&
Z
Zhu Yi 已提交
588
	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
589
		if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
Z
Zhu Yi 已提交
590 591 592 593 594
		    == IWL_INVALID_STATION) {
			IWL_ERROR("Error adding AP address for transmit.\n");
			return -EIO;
		}
		priv->assoc_station_added = 1;
595 596 597
		if (priv->default_wep_key &&
		    iwl_send_static_wepkey_cmd(priv, 0))
			IWL_ERROR("Could not send WEP static key.\n");
Z
Zhu Yi 已提交
598 599 600 601 602
	}

	return 0;
}

M
Mohamed Abbas 已提交
603 604 605
void iwl4965_update_chain_flags(struct iwl_priv *priv)
{

R
Ron Rindjunsky 已提交
606
	iwl_set_rxon_chain(priv);
M
Mohamed Abbas 已提交
607 608 609
	iwl4965_commit_rxon(priv);
}

610
static int iwl4965_send_bt_config(struct iwl_priv *priv)
Z
Zhu Yi 已提交
611
{
C
Christoph Hellwig 已提交
612
	struct iwl4965_bt_cmd bt_cmd = {
Z
Zhu Yi 已提交
613 614 615 616 617 618 619
		.flags = 3,
		.lead_time = 0xAA,
		.max_kill = 1,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

620
	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
C
Christoph Hellwig 已提交
621
				sizeof(struct iwl4965_bt_cmd), &bt_cmd);
Z
Zhu Yi 已提交
622 623
}

624
static int iwl4965_send_scan_abort(struct iwl_priv *priv)
Z
Zhu Yi 已提交
625
{
626 627
	int ret = 0;
	struct iwl_rx_packet *res;
628
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
629 630 631 632 633 634 635 636 637 638 639 640
		.id = REPLY_SCAN_ABORT_CMD,
		.meta.flags = CMD_WANT_SKB,
	};

	/* If there isn't a scan actively going on in the hardware
	 * then we are in between scan bands and not actually
	 * actively scanning, so don't send the abort command */
	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
		return 0;
	}

641 642
	ret = iwl_send_cmd_sync(priv, &cmd);
	if (ret) {
Z
Zhu Yi 已提交
643
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
644
		return ret;
Z
Zhu Yi 已提交
645 646
	}

647
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
Z
Zhu Yi 已提交
648 649 650 651 652 653 654 655 656 657 658 659 660 661
	if (res->u.status != CAN_ABORT_STATUS) {
		/* The scan abort will return 1 for success or
		 * 2 for "failure".  A failure condition can be
		 * due to simply not being in an active scan which
		 * can occur if we send the scan abort before we
		 * the microcode has notified us that a scan is
		 * completed. */
		IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
		clear_bit(STATUS_SCAN_HW, &priv->status);
	}

	dev_kfree_skb_any(cmd.meta.u.skb);

662
	return ret;
Z
Zhu Yi 已提交
663 664 665 666 667
}

/*
 * CARD_STATE_CMD
 *
668
 * Use: Sets the device's internal card state to enable, disable, or halt
Z
Zhu Yi 已提交
669 670 671 672 673 674
 *
 * When in the 'enable' state the card operates as normal.
 * When in the 'disable' state, the card enters into a low power mode.
 * When in the 'halt' state, the card is shut down and must be fully
 * restarted to come back on.
 */
675
static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
Z
Zhu Yi 已提交
676
{
677
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
678 679 680 681 682 683
		.id = REPLY_CARD_STATE_CMD,
		.len = sizeof(u32),
		.data = &flags,
		.meta.flags = meta_flag,
	};

684
	return iwl_send_cmd(priv, &cmd);
Z
Zhu Yi 已提交
685 686
}

687
static void iwl_clear_free_frames(struct iwl_priv *priv)
Z
Zhu Yi 已提交
688 689 690 691 692 693 694 695 696
{
	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);
697
		kfree(list_entry(element, struct iwl_frame, list));
Z
Zhu Yi 已提交
698 699 700 701 702 703 704 705 706 707
		priv->frames_count--;
	}

	if (priv->frames_count) {
		IWL_WARNING("%d frames still in use.  Did we lose one?\n",
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

708
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
Z
Zhu Yi 已提交
709
{
710
	struct iwl_frame *frame;
Z
Zhu Yi 已提交
711 712 713 714 715 716 717 718 719 720 721 722 723 724
	struct list_head *element;
	if (list_empty(&priv->free_frames)) {
		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
		if (!frame) {
			IWL_ERROR("Could not allocate frame!\n");
			return NULL;
		}

		priv->frames_count++;
		return frame;
	}

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

728
static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
Z
Zhu Yi 已提交
729 730 731 732 733
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

734
unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
Z
Zhu Yi 已提交
735 736 737 738
				struct ieee80211_hdr *hdr,
				const u8 *dest, int left)
{

739
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
Z
Zhu Yi 已提交
740 741 742 743 744 745 746 747 748 749 750 751
	    ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
	     (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
		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;
}

G
Guy Cohen 已提交
752
static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
Z
Zhu Yi 已提交
753
{
G
Guy Cohen 已提交
754 755 756 757 758 759 760 761
	int i;
	int rate_mask;

	/* Set rate mask*/
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
		rate_mask = priv->active_rate_basic & 0xF;
	else
		rate_mask = priv->active_rate_basic & 0xFF0;
Z
Zhu Yi 已提交
762

G
Guy Cohen 已提交
763
	/* Find lowest valid rate */
Z
Zhu Yi 已提交
764
	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
765
					i = iwl_rates[i].next_ieee) {
Z
Zhu Yi 已提交
766
		if (rate_mask & (1 << i))
767
			return iwl_rates[i].plcp;
Z
Zhu Yi 已提交
768 769
	}

G
Guy Cohen 已提交
770 771 772 773 774
	/* 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 已提交
775 776
}

777
static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
Z
Zhu Yi 已提交
778
{
779
	struct iwl_frame *frame;
Z
Zhu Yi 已提交
780 781 782 783
	unsigned int frame_size;
	int rc;
	u8 rate;

784
	frame = iwl_get_free_frame(priv);
Z
Zhu Yi 已提交
785 786 787 788 789 790 791

	if (!frame) {
		IWL_ERROR("Could not obtain free frame buffer for beacon "
			  "command.\n");
		return -ENOMEM;
	}

G
Guy Cohen 已提交
792
	rate = iwl4965_rate_get_lowest_plcp(priv);
Z
Zhu Yi 已提交
793

C
Christoph Hellwig 已提交
794
	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
Z
Zhu Yi 已提交
795

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

799
	iwl_free_frame(priv, frame);
Z
Zhu Yi 已提交
800 801 802 803 804 805 806 807 808 809 810

	return rc;
}

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

/**
C
Christoph Hellwig 已提交
811
 * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
Z
Zhu Yi 已提交
812 813 814
 *
 * return : set the bit for each supported rate insert in ie
 */
C
Christoph Hellwig 已提交
815
static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
816
				    u16 basic_rate, int *left)
Z
Zhu Yi 已提交
817 818 819
{
	u16 ret_rates = 0, bit;
	int i;
820 821
	u8 *cnt = ie;
	u8 *rates = ie + 1;
Z
Zhu Yi 已提交
822 823 824 825

	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
		if (bit & supported_rate) {
			ret_rates |= bit;
826
			rates[*cnt] = iwl_rates[i].ieee |
827 828 829 830 831
				((bit & basic_rate) ? 0x80 : 0x00);
			(*cnt)++;
			(*left)--;
			if ((*left <= 0) ||
			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
Z
Zhu Yi 已提交
832 833 834 835 836 837 838
				break;
		}
	}

	return ret_rates;
}

839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
#ifdef CONFIG_IWL4965_HT
static void iwl4965_ht_conf(struct iwl_priv *priv,
			    struct ieee80211_bss_conf *bss_conf)
{
	struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
	struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;

	IWL_DEBUG_MAC80211("enter: \n");

	iwl_conf->is_ht = bss_conf->assoc_ht;

	if (!iwl_conf->is_ht)
		return;

	priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);

	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
		iwl_conf->sgf |= 0x1;
	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
		iwl_conf->sgf |= 0x2;

	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 =
		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
	iwl_conf->extension_chan_offset =
		ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
	/* If no above or below channel supplied disable FAT channel */
	if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE &&
	    iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW)
		iwl_conf->supported_chan_width = 0;

	iwl_conf->tx_mimo_ps_mode =
		(u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
	memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);

	iwl_conf->control_channel = ht_bss_conf->primary_channel;
	iwl_conf->tx_chan_width =
		!!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
	iwl_conf->ht_protection =
		ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
	iwl_conf->non_GF_STA_present =
		!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);

	IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
	IWL_DEBUG_MAC80211("leave\n");
}

static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
			u8 *pos, int *left)
{
	struct ieee80211_ht_cap *ht_cap;

	if (!sband || !sband->ht_info.ht_supported)
		return;

	if (*left < sizeof(struct ieee80211_ht_cap))
		return;

	*pos++ = sizeof(struct ieee80211_ht_cap);
	ht_cap = (struct ieee80211_ht_cap *) pos;

	ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
	memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
	ht_cap->ampdu_params_info =
		(sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
		((sband->ht_info.ampdu_density << 2) &
			IEEE80211_HT_CAP_AMPDU_DENSITY);
	*left -= sizeof(struct ieee80211_ht_cap);
}
#else
static inline void iwl4965_ht_conf(struct iwl_priv *priv,
				   struct ieee80211_bss_conf *bss_conf)
{
}
static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
			u8 *pos, int *left)
{
}
#endif


Z
Zhu Yi 已提交
924
/**
C
Christoph Hellwig 已提交
925
 * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
Z
Zhu Yi 已提交
926
 */
927
static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
928 929 930
				  enum ieee80211_band band,
				  struct ieee80211_mgmt *frame,
				  int left, int is_direct)
Z
Zhu Yi 已提交
931 932 933
{
	int len = 0;
	u8 *pos = NULL;
934
	u16 active_rates, ret_rates, cck_rates, active_rate_basic;
935
	const struct ieee80211_supported_band *sband =
936
						iwl_get_hw_mode(priv, band);
Z
Zhu Yi 已提交
937 938 939 940 941 942 943 944 945

	/* Make sure there is enough space for the probe request,
	 * two mandatory IEs and the data */
	left -= 24;
	if (left < 0)
		return 0;
	len += 24;

	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
946
	memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
Z
Zhu Yi 已提交
947
	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
948
	memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
Z
Zhu Yi 已提交
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
	frame->seq_ctrl = 0;

	/* fill in our indirect SSID IE */
	/* ...next IE... */

	left -= 2;
	if (left < 0)
		return 0;
	len += 2;
	pos = &(frame->u.probe_req.variable[0]);
	*pos++ = WLAN_EID_SSID;
	*pos++ = 0;

	/* fill in our direct SSID IE... */
	if (is_direct) {
		/* ...next IE... */
		left -= 2 + priv->essid_len;
		if (left < 0)
			return 0;
		/* ... fill it in... */
		*pos++ = WLAN_EID_SSID;
		*pos++ = priv->essid_len;
		memcpy(pos, priv->essid, priv->essid_len);
		pos += priv->essid_len;
		len += 2 + priv->essid_len;
	}

	/* fill in supported rate */
	/* ...next IE... */
	left -= 2;
	if (left < 0)
		return 0;
981

Z
Zhu Yi 已提交
982 983 984
	/* ... fill it in... */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos = 0;
985

986 987 988 989 990
	/* exclude 60M rate */
	active_rates = priv->rates_mask;
	active_rates &= ~IWL_RATE_60M_MASK;

	active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
Z
Zhu Yi 已提交
991

992
	cck_rates = IWL_CCK_RATES_MASK & active_rates;
C
Christoph Hellwig 已提交
993
	ret_rates = iwl4965_supported_rate_to_ie(pos, cck_rates,
994
			active_rate_basic, &left);
995 996
	active_rates &= ~ret_rates;

C
Christoph Hellwig 已提交
997
	ret_rates = iwl4965_supported_rate_to_ie(pos, active_rates,
998
				 active_rate_basic, &left);
999 1000
	active_rates &= ~ret_rates;

Z
Zhu Yi 已提交
1001 1002
	len += 2 + *pos;
	pos += (*pos) + 1;
1003
	if (active_rates == 0)
Z
Zhu Yi 已提交
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
		goto fill_end;

	/* fill in supported extended rate */
	/* ...next IE... */
	left -= 2;
	if (left < 0)
		return 0;
	/* ... fill it in... */
	*pos++ = WLAN_EID_EXT_SUPP_RATES;
	*pos = 0;
C
Christoph Hellwig 已提交
1014
	iwl4965_supported_rate_to_ie(pos, active_rates,
1015
				 active_rate_basic, &left);
Z
Zhu Yi 已提交
1016 1017 1018 1019
	if (*pos > 0)
		len += 2 + *pos;

 fill_end:
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
	/* fill in HT IE */
	left -= 2;
	if (left < 0)
		return 0;

	*pos++ = WLAN_EID_HT_CAPABILITY;
	*pos = 0;

	iwl_ht_cap_to_ie(sband, pos, &left);

	if (*pos > 0)
		len += 2 + *pos;
Z
Zhu Yi 已提交
1032 1033 1034 1035 1036 1037
	return (u16)len;
}

/*
 * QoS  support
*/
1038
static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
C
Christoph Hellwig 已提交
1039
				       struct iwl4965_qosparam_cmd *qos)
Z
Zhu Yi 已提交
1040 1041
{

1042
	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
C
Christoph Hellwig 已提交
1043
				sizeof(struct iwl4965_qosparam_cmd), qos);
Z
Zhu Yi 已提交
1044 1045
}

1046
static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
Z
Zhu Yi 已提交
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
{
	unsigned long flags;

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

	if (!priv->qos_data.qos_enable)
		return;

	spin_lock_irqsave(&priv->lock, flags);
	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;

1067
#ifdef CONFIG_IWL4965_HT
1068
	if (priv->current_ht_config.is_ht)
1069
		priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
1070
#endif /* CONFIG_IWL4965_HT */
1071

Z
Zhu Yi 已提交
1072 1073
	spin_unlock_irqrestore(&priv->lock, flags);

1074
	if (force || iwl_is_associated(priv)) {
1075 1076 1077
		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 已提交
1078

C
Christoph Hellwig 已提交
1079
		iwl4965_send_qos_params_command(priv,
Z
Zhu Yi 已提交
1080 1081 1082 1083
				&(priv->qos_data.def_qos_parm));
	}
}

1084
int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
Z
Zhu Yi 已提交
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
{
	/* Filter incoming packets to determine if they are targeted toward
	 * this network, discarding packets coming from ourselves */
	switch (priv->iw_mode) {
	case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
		/* packets from our adapter are dropped (echo) */
		if (!compare_ether_addr(header->addr2, priv->mac_addr))
			return 0;
		/* {broad,multi}cast packets to our IBSS go through */
		if (is_multicast_ether_addr(header->addr1))
			return !compare_ether_addr(header->addr3, priv->bssid);
		/* packets to our adapter go through */
		return !compare_ether_addr(header->addr1, priv->mac_addr);
	case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
		/* packets from our adapter are dropped (echo) */
		if (!compare_ether_addr(header->addr3, priv->mac_addr))
			return 0;
		/* {broad,multi}cast packets to our BSS go through */
		if (is_multicast_ether_addr(header->addr1))
			return !compare_ether_addr(header->addr2, priv->bssid);
		/* packets to our adapter go through */
		return !compare_ether_addr(header->addr1, priv->mac_addr);
1107 1108
	default:
		break;
Z
Zhu Yi 已提交
1109 1110 1111 1112 1113 1114 1115
	}

	return 1;
}

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

C
Christoph Hellwig 已提交
1116
static const char *iwl4965_get_tx_fail_reason(u32 status)
Z
Zhu Yi 已提交
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
{
	switch (status & TX_STATUS_MSK) {
	case TX_STATUS_SUCCESS:
		return "SUCCESS";
		TX_STATUS_ENTRY(SHORT_LIMIT);
		TX_STATUS_ENTRY(LONG_LIMIT);
		TX_STATUS_ENTRY(FIFO_UNDERRUN);
		TX_STATUS_ENTRY(MGMNT_ABORT);
		TX_STATUS_ENTRY(NEXT_FRAG);
		TX_STATUS_ENTRY(LIFE_EXPIRE);
		TX_STATUS_ENTRY(DEST_PS);
		TX_STATUS_ENTRY(ABORTED);
		TX_STATUS_ENTRY(BT_RETRY);
		TX_STATUS_ENTRY(STA_INVALID);
		TX_STATUS_ENTRY(FRAG_DROPPED);
		TX_STATUS_ENTRY(TID_DISABLE);
		TX_STATUS_ENTRY(FRAME_FLUSHED);
		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
		TX_STATUS_ENTRY(TX_LOCKED);
		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
	}

	return "UNKNOWN";
}

/**
C
Christoph Hellwig 已提交
1143
 * iwl4965_scan_cancel - Cancel any currently executing HW scan
Z
Zhu Yi 已提交
1144 1145 1146
 *
 * NOTE: priv->mutex is not required before calling this function
 */
1147
static int iwl4965_scan_cancel(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
{
	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
		clear_bit(STATUS_SCANNING, &priv->status);
		return 0;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
			IWL_DEBUG_SCAN("Queuing scan abort.\n");
			set_bit(STATUS_SCAN_ABORTING, &priv->status);
			queue_work(priv->workqueue, &priv->abort_scan);

		} else
			IWL_DEBUG_SCAN("Scan abort already in progress.\n");

		return test_bit(STATUS_SCANNING, &priv->status);
	}

	return 0;
}

/**
C
Christoph Hellwig 已提交
1170
 * iwl4965_scan_cancel_timeout - Cancel any currently executing HW scan
Z
Zhu Yi 已提交
1171 1172 1173 1174
 * @ms: amount of time to wait (in milliseconds) for scan to abort
 *
 * NOTE: priv->mutex must be held before calling this function
 */
1175
static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
Z
Zhu Yi 已提交
1176 1177 1178 1179
{
	unsigned long now = jiffies;
	int ret;

C
Christoph Hellwig 已提交
1180
	ret = iwl4965_scan_cancel(priv);
Z
Zhu Yi 已提交
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
	if (ret && ms) {
		mutex_unlock(&priv->mutex);
		while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
				test_bit(STATUS_SCANNING, &priv->status))
			msleep(1);
		mutex_lock(&priv->mutex);

		return test_bit(STATUS_SCANNING, &priv->status);
	}

	return ret;
}

1194
static void iwl4965_sequence_reset(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
{
	/* Reset ieee stats */

	/* We don't reset the net_device_stats (ieee->stats) on
	 * re-association */

	priv->last_seq_num = -1;
	priv->last_frag_num = -1;
	priv->last_packet_time = 0;

C
Christoph Hellwig 已提交
1205
	iwl4965_scan_cancel(priv);
Z
Zhu Yi 已提交
1206 1207 1208 1209 1210
}

#define MAX_UCODE_BEACON_INTERVAL	4096
#define INTEL_CONN_LISTEN_INTERVAL	__constant_cpu_to_le16(0xA)

C
Christoph Hellwig 已提交
1211
static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
Z
Zhu Yi 已提交
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
{
	u16 new_val = 0;
	u16 beacon_factor = 0;

	beacon_factor =
	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
		/ MAX_UCODE_BEACON_INTERVAL;
	new_val = beacon_val / beacon_factor;

	return cpu_to_le16(new_val);
}

1224
static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
{
	u64 interval_tm_unit;
	u64 tsf, result;
	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);
1235 1236 1237
	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
	priv->rxon_timing.timestamp.dw[0] =
				cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
Z
Zhu Yi 已提交
1238 1239 1240

	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;

1241
	tsf = priv->timestamp;
Z
Zhu Yi 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253

	beacon_int = priv->beacon_int;
	spin_unlock_irqrestore(&priv->lock, flags);

	if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
		if (beacon_int == 0) {
			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
		} else {
			priv->rxon_timing.beacon_interval =
				cpu_to_le16(beacon_int);
			priv->rxon_timing.beacon_interval =
C
Christoph Hellwig 已提交
1254
			    iwl4965_adjust_beacon_interval(
Z
Zhu Yi 已提交
1255 1256 1257 1258 1259 1260
				le16_to_cpu(priv->rxon_timing.beacon_interval));
		}

		priv->rxon_timing.atim_window = 0;
	} else {
		priv->rxon_timing.beacon_interval =
C
Christoph Hellwig 已提交
1261
			iwl4965_adjust_beacon_interval(conf->beacon_int);
Z
Zhu Yi 已提交
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
		/* TODO: we need to get atim_window from upper stack
		 * for now we set to 0 */
		priv->rxon_timing.atim_window = 0;
	}

	interval_tm_unit =
		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
	result = do_div(tsf, interval_tm_unit);
	priv->rxon_timing.beacon_init_val =
	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));

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

1280
static int iwl4965_scan_initiate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1281 1282 1283 1284 1285 1286
{
	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
		IWL_ERROR("APs don't scan.\n");
		return 0;
	}

1287
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
		return -EIO;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
		IWL_DEBUG_SCAN("Scan already in progress.\n");
		return -EAGAIN;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_SCAN("Scan request while abort pending.  "
			       "Queuing.\n");
		return -EAGAIN;
	}

	IWL_DEBUG_INFO("Starting scan...\n");
	priv->scan_bands = 2;
	set_bit(STATUS_SCANNING, &priv->status);
	priv->scan_start = jiffies;
	priv->scan_pass_start = priv->scan_start;

	queue_work(priv->workqueue, &priv->request_scan);

	return 0;
}


1315
static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
1316
					  enum ieee80211_band band)
Z
Zhu Yi 已提交
1317
{
1318
	if (band == IEEE80211_BAND_5GHZ) {
Z
Zhu Yi 已提交
1319 1320 1321 1322 1323
		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 {
1324
		/* Copied from iwl4965_post_associate() */
Z
Zhu Yi 已提交
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
		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;

		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
			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;
	}
}

/*
1340
 * initialize rxon structure with default values from eeprom
Z
Zhu Yi 已提交
1341
 */
1342
static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1343
{
1344
	const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369

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

	switch (priv->iw_mode) {
	case IEEE80211_IF_TYPE_AP:
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
		break;

	case IEEE80211_IF_TYPE_STA:
		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
		break;

	case IEEE80211_IF_TYPE_IBSS:
		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;

	case IEEE80211_IF_TYPE_MNTR:
		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;
1370 1371 1372
	default:
		IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
		break;
Z
Zhu Yi 已提交
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
	}

#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

1384
	ch_info = iwl_get_channel_info(priv, priv->band,
Z
Zhu Yi 已提交
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
				       le16_to_cpu(priv->staging_rxon.channel));

	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
	 */
	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
	    !(is_channel_ibss(ch_info)))
		ch_info = &priv->channel_info[0];

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

1401
	iwl4965_set_flags_for_phymode(priv, priv->band);
Z
Zhu Yi 已提交
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413

	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 已提交
1414
	iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
1415 1416
}

1417
static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
Z
Zhu Yi 已提交
1418 1419
{
	if (mode == IEEE80211_IF_TYPE_IBSS) {
1420
		const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
1421

1422
		ch_info = iwl_get_channel_info(priv,
1423
			priv->band,
Z
Zhu Yi 已提交
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
			le16_to_cpu(priv->staging_rxon.channel));

		if (!ch_info || !is_channel_ibss(ch_info)) {
			IWL_ERROR("channel %d not IBSS channel\n",
				  le16_to_cpu(priv->staging_rxon.channel));
			return -EINVAL;
		}
	}

	priv->iw_mode = mode;

C
Christoph Hellwig 已提交
1435
	iwl4965_connection_init_rx_config(priv);
Z
Zhu Yi 已提交
1436 1437
	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);

1438
	iwlcore_clear_stations_table(priv);
Z
Zhu Yi 已提交
1439

1440
	/* dont commit rxon if rf-kill is on*/
1441
	if (!iwl_is_ready_rf(priv))
1442 1443 1444 1445 1446 1447 1448 1449 1450
		return -EAGAIN;

	cancel_delayed_work(&priv->scan_check);
	if (iwl4965_scan_cancel_timeout(priv, 100)) {
		IWL_WARNING("Aborted scan still in progress after 100ms\n");
		IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
		return -EAGAIN;
	}

C
Christoph Hellwig 已提交
1451
	iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
1452 1453 1454 1455

	return 0;
}

1456
static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
Z
Zhu Yi 已提交
1457
				      struct ieee80211_tx_control *ctl,
1458
				      struct iwl_cmd *cmd,
Z
Zhu Yi 已提交
1459
				      struct sk_buff *skb_frag,
1460
				      int sta_id)
Z
Zhu Yi 已提交
1461
{
1462
	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
1463 1464 1465
	struct iwl_wep_key *wepkey;
	int keyidx = 0;

1466
	BUG_ON(ctl->hw_key->hw_key_idx > 3);
Z
Zhu Yi 已提交
1467 1468 1469 1470 1471

	switch (keyinfo->alg) {
	case ALG_CCMP:
		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
1472 1473
		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
			cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
Z
Zhu Yi 已提交
1474 1475 1476 1477 1478
		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
		break;

	case ALG_TKIP:
		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
1479 1480 1481
		ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
			IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
		IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
Z
Zhu Yi 已提交
1482 1483 1484
		break;

	case ALG_WEP:
1485
		wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
1486 1487 1488
		cmd->cmd.tx.sec_ctl = 0;
		if (priv->default_wep_key) {
			/* the WEP key was sent as static */
1489
			keyidx = ctl->hw_key->hw_key_idx;
1490 1491 1492 1493 1494
			memcpy(&cmd->cmd.tx.key[3], wepkey->key,
							wepkey->key_size);
			if (wepkey->key_size == WEP_KEY_LEN_128)
				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
		} else {
1495 1496 1497 1498 1499 1500
			/* the WEP key was sent as dynamic */
			keyidx = keyinfo->keyidx;
			memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
							keyinfo->keylen);
			if (keyinfo->keylen == WEP_KEY_LEN_128)
				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
1501
		}
Z
Zhu Yi 已提交
1502

1503 1504
		cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
			(keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
Z
Zhu Yi 已提交
1505 1506

		IWL_DEBUG_TX("Configuring packet for WEP encryption "
1507
			     "with key %d\n", keyidx);
Z
Zhu Yi 已提交
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518
		break;

	default:
		printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
		break;
	}
}

/*
 * handle build REPLY_TX command notification.
 */
1519
static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
1520
				  struct iwl_cmd *cmd,
Z
Zhu Yi 已提交
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
				  struct ieee80211_tx_control *ctrl,
				  struct ieee80211_hdr *hdr,
				  int is_unicast, u8 std_id)
{
	u16 fc = le16_to_cpu(hdr->frame_control);
	__le32 tx_flags = cmd->cmd.tx.tx_flags;

	cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
	if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
		tx_flags |= TX_CMD_FLG_ACK_MSK;
		if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
		if (ieee80211_is_probe_response(fc) &&
		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
			tx_flags |= TX_CMD_FLG_TSF_MSK;
	} else {
		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
	}

T
Tomas Winkler 已提交
1541 1542 1543 1544
	if (ieee80211_is_back_request(fc))
		tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;


Z
Zhu Yi 已提交
1545 1546 1547 1548
	cmd->cmd.tx.sta_id = std_id;
	if (ieee80211_get_morefrag(hdr))
		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

1549 1550 1551
	if (ieee80211_is_qos_data(fc)) {
		u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
		cmd->cmd.tx.tid_tspec = qc[0] & 0xf;
Z
Zhu Yi 已提交
1552
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
1553
	} else {
Z
Zhu Yi 已提交
1554
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
1555
	}
Z
Zhu Yi 已提交
1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571

	if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
		tx_flags |= TX_CMD_FLG_RTS_MSK;
		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
	} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
		tx_flags |= TX_CMD_FLG_CTS_MSK;
	}

	if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
		tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;

	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
		    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
1572
			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
Z
Zhu Yi 已提交
1573
		else
1574
			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
M
Mohamed Abbas 已提交
1575
	} else {
Z
Zhu Yi 已提交
1576
		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
M
Mohamed Abbas 已提交
1577
	}
Z
Zhu Yi 已提交
1578 1579 1580 1581 1582

	cmd->cmd.tx.driver_txop = 0;
	cmd->cmd.tx.tx_flags = tx_flags;
	cmd->cmd.tx.next_frame_len = 0;
}
1583 1584 1585 1586 1587 1588 1589
static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
{
	/* 0 - mgmt, 1 - cnt, 2 - data */
	int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
	priv->tx_stats[idx].cnt++;
	priv->tx_stats[idx].bytes += len;
}
Z
Zhu Yi 已提交
1590 1591 1592
/*
 * start REPLY_TX command process
 */
1593
static int iwl4965_tx_skb(struct iwl_priv *priv,
Z
Zhu Yi 已提交
1594 1595 1596
		      struct sk_buff *skb, struct ieee80211_tx_control *ctl)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1597
	struct iwl_tfd_frame *tfd;
Z
Zhu Yi 已提交
1598 1599
	u32 *control_flags;
	int txq_id = ctl->queue;
1600
	struct iwl_tx_queue *txq = NULL;
1601
	struct iwl_queue *q = NULL;
Z
Zhu Yi 已提交
1602 1603
	dma_addr_t phys_addr;
	dma_addr_t txcmd_phys;
T
Tomas Winkler 已提交
1604
	dma_addr_t scratch_phys;
1605
	struct iwl_cmd *out_cmd = NULL;
Z
Zhu Yi 已提交
1606
	u16 len, idx, len_org;
1607 1608 1609
	u8 hdr_len;
	u8 id;
	u8 unicast;
Z
Zhu Yi 已提交
1610
	u8 sta_id;
1611 1612
	u8 tid = 0;
	u8 wait_write_ptr = 0;
Z
Zhu Yi 已提交
1613 1614
	u16 seq_number = 0;
	u16 fc;
1615
	u8 *qc = NULL;
Z
Zhu Yi 已提交
1616 1617 1618 1619
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&priv->lock, flags);
1620
	if (iwl_is_rfkill(priv)) {
Z
Zhu Yi 已提交
1621 1622 1623 1624
		IWL_DEBUG_DROP("Dropping - RF KILL\n");
		goto drop_unlock;
	}

1625 1626
	if (!priv->vif) {
		IWL_DEBUG_DROP("Dropping - !priv->vif\n");
Z
Zhu Yi 已提交
1627 1628 1629
		goto drop_unlock;
	}

1630
	if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
Z
Zhu Yi 已提交
1631 1632 1633 1634 1635 1636 1637 1638 1639
		IWL_ERROR("ERROR: No TX rate available.\n");
		goto drop_unlock;
	}

	unicast = !is_multicast_ether_addr(hdr->addr1);
	id = 0;

	fc = le16_to_cpu(hdr->frame_control);

1640
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
1641 1642 1643 1644 1645 1646 1647 1648
	if (ieee80211_is_auth(fc))
		IWL_DEBUG_TX("Sending AUTH frame\n");
	else if (ieee80211_is_assoc_request(fc))
		IWL_DEBUG_TX("Sending ASSOC frame\n");
	else if (ieee80211_is_reassoc_request(fc))
		IWL_DEBUG_TX("Sending REASSOC frame\n");
#endif

1649
	/* drop all data frame if we are not associated */
1650
	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
1651
	   (!iwl_is_associated(priv) ||
1652
	    ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
1653
	    !priv->assoc_station_added)) {
1654
		IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
Z
Zhu Yi 已提交
1655 1656 1657 1658 1659 1660
		goto drop_unlock;
	}

	spin_unlock_irqrestore(&priv->lock, flags);

	hdr_len = ieee80211_get_hdrlen(fc);
1661 1662

	/* Find (or create) index into station table for destination station */
1663
	sta_id = iwl_get_sta_id(priv, hdr);
Z
Zhu Yi 已提交
1664
	if (sta_id == IWL_INVALID_STATION) {
1665 1666 1667 1668
		DECLARE_MAC_BUF(mac);

		IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
			       print_mac(mac, hdr->addr1));
Z
Zhu Yi 已提交
1669 1670 1671
		goto drop;
	}

G
Guy Cohen 已提交
1672
	IWL_DEBUG_TX("station Id %d\n", sta_id);
Z
Zhu Yi 已提交
1673

1674 1675 1676
	if (ieee80211_is_qos_data(fc)) {
		qc = ieee80211_get_qos_ctrl(hdr, hdr_len);
		tid = qc[0] & 0xf;
Z
Zhu Yi 已提交
1677 1678 1679 1680 1681 1682
		seq_number = priv->stations[sta_id].tid[tid].seq_number &
				IEEE80211_SCTL_SEQ;
		hdr->seq_ctrl = cpu_to_le16(seq_number) |
			(hdr->seq_ctrl &
				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
		seq_number += 0x10;
1683
#ifdef CONFIG_IWL4965_HT
Z
Zhu Yi 已提交
1684
		/* aggregation is on for this <sta,tid> */
1685
		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
Z
Zhu Yi 已提交
1686
			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
1687
		priv->stations[sta_id].tid[tid].tfds_in_queue++;
1688
#endif /* CONFIG_IWL4965_HT */
Z
Zhu Yi 已提交
1689
	}
1690 1691

	/* Descriptor for chosen Tx queue */
Z
Zhu Yi 已提交
1692 1693 1694 1695 1696
	txq = &priv->txq[txq_id];
	q = &txq->q;

	spin_lock_irqsave(&priv->lock, flags);

1697
	/* Set up first empty TFD within this queue's circular TFD buffer */
1698
	tfd = &txq->bd[q->write_ptr];
Z
Zhu Yi 已提交
1699 1700
	memset(tfd, 0, sizeof(*tfd));
	control_flags = (u32 *) tfd;
1701
	idx = get_cmd_index(q, q->write_ptr, 0);
Z
Zhu Yi 已提交
1702

1703
	/* Set up driver data for this TFD */
1704
	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
1705 1706
	txq->txb[q->write_ptr].skb[0] = skb;
	memcpy(&(txq->txb[q->write_ptr].status.control),
Z
Zhu Yi 已提交
1707
	       ctl, sizeof(struct ieee80211_tx_control));
1708 1709

	/* Set up first empty entry in queue's array of Tx/cmd buffers */
Z
Zhu Yi 已提交
1710 1711 1712
	out_cmd = &txq->cmd[idx];
	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
	memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
1713 1714 1715 1716 1717 1718 1719

	/*
	 * Set up the Tx-command (not MAC!) header.
	 * Store the chosen Tx queue and TFD index within the sequence field;
	 * after Tx, uCode's Tx response will return this value so driver can
	 * locate the frame within the tx queue and do post-tx processing.
	 */
Z
Zhu Yi 已提交
1720 1721
	out_cmd->hdr.cmd = REPLY_TX;
	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
1722
				INDEX_TO_SEQ(q->write_ptr)));
1723 1724

	/* Copy MAC header from skb into command buffer */
Z
Zhu Yi 已提交
1725 1726
	memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);

1727 1728 1729 1730 1731 1732 1733 1734 1735
	/*
	 * Use the first empty entry in this queue's command buffer array
	 * to contain the Tx command and MAC header concatenated together
	 * (payload data will be in another buffer).
	 * Size of this varies, due to varying MAC header length.
	 * If end is not dword aligned, we'll have 2 extra bytes at the end
	 * of the MAC header (device reads on dword boundaries).
	 * We'll tell device about this padding later.
	 */
1736
	len = sizeof(struct iwl_tx_cmd) +
1737
		sizeof(struct iwl_cmd_header) + hdr_len;
Z
Zhu Yi 已提交
1738 1739 1740 1741 1742 1743 1744 1745 1746

	len_org = len;
	len = (len + 3) & ~3;

	if (len_org != len)
		len_org = 1;
	else
		len_org = 0;

1747 1748
	/* Physical address of this Tx command's header (not MAC header!),
	 * within command buffer array. */
1749 1750
	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
		     offsetof(struct iwl_cmd, hdr);
Z
Zhu Yi 已提交
1751

1752 1753
	/* Add buffer containing Tx command and MAC(!) header to TFD's
	 * first entry */
C
Christoph Hellwig 已提交
1754
	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
Z
Zhu Yi 已提交
1755 1756

	if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
1757
		iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
Z
Zhu Yi 已提交
1758

1759 1760
	/* Set up TFD's 2nd entry to point directly to remainder of skb,
	 * if any (802.11 null frames have no payload). */
Z
Zhu Yi 已提交
1761 1762 1763 1764
	len = skb->len - hdr_len;
	if (len) {
		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
					   len, PCI_DMA_TODEVICE);
C
Christoph Hellwig 已提交
1765
		iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
Z
Zhu Yi 已提交
1766 1767
	}

1768
	/* Tell 4965 about any 2-byte padding after MAC header */
Z
Zhu Yi 已提交
1769 1770 1771
	if (len_org)
		out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK;

1772
	/* Total # bytes to be transmitted */
Z
Zhu Yi 已提交
1773 1774 1775 1776
	len = (u16)skb->len;
	out_cmd->cmd.tx.len = cpu_to_le16(len);

	/* TODO need this for burst mode later on */
C
Christoph Hellwig 已提交
1777
	iwl4965_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
Z
Zhu Yi 已提交
1778 1779

	/* set is_hcca to 0; it probably will never be implemented */
C
Christoph Hellwig 已提交
1780
	iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
Z
Zhu Yi 已提交
1781

1782 1783
	iwl_update_tx_stats(priv, fc, len);

1784
	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
1785
		offsetof(struct iwl_tx_cmd, scratch);
T
Tomas Winkler 已提交
1786 1787 1788
	out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
	out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);

Z
Zhu Yi 已提交
1789 1790
	if (!ieee80211_get_morefrag(hdr)) {
		txq->need_update = 1;
1791
		if (qc)
Z
Zhu Yi 已提交
1792 1793 1794 1795 1796 1797
			priv->stations[sta_id].tid[tid].seq_number = seq_number;
	} else {
		wait_write_ptr = 1;
		txq->need_update = 0;
	}

1798
	iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload,
Z
Zhu Yi 已提交
1799 1800
			   sizeof(out_cmd->cmd.tx));

1801
	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
Z
Zhu Yi 已提交
1802 1803
			   ieee80211_get_hdrlen(fc));

1804
	/* Set up entry for this TFD in Tx byte-count array */
1805
	priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
Z
Zhu Yi 已提交
1806

1807
	/* Tell device the write index *just past* this latest filled TFD */
T
Tomas Winkler 已提交
1808
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
1809
	rc = iwl_txq_update_write_ptr(priv, txq);
Z
Zhu Yi 已提交
1810 1811 1812 1813 1814
	spin_unlock_irqrestore(&priv->lock, flags);

	if (rc)
		return rc;

1815
	if ((iwl_queue_space(q) < q->high_mark)
Z
Zhu Yi 已提交
1816 1817 1818 1819
	    && priv->mac80211_registered) {
		if (wait_write_ptr) {
			spin_lock_irqsave(&priv->lock, flags);
			txq->need_update = 1;
1820
			iwl_txq_update_write_ptr(priv, txq);
Z
Zhu Yi 已提交
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834
			spin_unlock_irqrestore(&priv->lock, flags);
		}

		ieee80211_stop_queue(priv->hw, ctl->queue);
	}

	return 0;

drop_unlock:
	spin_unlock_irqrestore(&priv->lock, flags);
drop:
	return -1;
}

1835
static void iwl4965_set_rate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1836
{
1837
	const struct ieee80211_supported_band *hw = NULL;
Z
Zhu Yi 已提交
1838 1839 1840
	struct ieee80211_rate *rate;
	int i;

1841
	hw = iwl_get_hw_mode(priv, priv->band);
1842 1843 1844 1845
	if (!hw) {
		IWL_ERROR("Failed to set rate: unable to get hw mode\n");
		return;
	}
Z
Zhu Yi 已提交
1846 1847 1848 1849

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

1850 1851 1852 1853
	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 已提交
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
	}

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

1882
void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
Z
Zhu Yi 已提交
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
{
	unsigned long flags;

	if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
		return;

	IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
			  disable_radio ? "OFF" : "ON");

	if (disable_radio) {
C
Christoph Hellwig 已提交
1893
		iwl4965_scan_cancel(priv);
Z
Zhu Yi 已提交
1894 1895 1896
		/* FIXME: This is a workaround for AP */
		if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
			spin_lock_irqsave(&priv->lock, flags);
1897
			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
1898 1899
				    CSR_UCODE_SW_BIT_RFKILL);
			spin_unlock_irqrestore(&priv->lock, flags);
1900
			/* call the host command only if no hw rf-kill set */
1901 1902
			if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
			    iwl_is_ready(priv))
1903 1904 1905
				iwl4965_send_card_state(priv,
							CARD_STATE_CMD_DISABLE,
							0);
Z
Zhu Yi 已提交
1906
			set_bit(STATUS_RF_KILL_SW, &priv->status);
1907 1908 1909 1910

			/* make sure mac80211 stop sending Tx frame */
			if (priv->mac80211_registered)
				ieee80211_stop_queues(priv->hw);
Z
Zhu Yi 已提交
1911 1912 1913 1914 1915
		}
		return;
	}

	spin_lock_irqsave(&priv->lock, flags);
1916
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Z
Zhu Yi 已提交
1917 1918 1919 1920 1921 1922 1923 1924

	clear_bit(STATUS_RF_KILL_SW, &priv->status);
	spin_unlock_irqrestore(&priv->lock, flags);

	/* wake up ucode */
	msleep(10);

	spin_lock_irqsave(&priv->lock, flags);
1925 1926 1927
	iwl_read32(priv, CSR_UCODE_DRV_GP1);
	if (!iwl_grab_nic_access(priv))
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941
	spin_unlock_irqrestore(&priv->lock, flags);

	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
		IWL_DEBUG_RF_KILL("Can not turn radio back on - "
				  "disabled by HW switch\n");
		return;
	}

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

#define IWL_PACKET_RETRY_TIME HZ

1942
int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
Z
Zhu Yi 已提交
1943 1944 1945 1946 1947 1948 1949 1950 1951 1952
{
	u16 sc = le16_to_cpu(header->seq_ctrl);
	u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
	u16 frag = sc & IEEE80211_SCTL_FRAG;
	u16 *last_seq, *last_frag;
	unsigned long *last_time;

	switch (priv->iw_mode) {
	case IEEE80211_IF_TYPE_IBSS:{
		struct list_head *p;
C
Christoph Hellwig 已提交
1953
		struct iwl4965_ibss_seq *entry = NULL;
Z
Zhu Yi 已提交
1954 1955 1956 1957
		u8 *mac = header->addr2;
		int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);

		__list_for_each(p, &priv->ibss_mac_hash[index]) {
C
Christoph Hellwig 已提交
1958
			entry = list_entry(p, struct iwl4965_ibss_seq, list);
Z
Zhu Yi 已提交
1959 1960 1961 1962 1963 1964
			if (!compare_ether_addr(entry->mac, mac))
				break;
		}
		if (p == &priv->ibss_mac_hash[index]) {
			entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
			if (!entry) {
1965
				IWL_ERROR("Cannot malloc new mac entry\n");
Z
Zhu Yi 已提交
1966 1967 1968 1969 1970 1971
				return 0;
			}
			memcpy(entry->mac, mac, ETH_ALEN);
			entry->seq_num = seq;
			entry->frag_num = frag;
			entry->packet_time = jiffies;
1972
			list_add(&entry->list, &priv->ibss_mac_hash[index]);
Z
Zhu Yi 已提交
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
			return 0;
		}
		last_seq = &entry->seq_num;
		last_frag = &entry->frag_num;
		last_time = &entry->packet_time;
		break;
	}
	case IEEE80211_IF_TYPE_STA:
		last_seq = &priv->last_seq_num;
		last_frag = &priv->last_frag_num;
		last_time = &priv->last_packet_time;
		break;
	default:
		return 0;
	}
	if ((*last_seq == seq) &&
	    time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
		if (*last_frag == frag)
			goto drop;
		if (*last_frag + 1 != frag)
			/* out-of-order fragment */
			goto drop;
	} else
		*last_seq = seq;

	*last_frag = frag;
	*last_time = jiffies;
	return 0;

 drop:
	return 1;
}

2006
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020

#include "iwl-spectrum.h"

#define BEACON_TIME_MASK_LOW	0x00FFFFFF
#define BEACON_TIME_MASK_HIGH	0xFF000000
#define TIME_UNIT		1024

/*
 * extended beacon time format
 * time in usec will be changed into a 32-bit value in 8:24 format
 * the high 1 byte is the beacon counts
 * the lower 3 bytes is the time in usec within one beacon interval
 */

C
Christoph Hellwig 已提交
2021
static u32 iwl4965_usecs_to_beacons(u32 usec, u32 beacon_interval)
Z
Zhu Yi 已提交
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039
{
	u32 quot;
	u32 rem;
	u32 interval = beacon_interval * 1024;

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

	quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
	rem = (usec % interval) & BEACON_TIME_MASK_LOW;

	return (quot << 24) + rem;
}

/* base is usually what we get from ucode with each received frame,
 * the same as HW timer counter counting down
 */

C
Christoph Hellwig 已提交
2040
static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
Z
Zhu Yi 已提交
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
{
	u32 base_low = base & BEACON_TIME_MASK_LOW;
	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
	u32 interval = beacon_interval * TIME_UNIT;
	u32 res = (base & BEACON_TIME_MASK_HIGH) +
	    (addon & BEACON_TIME_MASK_HIGH);

	if (base_low > addon_low)
		res += base_low - addon_low;
	else if (base_low < addon_low) {
		res += interval + base_low - addon_low;
		res += (1 << 24);
	} else
		res += (1 << 24);

	return cpu_to_le32(res);
}

2059
static int iwl4965_get_measurement(struct iwl_priv *priv,
Z
Zhu Yi 已提交
2060 2061 2062
			       struct ieee80211_measurement_params *params,
			       u8 type)
{
C
Christoph Hellwig 已提交
2063
	struct iwl4965_spectrum_cmd spectrum;
2064
	struct iwl_rx_packet *res;
2065
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
2066 2067 2068 2069 2070 2071 2072 2073 2074
		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
		.data = (void *)&spectrum,
		.meta.flags = CMD_WANT_SKB,
	};
	u32 add_time = le64_to_cpu(params->start_time);
	int rc;
	int spectrum_resp_status;
	int duration = le16_to_cpu(params->duration);

2075
	if (iwl_is_associated(priv))
Z
Zhu Yi 已提交
2076
		add_time =
C
Christoph Hellwig 已提交
2077
		    iwl4965_usecs_to_beacons(
Z
Zhu Yi 已提交
2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
			le64_to_cpu(params->start_time) - priv->last_tsf,
			le16_to_cpu(priv->rxon_timing.beacon_interval));

	memset(&spectrum, 0, sizeof(spectrum));

	spectrum.channel_count = cpu_to_le16(1);
	spectrum.flags =
	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
	cmd.len = sizeof(spectrum);
	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));

2090
	if (iwl_is_associated(priv))
Z
Zhu Yi 已提交
2091
		spectrum.start_time =
C
Christoph Hellwig 已提交
2092
		    iwl4965_add_beacon_time(priv->last_beacon_time,
Z
Zhu Yi 已提交
2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
				add_time,
				le16_to_cpu(priv->rxon_timing.beacon_interval));
	else
		spectrum.start_time = 0;

	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
	spectrum.channels[0].channel = params->channel;
	spectrum.channels[0].type = type;
	if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;

2105
	rc = iwl_send_cmd_sync(priv, &cmd);
Z
Zhu Yi 已提交
2106 2107 2108
	if (rc)
		return rc;

2109
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
Z
Zhu Yi 已提交
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138
	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
		IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
		rc = -EIO;
	}

	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
	switch (spectrum_resp_status) {
	case 0:		/* Command will be handled */
		if (res->u.spectrum.id != 0xff) {
			IWL_DEBUG_INFO
			    ("Replaced existing measurement: %d\n",
			     res->u.spectrum.id);
			priv->measurement_status &= ~MEASUREMENT_READY;
		}
		priv->measurement_status |= MEASUREMENT_ACTIVE;
		rc = 0;
		break;

	case 1:		/* Command will not be handled */
		rc = -EAGAIN;
		break;
	}

	dev_kfree_skb_any(cmd.meta.u.skb);

	return rc;
}
#endif

2139
static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
2140
				     struct iwl_tx_info *tx_sta)
Z
Zhu Yi 已提交
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156
{

	tx_sta->status.ack_signal = 0;
	tx_sta->status.excessive_retries = 0;

	if (in_interrupt())
		ieee80211_tx_status_irqsafe(priv->hw,
					    tx_sta->skb[0], &(tx_sta->status));
	else
		ieee80211_tx_status(priv->hw,
				    tx_sta->skb[0], &(tx_sta->status));

	tx_sta->skb[0] = NULL;
}

/**
2157
 * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
Z
Zhu Yi 已提交
2158
 *
2159 2160 2161
 * When FW advances 'R' index, all entries between old and new 'R' index
 * need to be reclaimed. As result, some free space forms.  If there is
 * enough free space (> low mark), wake the stack that feeds us.
Z
Zhu Yi 已提交
2162
 */
2163
int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
Z
Zhu Yi 已提交
2164
{
2165
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
2166
	struct iwl_queue *q = &txq->q;
Z
Zhu Yi 已提交
2167 2168
	int nfreed = 0;

2169
	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
Z
Zhu Yi 已提交
2170 2171
		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
			  "is out of range [0-%d] %d %d.\n", txq_id,
2172
			  index, q->n_bd, q->write_ptr, q->read_ptr);
Z
Zhu Yi 已提交
2173 2174 2175
		return 0;
	}

T
Tomas Winkler 已提交
2176
	for (index = iwl_queue_inc_wrap(index, q->n_bd);
2177
		q->read_ptr != index;
T
Tomas Winkler 已提交
2178
		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
Z
Zhu Yi 已提交
2179
		if (txq_id != IWL_CMD_QUEUE_NUM) {
C
Christoph Hellwig 已提交
2180
			iwl4965_txstatus_to_ieee(priv,
2181
					&(txq->txb[txq->q.read_ptr]));
2182
			iwl_hw_txq_free_tfd(priv, txq);
Z
Zhu Yi 已提交
2183 2184
		} else if (nfreed > 1) {
			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
2185
					q->write_ptr, q->read_ptr);
Z
Zhu Yi 已提交
2186 2187 2188 2189 2190 2191 2192 2193
			queue_work(priv->workqueue, &priv->restart);
		}
		nfreed++;
	}

	return nfreed;
}

C
Christoph Hellwig 已提交
2194
static int iwl4965_is_tx_success(u32 status)
Z
Zhu Yi 已提交
2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205
{
	status &= TX_STATUS_MSK;
	return (status == TX_STATUS_SUCCESS)
	    || (status == TX_STATUS_DIRECT_DONE);
}

/******************************************************************************
 *
 * Generic RX handler implementations
 *
 ******************************************************************************/
2206
#ifdef CONFIG_IWL4965_HT
Z
Zhu Yi 已提交
2207

2208
static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
Z
Zhu Yi 已提交
2209 2210 2211 2212 2213 2214
				    struct ieee80211_hdr *hdr)
{
	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
		return IWL_AP_ID;
	else {
		u8 *da = ieee80211_get_DA(hdr);
2215
		return iwl_find_station(priv, da);
Z
Zhu Yi 已提交
2216 2217 2218
	}
}

C
Christoph Hellwig 已提交
2219
static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
2220
	struct iwl_priv *priv, int txq_id, int idx)
Z
Zhu Yi 已提交
2221 2222 2223 2224 2225 2226 2227
{
	if (priv->txq[txq_id].txb[idx].skb[0])
		return (struct ieee80211_hdr *)priv->txq[txq_id].
				txb[idx].skb[0]->data;
	return NULL;
}

C
Christoph Hellwig 已提交
2228
static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
Z
Zhu Yi 已提交
2229 2230 2231 2232 2233 2234
{
	__le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
				tx_resp->frame_count);
	return le32_to_cpu(*scd_ssn) & MAX_SN;

}
2235 2236 2237 2238

/**
 * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
 */
2239
static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
2240
				      struct iwl_ht_agg *agg,
2241
				      struct iwl4965_tx_resp_agg *tx_resp,
Z
Zhu Yi 已提交
2242 2243
				      u16 start_idx)
{
2244 2245
	u16 status;
	struct agg_tx_status *frame_status = &tx_resp->status;
Z
Zhu Yi 已提交
2246 2247 2248 2249 2250 2251 2252
	struct ieee80211_tx_status *tx_status = NULL;
	struct ieee80211_hdr *hdr = NULL;
	int i, sh;
	int txq_id, idx;
	u16 seq;

	if (agg->wait_for_ba)
2253
		IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
Z
Zhu Yi 已提交
2254 2255 2256 2257

	agg->frame_count = tx_resp->frame_count;
	agg->start_idx = start_idx;
	agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
2258
	agg->bitmap = 0;
Z
Zhu Yi 已提交
2259

2260
	/* # frames attempted by Tx command */
Z
Zhu Yi 已提交
2261
	if (agg->frame_count == 1) {
2262
		/* Only one frame was attempted; no block-ack will arrive */
2263 2264 2265 2266
		status = le16_to_cpu(frame_status[0].status);
		seq  = le16_to_cpu(frame_status[0].sequence);
		idx = SEQ_TO_INDEX(seq);
		txq_id = SEQ_TO_QUEUE(seq);
Z
Zhu Yi 已提交
2267 2268

		/* FIXME: code repetition */
2269 2270
		IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
				   agg->frame_count, agg->start_idx, idx);
Z
Zhu Yi 已提交
2271

2272
		tx_status = &(priv->txq[txq_id].txb[idx].status);
Z
Zhu Yi 已提交
2273
		tx_status->retry_count = tx_resp->failure_frame;
2274
		tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
C
Christoph Hellwig 已提交
2275
		tx_status->flags = iwl4965_is_tx_success(status)?
Z
Zhu Yi 已提交
2276
			IEEE80211_TX_STATUS_ACK : 0;
2277 2278 2279
		iwl4965_hwrate_to_tx_control(priv,
					     le32_to_cpu(tx_resp->rate_n_flags),
					     &tx_status->control);
Z
Zhu Yi 已提交
2280 2281 2282 2283 2284
		/* FIXME: code repetition end */

		IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
				    status & 0xff, tx_resp->failure_frame);
		IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
C
Christoph Hellwig 已提交
2285
				iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
Z
Zhu Yi 已提交
2286 2287 2288

		agg->wait_for_ba = 0;
	} else {
2289
		/* Two or more frames were attempted; expect block-ack */
Z
Zhu Yi 已提交
2290 2291 2292
		u64 bitmap = 0;
		int start = agg->start_idx;

2293
		/* Construct bit-map of pending frames within Tx window */
Z
Zhu Yi 已提交
2294 2295
		for (i = 0; i < agg->frame_count; i++) {
			u16 sc;
2296 2297
			status = le16_to_cpu(frame_status[i].status);
			seq  = le16_to_cpu(frame_status[i].sequence);
Z
Zhu Yi 已提交
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
			idx = SEQ_TO_INDEX(seq);
			txq_id = SEQ_TO_QUEUE(seq);

			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
				      AGG_TX_STATE_ABORT_MSK))
				continue;

			IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
					   agg->frame_count, txq_id, idx);

C
Christoph Hellwig 已提交
2308
			hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, idx);
Z
Zhu Yi 已提交
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340

			sc = le16_to_cpu(hdr->seq_ctrl);
			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
				IWL_ERROR("BUG_ON idx doesn't match seq control"
					  " idx=%d, seq_idx=%d, seq=%d\n",
					  idx, SEQ_TO_SN(sc),
					  hdr->seq_ctrl);
				return -1;
			}

			IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
					   i, idx, SEQ_TO_SN(sc));

			sh = idx - start;
			if (sh > 64) {
				sh = (start - idx) + 0xff;
				bitmap = bitmap << sh;
				sh = 0;
				start = idx;
			} else if (sh < -64)
				sh  = 0xff - (start - idx);
			else if (sh < 0) {
				sh = start - idx;
				start = idx;
				bitmap = bitmap << sh;
				sh = 0;
			}
			bitmap |= (1 << sh);
			IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
					   start, (u32)(bitmap & 0xFFFFFFFF));
		}

2341
		agg->bitmap = bitmap;
Z
Zhu Yi 已提交
2342 2343
		agg->start_idx = start;
		agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
2344
		IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
Z
Zhu Yi 已提交
2345
				   agg->frame_count, agg->start_idx,
2346
				   (unsigned long long)agg->bitmap);
Z
Zhu Yi 已提交
2347 2348 2349 2350 2351 2352 2353 2354

		if (bitmap)
			agg->wait_for_ba = 1;
	}
	return 0;
}
#endif

2355 2356 2357
/**
 * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
 */
2358
static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2359
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2360
{
2361
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2362 2363 2364
	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
	int txq_id = SEQ_TO_QUEUE(sequence);
	int index = SEQ_TO_INDEX(sequence);
2365
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
Z
Zhu Yi 已提交
2366
	struct ieee80211_tx_status *tx_status;
C
Christoph Hellwig 已提交
2367
	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
Z
Zhu Yi 已提交
2368
	u32  status = le32_to_cpu(tx_resp->status);
2369
#ifdef CONFIG_IWL4965_HT
2370
	int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
2371
	u16 fc;
2372
	struct ieee80211_hdr *hdr;
2373
	u8 *qc = NULL;
Z
Zhu Yi 已提交
2374 2375
#endif

2376
	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
Z
Zhu Yi 已提交
2377 2378
		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
			  "is out of range [0-%d] %d %d\n", txq_id,
2379 2380
			  index, txq->q.n_bd, txq->q.write_ptr,
			  txq->q.read_ptr);
Z
Zhu Yi 已提交
2381 2382 2383
		return;
	}

2384
#ifdef CONFIG_IWL4965_HT
2385
	hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
2386 2387 2388 2389 2390
	fc = le16_to_cpu(hdr->frame_control);
	if (ieee80211_is_qos_data(fc)) {
		qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
		tid = qc[0] & 0xf;
	}
2391 2392 2393 2394 2395 2396 2397

	sta_id = iwl4965_get_ra_sta_id(priv, hdr);
	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
		IWL_ERROR("Station not known\n");
		return;
	}

Z
Zhu Yi 已提交
2398
	if (txq->sched_retry) {
C
Christoph Hellwig 已提交
2399
		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
2400
		struct iwl_ht_agg *agg = NULL;
Z
Zhu Yi 已提交
2401

2402
		if (!qc)
Z
Zhu Yi 已提交
2403 2404 2405 2406
			return;

		agg = &priv->stations[sta_id].tid[tid].agg;

2407 2408
		iwl4965_tx_status_reply_tx(priv, agg,
				(struct iwl4965_tx_resp_agg *)tx_resp, index);
Z
Zhu Yi 已提交
2409 2410

		if ((tx_resp->frame_count == 1) &&
C
Christoph Hellwig 已提交
2411
		    !iwl4965_is_tx_success(status)) {
Z
Zhu Yi 已提交
2412 2413 2414
			/* TODO: send BAR */
		}

2415
		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
2416
			int freed, ampdu_q;
T
Tomas Winkler 已提交
2417
			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
Z
Zhu Yi 已提交
2418 2419
			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
					   "%d index %d\n", scd_ssn , index);
2420 2421 2422
			freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;

2423
			if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
2424
			    txq_id >= 0 && priv->mac80211_registered &&
2425 2426 2427 2428 2429 2430 2431 2432 2433
			    agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
				/* calculate mac80211 ampdu sw queue to wake */
				ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
					  priv->hw->queues;
				if (agg->state == IWL_AGG_OFF)
					ieee80211_wake_queue(priv->hw, txq_id);
				else
					ieee80211_wake_queue(priv->hw, ampdu_q);
			}
2434
			iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
Z
Zhu Yi 已提交
2435 2436
		}
	} else {
2437
#endif /* CONFIG_IWL4965_HT */
2438
	tx_status = &(txq->txb[txq->q.read_ptr].status);
Z
Zhu Yi 已提交
2439 2440 2441

	tx_status->retry_count = tx_resp->failure_frame;
	tx_status->flags =
C
Christoph Hellwig 已提交
2442
	    iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
2443 2444
	iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
				     &tx_status->control);
Z
Zhu Yi 已提交
2445 2446

	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
C
Christoph Hellwig 已提交
2447
		     "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
Z
Zhu Yi 已提交
2448 2449 2450 2451
		     status, le32_to_cpu(tx_resp->rate_n_flags),
		     tx_resp->failure_frame);

	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
2452
#ifdef CONFIG_IWL4965_HT
2453 2454 2455 2456
	if (index != -1) {
		int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
		if (tid != MAX_TID_COUNT)
			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
2457
		if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
2458
			(txq_id >= 0) && priv->mac80211_registered)
2459 2460 2461 2462
			ieee80211_wake_queue(priv->hw, txq_id);
		if (tid != MAX_TID_COUNT)
			iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
	}
Z
Zhu Yi 已提交
2463
	}
2464
#endif /* CONFIG_IWL4965_HT */
Z
Zhu Yi 已提交
2465 2466 2467 2468 2469 2470

	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
}


2471
static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
2472
				   struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2473
{
2474
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2475
	struct iwl4965_alive_resp *palive;
Z
Zhu Yi 已提交
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
	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,
C
Christoph Hellwig 已提交
2489
		       sizeof(struct iwl4965_init_alive_resp));
Z
Zhu Yi 已提交
2490 2491 2492 2493
		pwork = &priv->init_alive_start;
	} else {
		IWL_DEBUG_INFO("Runtime Alive received.\n");
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
C
Christoph Hellwig 已提交
2494
		       sizeof(struct iwl4965_alive_resp));
Z
Zhu Yi 已提交
2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
		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
		IWL_WARNING("uCode did not respond OK.\n");
}

2507
static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
2508
				     struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2509
{
2510
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2511 2512 2513 2514 2515

	IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
	return;
}

2516
static void iwl4965_rx_reply_error(struct iwl_priv *priv,
2517
				   struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2518
{
2519
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531

	IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
		"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

2532
static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2533
{
2534
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
G
Gregory Greenman 已提交
2535
	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
C
Christoph Hellwig 已提交
2536
	struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
Z
Zhu Yi 已提交
2537 2538 2539 2540 2541 2542
	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;
}

2543
static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
2544
					  struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2545
{
2546
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
2547
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2548
	struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
Z
Zhu Yi 已提交
2549 2550

	if (!report->state) {
2551 2552
		IWL_DEBUG(IWL_DL_11H,
			"Spectrum Measure Notification: Start\n");
Z
Zhu Yi 已提交
2553 2554 2555 2556 2557 2558 2559 2560
		return;
	}

	memcpy(&priv->measure_report, report, sizeof(*report));
	priv->measurement_status |= MEASUREMENT_READY;
#endif
}

2561
static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
2562
				      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2563
{
2564
#ifdef CONFIG_IWLWIFI_DEBUG
2565
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2566
	struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
Z
Zhu Yi 已提交
2567 2568 2569 2570 2571
	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}

2572
static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
2573
					     struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2574
{
2575
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2576 2577 2578
	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
			"notification for %s:\n",
			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
2579
	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
Z
Zhu Yi 已提交
2580 2581
}

C
Christoph Hellwig 已提交
2582
static void iwl4965_bg_beacon_update(struct work_struct *work)
Z
Zhu Yi 已提交
2583
{
2584 2585
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
Z
Zhu Yi 已提交
2586 2587 2588
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
2589
	beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
Z
Zhu Yi 已提交
2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603

	if (!beacon) {
		IWL_ERROR("update beacon failed\n");
		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);

C
Christoph Hellwig 已提交
2604
	iwl4965_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
2605 2606
}

2607
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
2608
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2609
{
2610
#ifdef CONFIG_IWLWIFI_DEBUG
2611
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2612 2613
	struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
	u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
Z
Zhu Yi 已提交
2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629

	IWL_DEBUG_RX("beacon status %x retries %d iss %d "
		"tsf %d %d rate %d\n",
		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
		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

	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
		queue_work(priv->workqueue, &priv->beacon_update);
}

/* Service response to REPLY_SCAN_CMD (0x80) */
2630
static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
2631
			      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2632
{
2633
#ifdef CONFIG_IWLWIFI_DEBUG
2634
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2635 2636
	struct iwl4965_scanreq_notification *notif =
	    (struct iwl4965_scanreq_notification *)pkt->u.raw;
Z
Zhu Yi 已提交
2637 2638 2639 2640 2641 2642

	IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
#endif
}

/* Service SCAN_START_NOTIFICATION (0x82) */
2643
static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
2644
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2645
{
2646
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2647 2648
	struct iwl4965_scanstart_notification *notif =
	    (struct iwl4965_scanstart_notification *)pkt->u.raw;
Z
Zhu Yi 已提交
2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659
	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
	IWL_DEBUG_SCAN("Scan start: "
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       notif->tsf_high,
		       notif->tsf_low, notif->status, notif->beacon_timer);
}

/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
2660
static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
2661
				      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2662
{
2663
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2664 2665
	struct iwl4965_scanresults_notification *notif =
	    (struct iwl4965_scanresults_notification *)pkt->u.raw;
Z
Zhu Yi 已提交
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680

	IWL_DEBUG_SCAN("Scan ch.res: "
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d "
		       "elapsed=%lu usec (%dms since last)\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       le32_to_cpu(notif->tsf_high),
		       le32_to_cpu(notif->tsf_low),
		       le32_to_cpu(notif->statistics[0]),
		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
		       jiffies_to_msecs(elapsed_jiffies
					(priv->last_scan_jiffies, jiffies)));

	priv->last_scan_jiffies = jiffies;
2681
	priv->next_scan_jiffies = 0;
Z
Zhu Yi 已提交
2682 2683 2684
}

/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
2685
static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
2686
				       struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2687
{
2688
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
C
Christoph Hellwig 已提交
2689
	struct iwl4965_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
Z
Zhu Yi 已提交
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723

	IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
		       scan_notif->scanned_channels,
		       scan_notif->tsf_low,
		       scan_notif->tsf_high, scan_notif->status);

	/* The HW is no longer scanning */
	clear_bit(STATUS_SCAN_HW, &priv->status);

	/* The scan completion notification came in, so kill that timer... */
	cancel_delayed_work(&priv->scan_check);

	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
		       (priv->scan_bands == 2) ? "2.4" : "5.2",
		       jiffies_to_msecs(elapsed_jiffies
					(priv->scan_pass_start, jiffies)));

	/* Remove this scanned band from the list
	 * of pending bands to scan */
	priv->scan_bands--;

	/* If a request to abort was given, or the scan did not succeed
	 * then we reset the scan state machine and terminate,
	 * re-queuing another scan if one has been requested */
	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_INFO("Aborted scan completed.\n");
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
	} else {
		/* If there are more bands on this scan pass reschedule */
		if (priv->scan_bands > 0)
			goto reschedule;
	}

	priv->last_scan_jiffies = jiffies;
2724
	priv->next_scan_jiffies = 0;
Z
Zhu Yi 已提交
2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742
	IWL_DEBUG_INFO("Setting scan to off\n");

	clear_bit(STATUS_SCANNING, &priv->status);

	IWL_DEBUG_INFO("Scan took %dms\n",
		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));

	queue_work(priv->workqueue, &priv->scan_completed);

	return;

reschedule:
	priv->scan_pass_start = jiffies;
	queue_work(priv->workqueue, &priv->request_scan);
}

/* Handle notification from uCode that card's power state is changing
 * due to software, hardware, or critical temperature RFKILL */
2743
static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
2744
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2745
{
2746
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
	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)) {

2757
		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
2758 2759
			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

2760 2761
		if (!iwl_grab_nic_access(priv)) {
			iwl_write_direct32(
Z
Zhu Yi 已提交
2762 2763 2764
				priv, HBUS_TARG_MBX_C,
				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

2765
			iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2766 2767 2768
		}

		if (!(flags & RXON_CARD_DISABLED)) {
2769
			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
Z
Zhu Yi 已提交
2770
				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
2771 2772
			if (!iwl_grab_nic_access(priv)) {
				iwl_write_direct32(
Z
Zhu Yi 已提交
2773 2774 2775
					priv, HBUS_TARG_MBX_C,
					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);

2776
				iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2777 2778 2779 2780
			}
		}

		if (flags & RF_CARD_DISABLED) {
2781
			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
2782
				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
2783 2784 2785
			iwl_read32(priv, CSR_UCODE_DRV_GP1);
			if (!iwl_grab_nic_access(priv))
				iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800
		}
	}

	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))
C
Christoph Hellwig 已提交
2801
		iwl4965_scan_cancel(priv);
Z
Zhu Yi 已提交
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812

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

/**
C
Christoph Hellwig 已提交
2813
 * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
Z
Zhu Yi 已提交
2814 2815 2816 2817 2818 2819 2820
 *
 * 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.
 */
2821
static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2822
{
C
Christoph Hellwig 已提交
2823 2824 2825 2826
	priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
	priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
	priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
Z
Zhu Yi 已提交
2827
	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
C
Christoph Hellwig 已提交
2828 2829
	    iwl4965_rx_spectrum_measure_notif;
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl4965_rx_pm_sleep_notif;
Z
Zhu Yi 已提交
2830
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
C
Christoph Hellwig 已提交
2831 2832
	    iwl4965_rx_pm_debug_statistics_notif;
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
Z
Zhu Yi 已提交
2833

2834 2835 2836 2837
	/*
	 * 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 已提交
2838
	 */
C
Christoph Hellwig 已提交
2839 2840
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
Z
Zhu Yi 已提交
2841

C
Christoph Hellwig 已提交
2842 2843
	priv->rx_handlers[REPLY_SCAN_CMD] = iwl4965_rx_reply_scan;
	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl4965_rx_scan_start_notif;
Z
Zhu Yi 已提交
2844
	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
C
Christoph Hellwig 已提交
2845
	    iwl4965_rx_scan_results_notif;
Z
Zhu Yi 已提交
2846
	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
C
Christoph Hellwig 已提交
2847 2848 2849
	    iwl4965_rx_scan_complete_notif;
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
	priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
Z
Zhu Yi 已提交
2850

2851
	/* Set up hardware specific Rx handlers */
2852
	priv->cfg->ops->lib->rx_handler_setup(priv);
Z
Zhu Yi 已提交
2853 2854 2855
}

/**
C
Christoph Hellwig 已提交
2856
 * iwl4965_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
Z
Zhu Yi 已提交
2857 2858 2859 2860 2861 2862
 * @rxb: Rx buffer to reclaim
 *
 * If an Rx buffer has an async callback associated with it the callback
 * will be executed.  The attached skb (if present) will only be freed
 * if the callback returns 1
 */
2863
static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
2864
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
2865
{
2866
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2867 2868 2869 2870 2871
	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
	int txq_id = SEQ_TO_QUEUE(sequence);
	int index = SEQ_TO_INDEX(sequence);
	int huge = sequence & SEQ_HUGE_FRAME;
	int cmd_index;
2872
	struct iwl_cmd *cmd;
Z
Zhu Yi 已提交
2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892

	/* If a Tx command is being handled and it isn't in the actual
	 * command queue then there a command routing bug has been introduced
	 * in the queue management code. */
	if (txq_id != IWL_CMD_QUEUE_NUM)
		IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
			  txq_id, pkt->hdr.cmd);
	BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);

	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
	cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];

	/* Input error checking is done when commands are added to queue. */
	if (cmd->meta.flags & CMD_WANT_SKB) {
		cmd->meta.source->u.skb = rxb->skb;
		rxb->skb = NULL;
	} else if (cmd->meta.u.callback &&
		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
		rxb->skb = NULL;

C
Christoph Hellwig 已提交
2893
	iwl4965_tx_queue_reclaim(priv, txq_id, index);
Z
Zhu Yi 已提交
2894 2895 2896 2897 2898 2899 2900

	if (!(cmd->meta.flags & CMD_ASYNC)) {
		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
		wake_up_interruptible(&priv->wait_command_queue);
	}
}

2901 2902 2903
/*
 * this should be called while priv->lock is locked
*/
2904
static void __iwl_rx_replenish(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2905
{
2906 2907
	iwl_rx_allocate(priv);
	iwl_rx_queue_restock(priv);
Z
Zhu Yi 已提交
2908 2909 2910 2911
}


/**
2912
 * iwl_rx_handle - Main entry function for receiving responses from uCode
Z
Zhu Yi 已提交
2913 2914 2915 2916 2917
 *
 * Uses the priv->rx_handlers callback function array to invoke
 * the appropriate handlers, including command responses,
 * frame-received notifications, and other notifications.
 */
2918
void iwl_rx_handle(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2919
{
2920
	struct iwl_rx_mem_buffer *rxb;
2921
	struct iwl_rx_packet *pkt;
2922
	struct iwl_rx_queue *rxq = &priv->rxq;
Z
Zhu Yi 已提交
2923 2924 2925
	u32 r, i;
	int reclaim;
	unsigned long flags;
2926
	u8 fill_rx = 0;
M
Mohamed Abbas 已提交
2927
	u32 count = 8;
Z
Zhu Yi 已提交
2928

2929 2930
	/* uCode's read index (stored in shared DRAM) indicates the last Rx
	 * buffer that the driver may process (last buffer filled by ucode). */
2931
	r = priv->cfg->ops->lib->shared_mem_rx_idx(priv);
Z
Zhu Yi 已提交
2932 2933 2934 2935
	i = rxq->read;

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

2938
	if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
2939 2940
		fill_rx = 1;

Z
Zhu Yi 已提交
2941 2942 2943
	while (i != r) {
		rxb = rxq->queue[i];

2944
		/* If an RXB doesn't have a Rx queue slot associated with it,
Z
Zhu Yi 已提交
2945 2946 2947 2948 2949 2950 2951
		 * then a bug has been introduced in the queue refilling
		 * routines -- catch it here */
		BUG_ON(rxb == NULL);

		rxq->queue[i] = NULL;

		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
T
Tomas Winkler 已提交
2952
					    priv->hw_params.rx_buf_size,
Z
Zhu Yi 已提交
2953
					    PCI_DMA_FROMDEVICE);
2954
		pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2955 2956 2957 2958 2959 2960 2961 2962 2963

		/* 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) &&
2964
			(pkt->hdr.cmd != REPLY_RX) &&
2965
			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
Z
Zhu Yi 已提交
2966 2967 2968 2969 2970
			(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
C
Christoph Hellwig 已提交
2971
		 *   rx_handlers table.  See iwl4965_setup_rx_handlers() */
Z
Zhu Yi 已提交
2972
		if (priv->rx_handlers[pkt->hdr.cmd]) {
2973 2974
			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 已提交
2975 2976 2977
			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
		} else {
			/* No handling needed */
2978
			IWL_DEBUG(IWL_DL_RX,
Z
Zhu Yi 已提交
2979 2980 2981 2982 2983 2984
				"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) {
2985
			/* Invoke any callbacks, transfer the skb to caller, and
2986
			 * fire off the (possibly) blocking iwl_send_cmd()
Z
Zhu Yi 已提交
2987 2988
			 * as we reclaim the driver command queue */
			if (rxb && rxb->skb)
C
Christoph Hellwig 已提交
2989
				iwl4965_tx_cmd_complete(priv, rxb);
Z
Zhu Yi 已提交
2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
			else
				IWL_WARNING("Claim null rxb?\n");
		}

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

		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
T
Tomas Winkler 已提交
3004
				 priv->hw_params.rx_buf_size,
3005
				 PCI_DMA_FROMDEVICE);
Z
Zhu Yi 已提交
3006 3007 3008 3009
		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;
3010 3011 3012 3013 3014 3015
		/* 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;
3016
				__iwl_rx_replenish(priv);
3017 3018 3019
				count = 0;
			}
		}
Z
Zhu Yi 已提交
3020 3021 3022 3023
	}

	/* Backtrack one entry */
	priv->rxq.read = i;
3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101
	iwl_rx_queue_restock(priv);
}
/* Convert linear signal-to-noise ratio into dB */
static u8 ratio2dB[100] = {
/*	 0   1   2   3   4   5   6   7   8   9 */
	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
};

/* Calculates a relative dB value from a ratio of linear
 *   (i.e. not dB) signal levels.
 * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
int iwl4965_calc_db_from_ratio(int sig_ratio)
{
	/* 1000:1 or higher just report as 60 dB */
	if (sig_ratio >= 1000)
		return 60;

	/* 100:1 or higher, divide by 10 and use table,
	 *   add 20 dB to make up for divide by 10 */
	if (sig_ratio >= 100)
		return (20 + (int)ratio2dB[sig_ratio/10]);

	/* We shouldn't see this */
	if (sig_ratio < 1)
		return 0;

	/* Use table for ratios 1:1 - 99:1 */
	return (int)ratio2dB[sig_ratio];
}

#define PERFECT_RSSI (-20) /* dBm */
#define WORST_RSSI (-95)   /* dBm */
#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)

/* Calculate an indication of rx signal quality (a percentage, not dBm!).
 * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
 *   about formulas used below. */
int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
{
	int sig_qual;
	int degradation = PERFECT_RSSI - rssi_dbm;

	/* If we get a noise measurement, use signal-to-noise ratio (SNR)
	 * as indicator; formula is (signal dbm - noise dbm).
	 * SNR at or above 40 is a great signal (100%).
	 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
	 * Weakest usable signal is usually 10 - 15 dB SNR. */
	if (noise_dbm) {
		if (rssi_dbm - noise_dbm >= 40)
			return 100;
		else if (rssi_dbm < noise_dbm)
			return 0;
		sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;

	/* Else use just the signal level.
	 * This formula is a least squares fit of data points collected and
	 *   compared with a reference system that had a percentage (%) display
	 *   for signal quality. */
	} else
		sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
			    (15 * RSSI_RANGE + 62 * degradation)) /
			   (RSSI_RANGE * RSSI_RANGE);

	if (sig_qual > 100)
		sig_qual = 100;
	else if (sig_qual < 1)
		sig_qual = 0;

	return sig_qual;
Z
Zhu Yi 已提交
3102 3103
}

3104
/**
3105
 * iwl_txq_update_write_ptr - Send new write index to hardware
3106
 */
3107
static int iwl_txq_update_write_ptr(struct iwl_priv *priv,
3108
				  struct iwl_tx_queue *txq)
Z
Zhu Yi 已提交
3109 3110
{
	u32 reg = 0;
3111
	int ret = 0;
Z
Zhu Yi 已提交
3112 3113 3114
	int txq_id = txq->q.id;

	if (txq->need_update == 0)
3115
		return ret;
Z
Zhu Yi 已提交
3116 3117 3118 3119 3120 3121

	/* if we're trying to save power */
	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
		/* wake up nic if it's powered down ...
		 * uCode will wake up, and interrupt us again, so next
		 * time we'll skip this part. */
3122
		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
Z
Zhu Yi 已提交
3123 3124 3125

		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
			IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
3126
			iwl_set_bit(priv, CSR_GP_CNTRL,
Z
Zhu Yi 已提交
3127
				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
3128
			return ret;
Z
Zhu Yi 已提交
3129 3130 3131
		}

		/* restore this queue's parameters in nic hardware. */
3132 3133 3134
		ret = iwl_grab_nic_access(priv);
		if (ret)
			return ret;
3135
		iwl_write_direct32(priv, HBUS_TARG_WRPTR,
3136
				     txq->q.write_ptr | (txq_id << 8));
3137
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3138 3139 3140 3141

	/* else not in power-save mode, uCode will never sleep when we're
	 * trying to tx (during RFKILL, we're not trying to tx). */
	} else
3142
		iwl_write32(priv, HBUS_TARG_WRPTR,
3143
			    txq->q.write_ptr | (txq_id << 8));
Z
Zhu Yi 已提交
3144 3145 3146

	txq->need_update = 0;

3147
	return ret;
Z
Zhu Yi 已提交
3148 3149
}

3150
#ifdef CONFIG_IWLWIFI_DEBUG
3151
static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3152
{
G
Gregory Greenman 已提交
3153
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
3154 3155
	DECLARE_MAC_BUF(mac);

Z
Zhu Yi 已提交
3156
	IWL_DEBUG_RADIO("RX CONFIG:\n");
3157
	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
Z
Zhu Yi 已提交
3158 3159 3160 3161 3162 3163 3164 3165
	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);
3166 3167 3168 3169
	IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
			print_mac(mac, rxon->node_addr));
	IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
			print_mac(mac, rxon->bssid_addr));
Z
Zhu Yi 已提交
3170 3171 3172 3173
	IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif

3174
static void iwl4965_enable_interrupts(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3175 3176 3177
{
	IWL_DEBUG_ISR("Enabling interrupts\n");
	set_bit(STATUS_INT_ENABLED, &priv->status);
3178
	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
Z
Zhu Yi 已提交
3179 3180
}

3181 3182 3183 3184 3185 3186 3187 3188
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
	/* wait to make sure we flush pedding tasklet*/
	synchronize_irq(priv->pci_dev->irq);
	tasklet_kill(&priv->irq_tasklet);
}

3189
static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3190 3191 3192 3193
{
	clear_bit(STATUS_INT_ENABLED, &priv->status);

	/* disable interrupts from uCode/NIC to host */
3194
	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
Z
Zhu Yi 已提交
3195 3196 3197

	/* acknowledge/clear/reset any interrupts still pending
	 * from uCode or flow handler (Rx/Tx DMA) */
3198 3199
	iwl_write32(priv, CSR_INT, 0xffffffff);
	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
Z
Zhu Yi 已提交
3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225
	IWL_DEBUG_ISR("Disabled interrupts\n");
}

static const char *desc_lookup(int i)
{
	switch (i) {
	case 1:
		return "FAIL";
	case 2:
		return "BAD_PARAM";
	case 3:
		return "BAD_CHECKSUM";
	case 4:
		return "NMI_INTERRUPT";
	case 5:
		return "SYSASSERT";
	case 6:
		return "FATAL_ERROR";
	}

	return "UNKNOWN";
}

#define ERROR_START_OFFSET  (1 * sizeof(u32))
#define ERROR_ELEM_SIZE     (7 * sizeof(u32))

3226
static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3227 3228 3229 3230 3231 3232 3233 3234
{
	u32 data2, line;
	u32 desc, time, count, base, data1;
	u32 blink1, blink2, ilink1, ilink2;
	int rc;

	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);

3235
	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
Z
Zhu Yi 已提交
3236 3237 3238 3239
		IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
		return;
	}

3240
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
3241 3242 3243 3244 3245
	if (rc) {
		IWL_WARNING("Can not read from adapter at this time.\n");
		return;
	}

3246
	count = iwl_read_targ_mem(priv, base);
Z
Zhu Yi 已提交
3247 3248 3249

	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
		IWL_ERROR("Start IWL Error Log Dump:\n");
3250
		IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
Z
Zhu Yi 已提交
3251 3252
	}

3253 3254 3255 3256 3257 3258 3259 3260 3261
	desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
	blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
	blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
	ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
	ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
	data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
	data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
	line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
	time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
Z
Zhu Yi 已提交
3262 3263 3264 3265 3266 3267 3268 3269 3270

	IWL_ERROR("Desc               Time       "
		  "data1      data2      line\n");
	IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
		  desc_lookup(desc), desc, time, data1, data2, line);
	IWL_ERROR("blink1  blink2  ilink1  ilink2\n");
	IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
		  ilink1, ilink2);

3271
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3272 3273 3274 3275 3276
}

#define EVENT_START_OFFSET  (4 * sizeof(u32))

/**
C
Christoph Hellwig 已提交
3277
 * iwl4965_print_event_log - Dump error event log to syslog
Z
Zhu Yi 已提交
3278
 *
3279
 * NOTE: Must be called with iwl_grab_nic_access() already obtained!
Z
Zhu Yi 已提交
3280
 */
3281
static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
Z
Zhu Yi 已提交
3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304
				u32 num_events, u32 mode)
{
	u32 i;
	u32 base;       /* SRAM byte address of event log header */
	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
	u32 ptr;        /* SRAM byte address of log data */
	u32 ev, time, data; /* event log data */

	if (num_events == 0)
		return;

	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);

	if (mode == 0)
		event_size = 2 * sizeof(u32);
	else
		event_size = 3 * sizeof(u32);

	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);

	/* "time" is actually "data" for mode 0 (no timestamp).
	 * place event id # at far right for easier visual parsing. */
	for (i = 0; i < num_events; i++) {
3305
		ev = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
3306
		ptr += sizeof(u32);
3307
		time = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
3308 3309 3310 3311
		ptr += sizeof(u32);
		if (mode == 0)
			IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
		else {
3312
			data = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
3313 3314 3315 3316 3317 3318
			ptr += sizeof(u32);
			IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
		}
	}
}

3319
static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3320 3321 3322 3323 3324 3325 3326 3327 3328 3329
{
	int rc;
	u32 base;       /* SRAM byte address of event log header */
	u32 capacity;   /* event log capacity in # entries */
	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
	u32 num_wraps;  /* # times uCode wrapped to top of log */
	u32 next_entry; /* index of next entry to be written by uCode */
	u32 size;       /* # entries that we'll print */

	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
3330
	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
Z
Zhu Yi 已提交
3331 3332 3333 3334
		IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
		return;
	}

3335
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
3336 3337 3338 3339 3340 3341
	if (rc) {
		IWL_WARNING("Can not read from adapter at this time.\n");
		return;
	}

	/* event log header */
3342 3343 3344 3345
	capacity = iwl_read_targ_mem(priv, base);
	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
Z
Zhu Yi 已提交
3346 3347 3348 3349 3350

	size = num_wraps ? capacity : next_entry;

	/* bail out if nothing in log */
	if (size == 0) {
3351
		IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
3352
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3353 3354 3355
		return;
	}

3356
	IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
Z
Zhu Yi 已提交
3357 3358 3359 3360 3361
		  size, num_wraps);

	/* if uCode has wrapped back to top of log, start at the oldest entry,
	 * i.e the next one that uCode would fill. */
	if (num_wraps)
C
Christoph Hellwig 已提交
3362
		iwl4965_print_event_log(priv, next_entry,
Z
Zhu Yi 已提交
3363 3364 3365
				    capacity - next_entry, mode);

	/* (then/else) start at top of log */
C
Christoph Hellwig 已提交
3366
	iwl4965_print_event_log(priv, 0, next_entry, mode);
Z
Zhu Yi 已提交
3367

3368
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3369 3370 3371
}

/**
C
Christoph Hellwig 已提交
3372
 * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
Z
Zhu Yi 已提交
3373
 */
3374
static void iwl4965_irq_handle_error(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3375
{
C
Christoph Hellwig 已提交
3376
	/* Set the FW error flag -- cleared on iwl4965_down */
Z
Zhu Yi 已提交
3377 3378 3379 3380 3381
	set_bit(STATUS_FW_ERROR, &priv->status);

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

3382
#ifdef CONFIG_IWLWIFI_DEBUG
3383
	if (priv->debug_level & IWL_DL_FW_ERRORS) {
C
Christoph Hellwig 已提交
3384 3385
		iwl4965_dump_nic_error_log(priv);
		iwl4965_dump_nic_event_log(priv);
3386
		iwl4965_print_rx_config_cmd(priv);
Z
Zhu Yi 已提交
3387 3388 3389 3390 3391 3392 3393 3394 3395 3396
	}
#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)) {
3397
		IWL_DEBUG(IWL_DL_FW_ERRORS,
Z
Zhu Yi 已提交
3398 3399
			  "Restarting adapter due to uCode error.\n");

3400
		if (iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
3401 3402 3403 3404
			memcpy(&priv->recovery_rxon, &priv->active_rxon,
			       sizeof(priv->recovery_rxon));
			priv->error_recovering = 1;
		}
3405 3406
		if (priv->cfg->mod_params->restart_fw)
			queue_work(priv->workqueue, &priv->restart);
Z
Zhu Yi 已提交
3407 3408 3409
	}
}

3410
static void iwl4965_error_recovery(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3411 3412 3413 3414 3415 3416
{
	unsigned long flags;

	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
	       sizeof(priv->staging_rxon));
	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
3417
	iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
3418

3419
	iwl_rxon_add_station(priv, priv->bssid, 1);
Z
Zhu Yi 已提交
3420 3421 3422 3423 3424 3425 3426

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

3427
static void iwl4965_irq_tasklet(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3428 3429 3430 3431
{
	u32 inta, handled = 0;
	u32 inta_fh;
	unsigned long flags;
3432
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
3433 3434 3435 3436 3437 3438 3439 3440
	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. */
3441 3442
	inta = iwl_read32(priv, CSR_INT);
	iwl_write32(priv, CSR_INT, inta);
Z
Zhu Yi 已提交
3443 3444 3445 3446

	/* 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. */
3447 3448
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
Z
Zhu Yi 已提交
3449

3450
#ifdef CONFIG_IWLWIFI_DEBUG
3451
	if (priv->debug_level & IWL_DL_ISR) {
3452
		/* just for debug */
3453
		inta_mask = iwl_read32(priv, CSR_INT_MASK);
Z
Zhu Yi 已提交
3454 3455 3456 3457 3458 3459 3460 3461 3462
		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 已提交
3463
	if (inta_fh & CSR49_FH_INT_RX_MASK)
Z
Zhu Yi 已提交
3464
		inta |= CSR_INT_BIT_FH_RX;
T
Tomas Winkler 已提交
3465
	if (inta_fh & CSR49_FH_INT_TX_MASK)
Z
Zhu Yi 已提交
3466 3467 3468 3469 3470 3471 3472
		inta |= CSR_INT_BIT_FH_TX;

	/* Now service all interrupt bits discovered above. */
	if (inta & CSR_INT_BIT_HW_ERR) {
		IWL_ERROR("Microcode HW error detected.  Restarting.\n");

		/* Tell the device to stop sending interrupts */
C
Christoph Hellwig 已提交
3473
		iwl4965_disable_interrupts(priv);
Z
Zhu Yi 已提交
3474

C
Christoph Hellwig 已提交
3475
		iwl4965_irq_handle_error(priv);
Z
Zhu Yi 已提交
3476 3477 3478 3479 3480 3481 3482 3483

		handled |= CSR_INT_BIT_HW_ERR;

		spin_unlock_irqrestore(&priv->lock, flags);

		return;
	}

3484
#ifdef CONFIG_IWLWIFI_DEBUG
3485
	if (priv->debug_level & (IWL_DL_ISR)) {
Z
Zhu Yi 已提交
3486
		/* NIC fires this, but we don't use it, redundant with WAKEUP */
3487 3488 3489
		if (inta & CSR_INT_BIT_SCD)
			IWL_DEBUG_ISR("Scheduler finished to transmit "
				      "the frame/frames.\n");
Z
Zhu Yi 已提交
3490 3491 3492 3493 3494 3495 3496

		/* 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 */
3497
	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
Z
Zhu Yi 已提交
3498

3499
	/* HW RF KILL switch toggled */
Z
Zhu Yi 已提交
3500 3501
	if (inta & CSR_INT_BIT_RF_KILL) {
		int hw_rf_kill = 0;
3502
		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
Z
Zhu Yi 已提交
3503 3504 3505
				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
			hw_rf_kill = 1;

3506
		IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
Z
Zhu Yi 已提交
3507 3508 3509 3510 3511
				hw_rf_kill ? "disable radio":"enable radio");

		/* Queue restart only if RF_KILL switch was set to "kill"
		 *   when we loaded driver, and is now set to "enable".
		 * After we're Alive, RF_KILL gets handled by
3512
		 *   iwl4965_rx_card_state_notif() */
3513 3514
		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
			clear_bit(STATUS_RF_KILL_HW, &priv->status);
Z
Zhu Yi 已提交
3515
			queue_work(priv->workqueue, &priv->restart);
3516
		}
Z
Zhu Yi 已提交
3517 3518 3519 3520

		handled |= CSR_INT_BIT_RF_KILL;
	}

3521
	/* Chip got too hot and stopped itself */
Z
Zhu Yi 已提交
3522 3523 3524 3525 3526 3527 3528 3529 3530
	if (inta & CSR_INT_BIT_CT_KILL) {
		IWL_ERROR("Microcode CT kill error detected.\n");
		handled |= CSR_INT_BIT_CT_KILL;
	}

	/* Error detected by uCode */
	if (inta & CSR_INT_BIT_SW_ERR) {
		IWL_ERROR("Microcode SW error detected.  Restarting 0x%X.\n",
			  inta);
C
Christoph Hellwig 已提交
3531
		iwl4965_irq_handle_error(priv);
Z
Zhu Yi 已提交
3532 3533 3534 3535 3536 3537
		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");
3538
		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
3539 3540 3541 3542 3543 3544
		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 已提交
3545 3546 3547 3548 3549 3550 3551 3552

		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)) {
3553
		iwl_rx_handle(priv);
Z
Zhu Yi 已提交
3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571
		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;
	}

	if (inta & ~handled)
		IWL_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);

	if (inta & ~CSR_INI_SET_MASK) {
		IWL_WARNING("Disabled INTA bits 0x%08x were pending\n",
			 inta & ~CSR_INI_SET_MASK);
		IWL_WARNING("   with FH_INT = 0x%08x\n", inta_fh);
	}

	/* Re-enable all interrupts */
3572 3573 3574
	/* only Re-enable if diabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
		iwl4965_enable_interrupts(priv);
Z
Zhu Yi 已提交
3575

3576
#ifdef CONFIG_IWLWIFI_DEBUG
3577
	if (priv->debug_level & (IWL_DL_ISR)) {
3578 3579 3580
		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 已提交
3581 3582 3583 3584 3585 3586 3587
		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);
}

C
Christoph Hellwig 已提交
3588
static irqreturn_t iwl4965_isr(int irq, void *data)
Z
Zhu Yi 已提交
3589
{
3590
	struct iwl_priv *priv = data;
Z
Zhu Yi 已提交
3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601
	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. */
3602 3603
	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
Z
Zhu Yi 已提交
3604 3605

	/* Discover which interrupts are active/pending */
3606 3607
	inta = iwl_read32(priv, CSR_INT);
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
Z
Zhu Yi 已提交
3608 3609 3610 3611 3612 3613 3614 3615 3616 3617

	/* 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)) {
3618 3619
		/* Hardware disappeared. It might have already raised
		 * an interrupt */
Z
Zhu Yi 已提交
3620
		IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
3621
		goto unplugged;
Z
Zhu Yi 已提交
3622 3623 3624 3625 3626
	}

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

3627 3628
	inta &= ~CSR_INT_BIT_SCD;

C
Christoph Hellwig 已提交
3629
	/* iwl4965_irq_tasklet() will service interrupts and re-enable them */
3630 3631
	if (likely(inta || inta_fh))
		tasklet_schedule(&priv->irq_tasklet);
Z
Zhu Yi 已提交
3632

3633 3634
 unplugged:
	spin_unlock(&priv->lock);
Z
Zhu Yi 已提交
3635 3636 3637 3638
	return IRQ_HANDLED;

 none:
	/* re-enable interrupts here since we don't have anything to service. */
3639 3640 3641
	/* only Re-enable if diabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
		iwl4965_enable_interrupts(priv);
Z
Zhu Yi 已提交
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668
	spin_unlock(&priv->lock);
	return IRQ_NONE;
}

/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
 * sending probe req.  This should be set long enough to hear probe responses
 * from more than one AP.  */
#define IWL_ACTIVE_DWELL_TIME_24    (20)	/* all times in msec */
#define IWL_ACTIVE_DWELL_TIME_52    (10)

/* For faster active scanning, scan will move to the next channel if fewer than
 * PLCP_QUIET_THRESH packets are heard on this channel within
 * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
 * time if it's a quiet channel (nothing responded to our probe, and there's
 * no other traffic).
 * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
#define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)	/* packets */
#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)	/* msec */

/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
 * Must be set longer than active dwell time.
 * For the most reliable scan, set > AP beacon interval (typically 100msec). */
#define IWL_PASSIVE_DWELL_TIME_24   (20)	/* all times in msec */
#define IWL_PASSIVE_DWELL_TIME_52   (10)
#define IWL_PASSIVE_DWELL_BASE      (100)
#define IWL_CHANNEL_TUNE_TIME       5

3669
static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv,
3670
						enum ieee80211_band band)
Z
Zhu Yi 已提交
3671
{
3672
	if (band == IEEE80211_BAND_5GHZ)
Z
Zhu Yi 已提交
3673 3674 3675 3676 3677
		return IWL_ACTIVE_DWELL_TIME_52;
	else
		return IWL_ACTIVE_DWELL_TIME_24;
}

3678
static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv,
3679
					  enum ieee80211_band band)
Z
Zhu Yi 已提交
3680
{
3681 3682
	u16 active = iwl4965_get_active_dwell_time(priv, band);
	u16 passive = (band != IEEE80211_BAND_5GHZ) ?
Z
Zhu Yi 已提交
3683 3684 3685
	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;

3686
	if (iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701
		/* If we're associated, we clamp the maximum passive
		 * dwell time to be 98% of the beacon interval (minus
		 * 2 * channel tune time) */
		passive = priv->beacon_int;
		if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
			passive = IWL_PASSIVE_DWELL_BASE;
		passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
	}

	if (passive <= active)
		passive = active + 1;

	return passive;
}

3702
static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
3703
					 enum ieee80211_band band,
Z
Zhu Yi 已提交
3704
				     u8 is_active, u8 direct_mask,
C
Christoph Hellwig 已提交
3705
				     struct iwl4965_scan_channel *scan_ch)
Z
Zhu Yi 已提交
3706 3707
{
	const struct ieee80211_channel *channels = NULL;
3708
	const struct ieee80211_supported_band *sband;
3709
	const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
3710 3711 3712 3713
	u16 passive_dwell = 0;
	u16 active_dwell = 0;
	int added, i;

3714
	sband = iwl_get_hw_mode(priv, band);
3715
	if (!sband)
Z
Zhu Yi 已提交
3716 3717
		return 0;

3718
	channels = sband->channels;
Z
Zhu Yi 已提交
3719

3720 3721
	active_dwell = iwl4965_get_active_dwell_time(priv, band);
	passive_dwell = iwl4965_get_passive_dwell_time(priv, band);
Z
Zhu Yi 已提交
3722

3723
	for (i = 0, added = 0; i < sband->n_channels; i++) {
3724 3725 3726
		if (channels[i].flags & IEEE80211_CHAN_DISABLED)
			continue;

3727
		scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
Z
Zhu Yi 已提交
3728

3729
		ch_info = iwl_get_channel_info(priv, band,
3730
					 scan_ch->channel);
Z
Zhu Yi 已提交
3731 3732 3733 3734 3735 3736 3737
		if (!is_channel_valid(ch_info)) {
			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
				       scan_ch->channel);
			continue;
		}

		if (!is_active || is_channel_passive(ch_info) ||
3738
		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
Z
Zhu Yi 已提交
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
			scan_ch->type = 0;	/* passive */
		else
			scan_ch->type = 1;	/* active */

		if (scan_ch->type & 1)
			scan_ch->type |= (direct_mask << 1);

		scan_ch->active_dwell = cpu_to_le16(active_dwell);
		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);

3749
		/* Set txpower levels to defaults */
Z
Zhu Yi 已提交
3750 3751 3752 3753
		scan_ch->tpc.dsp_atten = 110;
		/* scan_pwr_info->tpc.dsp_atten; */

		/*scan_pwr_info->tpc.tx_gain; */
3754
		if (band == IEEE80211_BAND_5GHZ)
Z
Zhu Yi 已提交
3755 3756 3757 3758
			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
		else {
			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
3759
			 * power level:
3760
			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
Z
Zhu Yi 已提交
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783
			 */
		}

		IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
			       scan_ch->channel,
			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
			       (scan_ch->type & 1) ?
			       active_dwell : passive_dwell);

		scan_ch++;
		added++;
	}

	IWL_DEBUG_SCAN("total channels to scan %d \n", added);
	return added;
}

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

3784
static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3785
{
3786 3787 3788 3789 3790 3791
	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 已提交
3792 3793
}

3794 3795 3796 3797 3798 3799 3800
static void iwl4965_nic_start(struct iwl_priv *priv)
{
	/* Remove all resets to allow NIC to operate */
	iwl_write32(priv, CSR_RESET, 0);
}


Z
Zhu Yi 已提交
3801
/**
C
Christoph Hellwig 已提交
3802
 * iwl4965_read_ucode - Read uCode images from disk file.
Z
Zhu Yi 已提交
3803 3804 3805
 *
 * Copy into buffers for card to fetch via bus-mastering
 */
3806
static int iwl4965_read_ucode(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3807
{
C
Christoph Hellwig 已提交
3808
	struct iwl4965_ucode *ucode;
3809
	int ret;
Z
Zhu Yi 已提交
3810
	const struct firmware *ucode_raw;
3811
	const char *name = priv->cfg->fw_name;
Z
Zhu Yi 已提交
3812 3813 3814 3815 3816 3817
	u8 *src;
	size_t len;
	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;

	/* Ask kernel firmware_class module to get the boot firmware off disk.
	 * request_firmware() is synchronous, file is in memory on return. */
3818 3819 3820 3821
	ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
	if (ret < 0) {
		IWL_ERROR("%s firmware file req failed: Reason %d\n",
					name, ret);
Z
Zhu Yi 已提交
3822 3823 3824 3825 3826 3827 3828 3829 3830
		goto error;
	}

	IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
		       name, ucode_raw->size);

	/* Make sure that we got at least our header! */
	if (ucode_raw->size < sizeof(*ucode)) {
		IWL_ERROR("File size way too small!\n");
3831
		ret = -EINVAL;
Z
Zhu Yi 已提交
3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863
		goto err_release;
	}

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

	ver = le32_to_cpu(ucode->ver);
	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);

	IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
	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);
3864
		ret = -EINVAL;
Z
Zhu Yi 已提交
3865 3866 3867 3868
		goto err_release;
	}

	/* Verify that uCode images will fit in card's SRAM */
3869
	if (inst_size > priv->hw_params.max_inst_size) {
3870 3871 3872
		IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
			       inst_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3873 3874 3875
		goto err_release;
	}

3876
	if (data_size > priv->hw_params.max_data_size) {
3877 3878 3879
		IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
				data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3880 3881
		goto err_release;
	}
3882
	if (init_size > priv->hw_params.max_inst_size) {
Z
Zhu Yi 已提交
3883
		IWL_DEBUG_INFO
3884 3885 3886
		    ("uCode init instr len %d too large to fit in\n",
		      init_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3887 3888
		goto err_release;
	}
3889
	if (init_data_size > priv->hw_params.max_data_size) {
Z
Zhu Yi 已提交
3890
		IWL_DEBUG_INFO
3891 3892 3893
		    ("uCode init data len %d too large to fit in\n",
		      init_data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3894 3895
		goto err_release;
	}
3896
	if (boot_size > priv->hw_params.max_bsm_size) {
Z
Zhu Yi 已提交
3897
		IWL_DEBUG_INFO
3898 3899 3900
		    ("uCode boot instr len %d too large to fit in\n",
		      boot_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3901 3902 3903 3904 3905 3906 3907 3908 3909
		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;
3910
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
Z
Zhu Yi 已提交
3911 3912

	priv->ucode_data.len = data_size;
3913
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
Z
Zhu Yi 已提交
3914 3915

	priv->ucode_data_backup.len = data_size;
3916
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
Z
Zhu Yi 已提交
3917 3918

	/* Initialization instructions and data */
3919 3920
	if (init_size && init_data_size) {
		priv->ucode_init.len = init_size;
3921
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
3922 3923

		priv->ucode_init_data.len = init_data_size;
3924
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
3925 3926 3927 3928

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

	/* Bootstrap (instructions only, no data) */
3931 3932
	if (boot_size) {
		priv->ucode_boot.len = boot_size;
3933
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
Z
Zhu Yi 已提交
3934

3935 3936 3937
		if (!priv->ucode_boot.v_addr)
			goto err_pci_alloc;
	}
Z
Zhu Yi 已提交
3938 3939 3940 3941 3942 3943

	/* 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;
3944
	IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len);
Z
Zhu Yi 已提交
3945 3946 3947 3948 3949
	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)
C
Christoph Hellwig 已提交
3950
	 * NOTE:  Copy into backup buffer will be done in iwl4965_up()  */
Z
Zhu Yi 已提交
3951 3952
	src = &ucode->data[inst_size];
	len = priv->ucode_data.len;
3953
	IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
Z
Zhu Yi 已提交
3954 3955 3956 3957 3958 3959 3960
	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;
3961 3962
		IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n",
				len);
Z
Zhu Yi 已提交
3963 3964 3965 3966 3967 3968 3969
		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;
3970 3971
		IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n",
			       len);
Z
Zhu Yi 已提交
3972 3973 3974 3975 3976 3977
		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;
3978
	IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len);
Z
Zhu Yi 已提交
3979 3980 3981 3982 3983 3984 3985 3986
	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:
	IWL_ERROR("failed to allocate pci memory\n");
3987
	ret = -ENOMEM;
C
Christoph Hellwig 已提交
3988
	iwl4965_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
3989 3990 3991 3992 3993

 err_release:
	release_firmware(ucode_raw);

 error:
3994
	return ret;
Z
Zhu Yi 已提交
3995 3996 3997
}

/**
C
Christoph Hellwig 已提交
3998
 * iwl4965_alive_start - called after REPLY_ALIVE notification received
Z
Zhu Yi 已提交
3999
 *                   from protocol/runtime uCode (initialization uCode's
C
Christoph Hellwig 已提交
4000
 *                   Alive gets handled by iwl4965_init_alive_start()).
Z
Zhu Yi 已提交
4001
 */
4002
static void iwl4965_alive_start(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4003
{
4004
	int ret = 0;
Z
Zhu Yi 已提交
4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017

	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.  */
4018
	if (iwl_verify_ucode(priv)) {
Z
Zhu Yi 已提交
4019 4020 4021 4022 4023 4024
		/* 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;
	}

4025
	iwlcore_clear_stations_table(priv);
Z
Zhu Yi 已提交
4026

4027 4028
	ret = priv->cfg->ops->lib->alive_notify(priv);
	if (ret) {
Z
Zhu Yi 已提交
4029
		IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
4030
			    ret);
Z
Zhu Yi 已提交
4031 4032 4033
		goto restart;
	}

4034
	/* After the ALIVE response, we can send host commands to 4965 uCode */
Z
Zhu Yi 已提交
4035 4036 4037 4038 4039
	set_bit(STATUS_ALIVE, &priv->status);

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

4040
	if (iwl_is_rfkill(priv))
Z
Zhu Yi 已提交
4041 4042
		return;

4043
	ieee80211_start_queues(priv->hw);
Z
Zhu Yi 已提交
4044 4045 4046 4047

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

4048
	if (iwl_is_associated(priv)) {
G
Gregory Greenman 已提交
4049 4050
		struct iwl_rxon_cmd *active_rxon =
				(struct iwl_rxon_cmd *)&priv->active_rxon;
Z
Zhu Yi 已提交
4051 4052 4053 4054 4055 4056

		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 */
C
Christoph Hellwig 已提交
4057
		iwl4965_connection_init_rx_config(priv);
Z
Zhu Yi 已提交
4058 4059 4060
		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
	}

4061
	/* Configure Bluetooth device coexistence support */
C
Christoph Hellwig 已提交
4062
	iwl4965_send_bt_config(priv);
Z
Zhu Yi 已提交
4063 4064

	/* Configure the adapter for unassociated operation */
C
Christoph Hellwig 已提交
4065
	iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
4066 4067 4068 4069 4070

	/* At this point, the NIC is initialized and operational */
	priv->notif_missed_beacons = 0;

	iwl4965_rf_kill_ct_config(priv);
4071

4072 4073
	iwl_leds_register(priv);

Z
Zhu Yi 已提交
4074
	IWL_DEBUG_INFO("ALIVE processing complete.\n");
4075
	set_bit(STATUS_READY, &priv->status);
4076
	wake_up_interruptible(&priv->wait_command_queue);
Z
Zhu Yi 已提交
4077 4078

	if (priv->error_recovering)
C
Christoph Hellwig 已提交
4079
		iwl4965_error_recovery(priv);
Z
Zhu Yi 已提交
4080

4081
	iwlcore_low_level_notify(priv, IWLCORE_START_EVT);
4082
	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
Z
Zhu Yi 已提交
4083 4084 4085 4086 4087 4088
	return;

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

4089
static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
Z
Zhu Yi 已提交
4090

4091
static void __iwl4965_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103
{
	unsigned long flags;
	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
	struct ieee80211_conf *conf = NULL;

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

	conf = ieee80211_get_hw_conf(priv->hw);

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

M
Mohamed Abbas 已提交
4104 4105
	iwl_leds_unregister(priv);

4106 4107
	iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT);

4108
	iwlcore_clear_stations_table(priv);
Z
Zhu Yi 已提交
4109 4110 4111 4112 4113 4114 4115 4116 4117 4118

	/* 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 */
4119
	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Z
Zhu Yi 已提交
4120 4121

	/* tell the device to stop sending interrupts */
4122
	spin_lock_irqsave(&priv->lock, flags);
C
Christoph Hellwig 已提交
4123
	iwl4965_disable_interrupts(priv);
4124 4125
	spin_unlock_irqrestore(&priv->lock, flags);
	iwl_synchronize_irq(priv);
Z
Zhu Yi 已提交
4126 4127 4128 4129

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

C
Christoph Hellwig 已提交
4130
	/* If we have not previously called iwl4965_init() then
Z
Zhu Yi 已提交
4131
	 * clear all bits but the RF Kill and SUSPEND bits and return */
4132
	if (!iwl_is_init(priv)) {
Z
Zhu Yi 已提交
4133 4134 4135 4136
		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 |
4137 4138
			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
					STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149
			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
					STATUS_IN_SUSPEND;
		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 |
4150 4151
			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
				STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
4152 4153 4154 4155 4156 4157
			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
				STATUS_IN_SUSPEND |
			test_bit(STATUS_FW_ERROR, &priv->status) <<
				STATUS_FW_ERROR;

	spin_lock_irqsave(&priv->lock, flags);
4158
	iwl_clear_bit(priv, CSR_GP_CNTRL,
4159
			 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Z
Zhu Yi 已提交
4160 4161
	spin_unlock_irqrestore(&priv->lock, flags);

C
Christoph Hellwig 已提交
4162 4163
	iwl4965_hw_txq_ctx_stop(priv);
	iwl4965_hw_rxq_stop(priv);
Z
Zhu Yi 已提交
4164 4165

	spin_lock_irqsave(&priv->lock, flags);
4166 4167
	if (!iwl_grab_nic_access(priv)) {
		iwl_write_prph(priv, APMG_CLK_DIS_REG,
Z
Zhu Yi 已提交
4168
					 APMG_CLK_VAL_DMA_CLK_RQT);
4169
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
4170 4171 4172 4173 4174
	}
	spin_unlock_irqrestore(&priv->lock, flags);

	udelay(5);

C
Christoph Hellwig 已提交
4175
	iwl4965_hw_nic_stop_master(priv);
4176
	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
C
Christoph Hellwig 已提交
4177
	iwl4965_hw_nic_reset(priv);
R
Ron Rindjunsky 已提交
4178
	priv->cfg->ops->lib->free_shared_mem(priv);
Z
Zhu Yi 已提交
4179 4180

 exit:
C
Christoph Hellwig 已提交
4181
	memset(&priv->card_alive, 0, sizeof(struct iwl4965_alive_resp));
Z
Zhu Yi 已提交
4182 4183 4184 4185 4186 4187

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

	/* clear out any free frames */
4188
	iwl_clear_free_frames(priv);
Z
Zhu Yi 已提交
4189 4190
}

4191
static void iwl4965_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4192 4193
{
	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
4194
	__iwl4965_down(priv);
Z
Zhu Yi 已提交
4195
	mutex_unlock(&priv->mutex);
4196

C
Christoph Hellwig 已提交
4197
	iwl4965_cancel_deferred_work(priv);
Z
Zhu Yi 已提交
4198 4199 4200 4201
}

#define MAX_HW_RESTARTS 5

4202
static int __iwl4965_up(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4203
{
4204 4205
	int i;
	int ret;
Z
Zhu Yi 已提交
4206 4207 4208 4209 4210 4211 4212 4213 4214

	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
		IWL_WARNING("Exit pending; will not bring the NIC up\n");
		return -EIO;
	}

	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
		IWL_WARNING("Radio disabled by SW RF kill (module "
			    "parameter)\n");
4215
		iwl_rfkill_set_hw_state(priv);
4216 4217 4218
		return -ENODEV;
	}

4219 4220 4221 4222 4223
	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
		IWL_ERROR("ucode not available for device bringup\n");
		return -EIO;
	}

4224
	/* If platform's RF_KILL switch is NOT set to KILL */
4225
	if (iwl_read32(priv, CSR_GP_CNTRL) &
4226 4227 4228 4229 4230
				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
		clear_bit(STATUS_RF_KILL_HW, &priv->status);
	else {
		set_bit(STATUS_RF_KILL_HW, &priv->status);
		if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
4231
			iwl_rfkill_set_hw_state(priv);
4232 4233 4234
			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
			return -ENODEV;
		}
Z
Zhu Yi 已提交
4235 4236
	}

4237
	iwl_rfkill_set_hw_state(priv);
4238
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
Z
Zhu Yi 已提交
4239

R
Ron Rindjunsky 已提交
4240 4241 4242 4243 4244 4245
	ret = priv->cfg->ops->lib->alloc_shared_mem(priv);
	if (ret) {
		IWL_ERROR("Unable to allocate shared memory\n");
		return ret;
	}

4246
	ret = iwl_hw_nic_init(priv);
4247 4248 4249
	if (ret) {
		IWL_ERROR("Unable to init nic\n");
		return ret;
Z
Zhu Yi 已提交
4250 4251 4252
	}

	/* make sure rfkill handshake bits are cleared */
4253 4254
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
Z
Zhu Yi 已提交
4255 4256 4257
		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

	/* clear (again), then enable host interrupts */
4258
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
C
Christoph Hellwig 已提交
4259
	iwl4965_enable_interrupts(priv);
Z
Zhu Yi 已提交
4260 4261

	/* really make sure rfkill handshake bits are cleared */
4262 4263
	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 已提交
4264 4265 4266 4267 4268

	/* 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,
4269
	       priv->ucode_data.len);
Z
Zhu Yi 已提交
4270

4271 4272
	/* We return success when we resume from suspend and rf_kill is on. */
	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
Z
Zhu Yi 已提交
4273 4274 4275 4276
		return 0;

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

4277
		iwlcore_clear_stations_table(priv);
Z
Zhu Yi 已提交
4278 4279 4280 4281

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

4284 4285
		if (ret) {
			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
Z
Zhu Yi 已提交
4286 4287 4288 4289
			continue;
		}

		/* start card; "initialize" will load runtime ucode */
4290
		iwl4965_nic_start(priv);
Z
Zhu Yi 已提交
4291 4292 4293 4294 4295 4296 4297

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

		return 0;
	}

	set_bit(STATUS_EXIT_PENDING, &priv->status);
C
Christoph Hellwig 已提交
4298
	__iwl4965_down(priv);
Z
Zhu Yi 已提交
4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312

	/* tried to restart and config the device for as long as our
	 * patience could withstand */
	IWL_ERROR("Unable to initialize device after %d attempts.\n", i);
	return -EIO;
}


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

C
Christoph Hellwig 已提交
4313
static void iwl4965_bg_init_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
4314
{
4315 4316
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, init_alive_start.work);
Z
Zhu Yi 已提交
4317 4318 4319 4320 4321

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

	mutex_lock(&priv->mutex);
4322
	priv->cfg->ops->lib->init_alive_start(priv);
Z
Zhu Yi 已提交
4323 4324 4325
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
4326
static void iwl4965_bg_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
4327
{
4328 4329
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, alive_start.work);
Z
Zhu Yi 已提交
4330 4331 4332 4333 4334

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

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
4335
	iwl4965_alive_start(priv);
Z
Zhu Yi 已提交
4336 4337 4338
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
4339
static void iwl4965_bg_rf_kill(struct work_struct *work)
Z
Zhu Yi 已提交
4340
{
4341
	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
Z
Zhu Yi 已提交
4342 4343 4344 4345 4346 4347 4348 4349

	wake_up_interruptible(&priv->wait_command_queue);

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

	mutex_lock(&priv->mutex);

4350
	if (!iwl_is_rfkill(priv)) {
4351
		IWL_DEBUG(IWL_DL_RF_KILL,
Z
Zhu Yi 已提交
4352 4353 4354 4355 4356
			  "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 {
4357 4358 4359
		/* make sure mac80211 stop sending Tx frame */
		if (priv->mac80211_registered)
			ieee80211_stop_queues(priv->hw);
Z
Zhu Yi 已提交
4360 4361 4362 4363 4364 4365 4366 4367 4368

		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
			IWL_WARNING("Radio Frequency Kill Switch is On:\n"
				    "Kill switch must be turned off for "
				    "wireless networking to work.\n");
	}
4369 4370
	iwl_rfkill_set_hw_state(priv);

Z
Zhu Yi 已提交
4371 4372 4373
	mutex_unlock(&priv->mutex);
}

4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391
static void iwl4965_bg_set_monitor(struct work_struct *work)
{
	struct iwl_priv *priv = container_of(work,
				struct iwl_priv, set_monitor);

	IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");

	mutex_lock(&priv->mutex);

	if (!iwl_is_ready(priv))
		IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
	else
		if (iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
			IWL_ERROR("iwl4965_set_mode() failed\n");

	mutex_unlock(&priv->mutex);
}

Z
Zhu Yi 已提交
4392 4393
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)

C
Christoph Hellwig 已提交
4394
static void iwl4965_bg_scan_check(struct work_struct *data)
Z
Zhu Yi 已提交
4395
{
4396 4397
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, scan_check.work);
Z
Zhu Yi 已提交
4398 4399 4400 4401 4402 4403 4404

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

	mutex_lock(&priv->mutex);
	if (test_bit(STATUS_SCANNING, &priv->status) ||
	    test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
4405 4406 4407
		IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting "
			"adapter (%dms)\n",
			jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
4408

Z
Zhu Yi 已提交
4409
		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
C
Christoph Hellwig 已提交
4410
			iwl4965_send_scan_abort(priv);
Z
Zhu Yi 已提交
4411 4412 4413 4414
	}
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
4415
static void iwl4965_bg_request_scan(struct work_struct *data)
Z
Zhu Yi 已提交
4416
{
4417 4418
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, request_scan);
4419
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
4420
		.id = REPLY_SCAN_CMD,
C
Christoph Hellwig 已提交
4421
		.len = sizeof(struct iwl4965_scan_cmd),
Z
Zhu Yi 已提交
4422 4423
		.meta.flags = CMD_SIZE_HUGE,
	};
C
Christoph Hellwig 已提交
4424
	struct iwl4965_scan_cmd *scan;
Z
Zhu Yi 已提交
4425
	struct ieee80211_conf *conf = NULL;
4426
	u16 cmd_len;
4427
	enum ieee80211_band band;
4428
	u8 direct_mask;
4429
	int ret = 0;
Z
Zhu Yi 已提交
4430 4431 4432 4433 4434

	conf = ieee80211_get_hw_conf(priv->hw);

	mutex_lock(&priv->mutex);

4435
	if (!iwl_is_ready(priv)) {
Z
Zhu Yi 已提交
4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449
		IWL_WARNING("request scan called when driver not ready.\n");
		goto done;
	}

	/* Make sure the scan wasn't cancelled before this queued work
	 * was given the chance to run... */
	if (!test_bit(STATUS_SCANNING, &priv->status))
		goto done;

	/* This should never be called or scheduled if there is currently
	 * a scan active in the hardware. */
	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
		IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
			       "Ignoring second request.\n");
4450
		ret = -EIO;
Z
Zhu Yi 已提交
4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463
		goto done;
	}

	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
		IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n");
		goto done;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_HC("Scan request while abort pending.  Queuing.\n");
		goto done;
	}

4464
	if (iwl_is_rfkill(priv)) {
Z
Zhu Yi 已提交
4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479
		IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
		goto done;
	}

	if (!test_bit(STATUS_READY, &priv->status)) {
		IWL_DEBUG_HC("Scan request while uninitialized.  Queuing.\n");
		goto done;
	}

	if (!priv->scan_bands) {
		IWL_DEBUG_HC("Aborting scan due to no requested bands\n");
		goto done;
	}

	if (!priv->scan) {
C
Christoph Hellwig 已提交
4480
		priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) +
Z
Zhu Yi 已提交
4481 4482
				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
		if (!priv->scan) {
4483
			ret = -ENOMEM;
Z
Zhu Yi 已提交
4484 4485 4486 4487
			goto done;
		}
	}
	scan = priv->scan;
C
Christoph Hellwig 已提交
4488
	memset(scan, 0, sizeof(struct iwl4965_scan_cmd) + IWL_MAX_SCAN_SIZE);
Z
Zhu Yi 已提交
4489 4490 4491 4492

	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;

4493
	if (iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506
		u16 interval = 0;
		u32 extra;
		u32 suspend_time = 100;
		u32 scan_suspend_time = 100;
		unsigned long flags;

		IWL_DEBUG_INFO("Scanning while associated...\n");

		spin_lock_irqsave(&priv->lock, flags);
		interval = priv->beacon_int;
		spin_unlock_irqrestore(&priv->lock, flags);

		scan->suspend_time = 0;
4507
		scan->max_out_time = cpu_to_le32(200 * 1024);
Z
Zhu Yi 已提交
4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522
		if (!interval)
			interval = suspend_time;

		extra = (suspend_time / interval) << 22;
		scan_suspend_time = (extra |
		    ((suspend_time % interval) * 1024));
		scan->suspend_time = cpu_to_le32(scan_suspend_time);
		IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n",
			       scan_suspend_time, interval);
	}

	/* We should add the ability for user to lock to PASSIVE ONLY */
	if (priv->one_direct_scan) {
		IWL_DEBUG_SCAN
		    ("Kicking off one direct scan for '%s'\n",
C
Christoph Hellwig 已提交
4523
		     iwl4965_escape_essid(priv->direct_ssid,
Z
Zhu Yi 已提交
4524 4525 4526 4527 4528 4529
				      priv->direct_ssid_len));
		scan->direct_scan[0].id = WLAN_EID_SSID;
		scan->direct_scan[0].len = priv->direct_ssid_len;
		memcpy(scan->direct_scan[0].ssid,
		       priv->direct_ssid, priv->direct_ssid_len);
		direct_mask = 1;
4530
	} else if (!iwl_is_associated(priv) && priv->essid_len) {
4531 4532 4533
		IWL_DEBUG_SCAN
		  ("Kicking off one direct scan for '%s' when not associated\n",
		   iwl4965_escape_essid(priv->essid, priv->essid_len));
Z
Zhu Yi 已提交
4534 4535 4536 4537
		scan->direct_scan[0].id = WLAN_EID_SSID;
		scan->direct_scan[0].len = priv->essid_len;
		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
		direct_mask = 1;
4538
	} else {
4539
		IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
Z
Zhu Yi 已提交
4540
		direct_mask = 0;
4541
	}
Z
Zhu Yi 已提交
4542 4543

	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
T
Tomas Winkler 已提交
4544
	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
4545 4546 4547 4548 4549 4550 4551
	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;


	switch (priv->scan_bands) {
	case 2:
		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
		scan->tx_cmd.rate_n_flags =
C
Christoph Hellwig 已提交
4552
				iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
Z
Zhu Yi 已提交
4553 4554 4555
				RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);

		scan->good_CRC_th = 0;
4556
		band = IEEE80211_BAND_2GHZ;
Z
Zhu Yi 已提交
4557 4558 4559 4560
		break;

	case 1:
		scan->tx_cmd.rate_n_flags =
C
Christoph Hellwig 已提交
4561
				iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
Z
Zhu Yi 已提交
4562 4563
				RATE_MCS_ANT_B_MSK);
		scan->good_CRC_th = IWL_GOOD_CRC_TH;
4564
		band = IEEE80211_BAND_5GHZ;
Z
Zhu Yi 已提交
4565 4566 4567 4568 4569 4570 4571
		break;

	default:
		IWL_WARNING("Invalid scan band count\n");
		goto done;
	}

4572 4573 4574 4575 4576 4577 4578
	/* We don't build a direct scan probe request; the uCode will do
	 * that based on the direct_mask added to each channel entry */
	cmd_len = iwl4965_fill_probe_req(priv, band,
					(struct ieee80211_mgmt *)scan->data,
					IWL_MAX_SCAN_SIZE - sizeof(*scan), 0);

	scan->tx_cmd.len = cpu_to_le16(cmd_len);
Z
Zhu Yi 已提交
4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591
	/* select Rx chains */

	/* Force use of chains B and C (0x6) for scan Rx.
	 * Avoid A (0x1) because of its off-channel reception on A-band.
	 * MIMO is not used here, but value is required to make uCode happy. */
	scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
			cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
			(0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
			(0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));

	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
		scan->filter_flags = RXON_FILTER_PROMISC_MSK;

4592
	if (direct_mask)
4593 4594 4595 4596 4597
		scan->channel_count =
			iwl4965_get_channels_for_scan(
				priv, band, 1, /* active */
				direct_mask,
				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
4598
	else
4599 4600 4601 4602 4603
		scan->channel_count =
			iwl4965_get_channels_for_scan(
				priv, band, 0, /* passive */
				direct_mask,
				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
Z
Zhu Yi 已提交
4604

M
Mohamed Abbas 已提交
4605 4606
	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
			       RXON_FILTER_BCON_AWARE_MSK);
Z
Zhu Yi 已提交
4607
	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
C
Christoph Hellwig 已提交
4608
	    scan->channel_count * sizeof(struct iwl4965_scan_channel);
Z
Zhu Yi 已提交
4609 4610 4611 4612
	cmd.data = scan;
	scan->len = cpu_to_le16(cmd.len);

	set_bit(STATUS_SCAN_HW, &priv->status);
4613 4614
	ret = iwl_send_cmd_sync(priv, &cmd);
	if (ret)
Z
Zhu Yi 已提交
4615 4616 4617 4618 4619 4620 4621 4622 4623
		goto done;

	queue_delayed_work(priv->workqueue, &priv->scan_check,
			   IWL_SCAN_CHECK_WATCHDOG);

	mutex_unlock(&priv->mutex);
	return;

 done:
4624
	/* inform mac80211 scan aborted */
Z
Zhu Yi 已提交
4625 4626 4627 4628
	queue_work(priv->workqueue, &priv->scan_completed);
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
4629
static void iwl4965_bg_up(struct work_struct *data)
Z
Zhu Yi 已提交
4630
{
4631
	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
Z
Zhu Yi 已提交
4632 4633 4634 4635 4636

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

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
4637
	__iwl4965_up(priv);
Z
Zhu Yi 已提交
4638 4639 4640
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
4641
static void iwl4965_bg_restart(struct work_struct *data)
Z
Zhu Yi 已提交
4642
{
4643
	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
Z
Zhu Yi 已提交
4644 4645 4646 4647

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

C
Christoph Hellwig 已提交
4648
	iwl4965_down(priv);
Z
Zhu Yi 已提交
4649 4650 4651
	queue_work(priv->workqueue, &priv->up);
}

C
Christoph Hellwig 已提交
4652
static void iwl4965_bg_rx_replenish(struct work_struct *data)
Z
Zhu Yi 已提交
4653
{
4654 4655
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, rx_replenish);
Z
Zhu Yi 已提交
4656 4657 4658 4659 4660

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

	mutex_lock(&priv->mutex);
4661
	iwl_rx_replenish(priv);
Z
Zhu Yi 已提交
4662 4663 4664
	mutex_unlock(&priv->mutex);
}

4665 4666
#define IWL_DELAY_NEXT_SCAN (HZ*2)

4667
static void iwl4965_post_associate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4668 4669
{
	struct ieee80211_conf *conf = NULL;
4670
	int ret = 0;
4671
	DECLARE_MAC_BUF(mac);
Z
Zhu Yi 已提交
4672 4673 4674 4675 4676 4677

	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
		IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
		return;
	}

4678 4679 4680
	IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
			priv->assoc_id,
			print_mac(mac, priv->active_rxon.bssid_addr));
Z
Zhu Yi 已提交
4681 4682 4683 4684 4685 4686


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


4687
	if (!priv->vif || !priv->is_open)
M
Mohamed Abbas 已提交
4688
		return;
4689

C
Christoph Hellwig 已提交
4690
	iwl4965_scan_cancel_timeout(priv, 200);
4691

Z
Zhu Yi 已提交
4692 4693 4694
	conf = ieee80211_get_hw_conf(priv->hw);

	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
4695
	iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
4696

C
Christoph Hellwig 已提交
4697 4698
	memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
	iwl4965_setup_rxon_timing(priv);
4699
	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
Z
Zhu Yi 已提交
4700
			      sizeof(priv->rxon_timing), &priv->rxon_timing);
4701
	if (ret)
Z
Zhu Yi 已提交
4702 4703 4704 4705 4706
		IWL_WARNING("REPLY_RXON_TIMING failed - "
			    "Attempting to continue.\n");

	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;

4707
#ifdef CONFIG_IWL4965_HT
4708
	if (priv->current_ht_config.is_ht)
4709
		iwl_set_rxon_ht(priv, &priv->current_ht_config);
4710
#endif /* CONFIG_IWL4965_HT*/
R
Ron Rindjunsky 已提交
4711
	iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732
	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;

		if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;

	}

C
Christoph Hellwig 已提交
4733
	iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
4734 4735 4736

	switch (priv->iw_mode) {
	case IEEE80211_IF_TYPE_STA:
C
Christoph Hellwig 已提交
4737
		iwl4965_rate_scale_init(priv->hw, IWL_AP_ID);
Z
Zhu Yi 已提交
4738 4739 4740 4741 4742
		break;

	case IEEE80211_IF_TYPE_IBSS:

		/* clear out the station table */
4743
		iwlcore_clear_stations_table(priv);
Z
Zhu Yi 已提交
4744

4745 4746
		iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
		iwl_rxon_add_station(priv, priv->bssid, 0);
C
Christoph Hellwig 已提交
4747 4748
		iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
		iwl4965_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
4749 4750 4751 4752 4753 4754 4755 4756 4757

		break;

	default:
		IWL_ERROR("%s Should not be called in %d mode\n",
				__FUNCTION__, priv->iw_mode);
		break;
	}

C
Christoph Hellwig 已提交
4758
	iwl4965_sequence_reset(priv);
Z
Zhu Yi 已提交
4759 4760

	/* Enable Rx differential gain and sensitivity calibrations */
4761
	iwl_chain_noise_reset(priv);
Z
Zhu Yi 已提交
4762 4763 4764 4765 4766
	priv->start_calib = 1;

	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
		priv->assoc_station_added = 1;

C
Christoph Hellwig 已提交
4767
	iwl4965_activate_qos(priv, 0);
4768

M
Mohamed Abbas 已提交
4769
	iwl_power_update_mode(priv, 0);
4770 4771
	/* we have just associated, don't start scan too early */
	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
4772 4773 4774 4775 4776 4777 4778 4779 4780 4781
}


static void iwl4965_bg_post_associate(struct work_struct *data)
{
	struct iwl_priv *priv = container_of(data, struct iwl_priv,
					     post_associate.work);

	mutex_lock(&priv->mutex);
	iwl4965_post_associate(priv);
Z
Zhu Yi 已提交
4782
	mutex_unlock(&priv->mutex);
4783

Z
Zhu Yi 已提交
4784 4785
}

C
Christoph Hellwig 已提交
4786
static void iwl4965_bg_abort_scan(struct work_struct *work)
Z
Zhu Yi 已提交
4787
{
4788
	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
Z
Zhu Yi 已提交
4789

4790
	if (!iwl_is_ready(priv))
Z
Zhu Yi 已提交
4791 4792 4793 4794 4795
		return;

	mutex_lock(&priv->mutex);

	set_bit(STATUS_SCAN_ABORTING, &priv->status);
C
Christoph Hellwig 已提交
4796
	iwl4965_send_scan_abort(priv);
Z
Zhu Yi 已提交
4797 4798 4799 4800

	mutex_unlock(&priv->mutex);
}

4801 4802
static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);

C
Christoph Hellwig 已提交
4803
static void iwl4965_bg_scan_completed(struct work_struct *work)
Z
Zhu Yi 已提交
4804
{
4805 4806
	struct iwl_priv *priv =
	    container_of(work, struct iwl_priv, scan_completed);
Z
Zhu Yi 已提交
4807

4808
	IWL_DEBUG(IWL_DL_SCAN, "SCAN complete scan\n");
Z
Zhu Yi 已提交
4809 4810 4811 4812

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

4813 4814
	if (test_bit(STATUS_CONF_PENDING, &priv->status))
		iwl4965_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
4815

Z
Zhu Yi 已提交
4816 4817 4818 4819 4820
	ieee80211_scan_completed(priv->hw);

	/* Since setting the TXPOWER may have been deferred while
	 * performing the scan, fire one off */
	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
4821
	iwl4965_hw_reg_send_txpower(priv);
Z
Zhu Yi 已提交
4822 4823 4824 4825 4826 4827 4828 4829 4830
	mutex_unlock(&priv->mutex);
}

/*****************************************************************************
 *
 * mac80211 entry point functions
 *
 *****************************************************************************/

4831 4832
#define UCODE_READY_TIMEOUT	(2 * HZ)

C
Christoph Hellwig 已提交
4833
static int iwl4965_mac_start(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
4834
{
4835
	struct iwl_priv *priv = hw->priv;
4836
	int ret;
Z
Zhu Yi 已提交
4837 4838 4839

	IWL_DEBUG_MAC80211("enter\n");

4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853
	if (pci_enable_device(priv->pci_dev)) {
		IWL_ERROR("Fail to pci_enable_device\n");
		return -ENODEV;
	}
	pci_restore_state(priv->pci_dev);
	pci_enable_msi(priv->pci_dev);

	ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
			  DRV_NAME, priv);
	if (ret) {
		IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
		goto out_disable_msi;
	}

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

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

4861 4862 4863 4864 4865 4866 4867 4868
	if (!priv->ucode_code.len) {
		ret = iwl4965_read_ucode(priv);
		if (ret) {
			IWL_ERROR("Could not read microcode: %d\n", ret);
			mutex_unlock(&priv->mutex);
			goto out_release_irq;
		}
	}
Z
Zhu Yi 已提交
4869

4870
	ret = __iwl4965_up(priv);
4871

Z
Zhu Yi 已提交
4872
	mutex_unlock(&priv->mutex);
4873

4874 4875 4876 4877 4878 4879 4880 4881
	if (ret)
		goto out_release_irq;

	IWL_DEBUG_INFO("Start UP work done.\n");

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

4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895
	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
	 * mac80211 will not be run successfully. */
	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)) {
			IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
				  jiffies_to_msecs(UCODE_READY_TIMEOUT));
			ret = -ETIMEDOUT;
			goto out_release_irq;
		}
	}

4896
	priv->is_open = 1;
Z
Zhu Yi 已提交
4897 4898
	IWL_DEBUG_MAC80211("leave\n");
	return 0;
4899 4900 4901 4902 4903

out_release_irq:
	free_irq(priv->pci_dev->irq, priv);
out_disable_msi:
	pci_disable_msi(priv->pci_dev);
4904 4905 4906
	pci_disable_device(priv->pci_dev);
	priv->is_open = 0;
	IWL_DEBUG_MAC80211("leave - failed\n");
4907
	return ret;
Z
Zhu Yi 已提交
4908 4909
}

C
Christoph Hellwig 已提交
4910
static void iwl4965_mac_stop(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
4911
{
4912
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4913 4914

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

4916 4917 4918 4919 4920
	if (!priv->is_open) {
		IWL_DEBUG_MAC80211("leave - skip\n");
		return;
	}

Z
Zhu Yi 已提交
4921
	priv->is_open = 0;
4922

4923
	if (iwl_is_ready_rf(priv)) {
4924 4925 4926
		/* stop mac, cancel any scan request and clear
		 * RXON_FILTER_ASSOC_MSK BIT
		 */
4927 4928 4929
		mutex_lock(&priv->mutex);
		iwl4965_scan_cancel_timeout(priv, 100);
		cancel_delayed_work(&priv->post_associate);
4930 4931 4932
		mutex_unlock(&priv->mutex);
	}

4933 4934 4935 4936 4937 4938 4939
	iwl4965_down(priv);

	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 已提交
4940

Z
Zhu Yi 已提交
4941 4942 4943
	IWL_DEBUG_MAC80211("leave\n");
}

C
Christoph Hellwig 已提交
4944
static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
Z
Zhu Yi 已提交
4945 4946
		      struct ieee80211_tx_control *ctl)
{
4947
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4948 4949 4950 4951 4952 4953 4954 4955 4956

	IWL_DEBUG_MAC80211("enter\n");

	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
		IWL_DEBUG_MAC80211("leave - monitor\n");
		return -1;
	}

	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
4957
		     ctl->tx_rate->bitrate);
Z
Zhu Yi 已提交
4958

C
Christoph Hellwig 已提交
4959
	if (iwl4965_tx_skb(priv, skb, ctl))
Z
Zhu Yi 已提交
4960 4961 4962 4963 4964 4965
		dev_kfree_skb_any(skb);

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

C
Christoph Hellwig 已提交
4966
static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
4967 4968
				 struct ieee80211_if_init_conf *conf)
{
4969
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4970
	unsigned long flags;
4971
	DECLARE_MAC_BUF(mac);
Z
Zhu Yi 已提交
4972

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

4975 4976
	if (priv->vif) {
		IWL_DEBUG_MAC80211("leave - vif != NULL\n");
4977
		return -EOPNOTSUPP;
Z
Zhu Yi 已提交
4978 4979 4980
	}

	spin_lock_irqsave(&priv->lock, flags);
4981
	priv->vif = conf->vif;
Z
Zhu Yi 已提交
4982 4983 4984 4985

	spin_unlock_irqrestore(&priv->lock, flags);

	mutex_lock(&priv->mutex);
4986 4987 4988 4989 4990

	if (conf->mac_addr) {
		IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr));
		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
	}
Z
Zhu Yi 已提交
4991

4992
	if (iwl_is_ready(priv))
4993 4994
		iwl4965_set_mode(priv, conf->type);

Z
Zhu Yi 已提交
4995 4996
	mutex_unlock(&priv->mutex);

4997
	IWL_DEBUG_MAC80211("leave\n");
Z
Zhu Yi 已提交
4998 4999 5000 5001
	return 0;
}

/**
C
Christoph Hellwig 已提交
5002
 * iwl4965_mac_config - mac80211 config callback
Z
Zhu Yi 已提交
5003 5004 5005 5006 5007
 *
 * 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.
 */
C
Christoph Hellwig 已提交
5008
static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
Z
Zhu Yi 已提交
5009
{
5010
	struct iwl_priv *priv = hw->priv;
5011
	const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
5012
	unsigned long flags;
5013
	int ret = 0;
Z
Zhu Yi 已提交
5014 5015

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

Z
Zhu Yi 已提交
5018 5019
	priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);

5020
	if (!iwl_is_ready(priv)) {
Z
Zhu Yi 已提交
5021
		IWL_DEBUG_MAC80211("leave - not ready\n");
5022 5023
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
5024 5025
	}

5026
	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
Z
Zhu Yi 已提交
5027
		     test_bit(STATUS_SCANNING, &priv->status))) {
5028 5029
		IWL_DEBUG_MAC80211("leave - scanning\n");
		set_bit(STATUS_CONF_PENDING, &priv->status);
Z
Zhu Yi 已提交
5030
		mutex_unlock(&priv->mutex);
5031
		return 0;
Z
Zhu Yi 已提交
5032 5033 5034 5035
	}

	spin_lock_irqsave(&priv->lock, flags);

5036
	ch_info = iwl_get_channel_info(priv, conf->channel->band,
5037
			ieee80211_frequency_to_channel(conf->channel->center_freq));
Z
Zhu Yi 已提交
5038 5039 5040
	if (!is_channel_valid(ch_info)) {
		IWL_DEBUG_MAC80211("leave - invalid channel\n");
		spin_unlock_irqrestore(&priv->lock, flags);
5041 5042
		ret = -EINVAL;
		goto out;
Z
Zhu Yi 已提交
5043 5044
	}

5045
#ifdef CONFIG_IWL4965_HT
5046
	/* if we are switching from ht to 2.4 clear flags
Z
Zhu Yi 已提交
5047 5048
	 * from any ht related info since 2.4 does not
	 * support ht */
5049
	if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel->hw_value)
Z
Zhu Yi 已提交
5050 5051 5052 5053 5054
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
	    && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
#endif
	)
		priv->staging_rxon.flags = 0;
5055
#endif /* CONFIG_IWL4965_HT */
Z
Zhu Yi 已提交
5056

R
Ron Rindjunsky 已提交
5057
	iwl_set_rxon_channel(priv, conf->channel->band,
5058
		ieee80211_frequency_to_channel(conf->channel->center_freq));
Z
Zhu Yi 已提交
5059

5060
	iwl4965_set_flags_for_phymode(priv, conf->channel->band);
Z
Zhu Yi 已提交
5061 5062

	/* The list of supported rates and rate mask can be different
5063
	 * for each band; since the band may have changed, reset
Z
Zhu Yi 已提交
5064
	 * the rate mask to what mac80211 lists */
C
Christoph Hellwig 已提交
5065
	iwl4965_set_rate(priv);
Z
Zhu Yi 已提交
5066 5067 5068 5069 5070

	spin_unlock_irqrestore(&priv->lock, flags);

#ifdef IEEE80211_CONF_CHANNEL_SWITCH
	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
C
Christoph Hellwig 已提交
5071
		iwl4965_hw_channel_switch(priv, conf->channel);
5072
		goto out;
Z
Zhu Yi 已提交
5073 5074 5075
	}
#endif

5076 5077
	if (priv->cfg->ops->lib->radio_kill_sw)
		priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled);
Z
Zhu Yi 已提交
5078 5079 5080

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

5084
	if (iwl_is_rfkill(priv)) {
Z
Zhu Yi 已提交
5085
		IWL_DEBUG_MAC80211("leave - RF kill\n");
5086 5087
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
5088 5089
	}

C
Christoph Hellwig 已提交
5090
	iwl4965_set_rate(priv);
Z
Zhu Yi 已提交
5091 5092 5093

	if (memcmp(&priv->active_rxon,
		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
C
Christoph Hellwig 已提交
5094
		iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5095 5096 5097 5098 5099
	else
		IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");

	IWL_DEBUG_MAC80211("leave\n");

5100 5101
out:
	clear_bit(STATUS_CONF_PENDING, &priv->status);
5102
	mutex_unlock(&priv->mutex);
5103
	return ret;
Z
Zhu Yi 已提交
5104 5105
}

5106
static void iwl4965_config_ap(struct iwl_priv *priv)
Z
Zhu Yi 已提交
5107
{
5108
	int ret = 0;
Z
Zhu Yi 已提交
5109

5110
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Z
Zhu Yi 已提交
5111 5112 5113 5114 5115 5116 5117
		return;

	/* The following should be done only at AP bring up */
	if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {

		/* RXON - unassoc (to set timing command) */
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
5118
		iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5119 5120

		/* RXON Timing */
C
Christoph Hellwig 已提交
5121 5122
		memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
		iwl4965_setup_rxon_timing(priv);
5123
		ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
Z
Zhu Yi 已提交
5124
				sizeof(priv->rxon_timing), &priv->rxon_timing);
5125
		if (ret)
Z
Zhu Yi 已提交
5126 5127 5128
			IWL_WARNING("REPLY_RXON_TIMING failed - "
					"Attempting to continue.\n");

R
Ron Rindjunsky 已提交
5129
		iwl_set_rxon_chain(priv);
Z
Zhu Yi 已提交
5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154

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

			if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
				priv->staging_rxon.flags &=
					~RXON_FLG_SHORT_SLOT_MSK;
		}
		/* restore RXON assoc */
		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
5155 5156
		iwl4965_commit_rxon(priv);
		iwl4965_activate_qos(priv, 1);
5157
		iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
5158
	}
C
Christoph Hellwig 已提交
5159
	iwl4965_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
5160 5161 5162 5163 5164 5165

	/* 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... */
}

5166 5167
static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
					struct ieee80211_vif *vif,
Z
Zhu Yi 已提交
5168 5169
				    struct ieee80211_if_conf *conf)
{
5170
	struct iwl_priv *priv = hw->priv;
5171
	DECLARE_MAC_BUF(mac);
Z
Zhu Yi 已提交
5172 5173 5174 5175 5176 5177
	unsigned long flags;
	int rc;

	if (conf == NULL)
		return -EIO;

5178 5179 5180 5181 5182
	if (priv->vif != vif) {
		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
		return 0;
	}

Z
Zhu Yi 已提交
5183 5184 5185 5186 5187 5188 5189
	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
	    (!conf->beacon || !conf->ssid_len)) {
		IWL_DEBUG_MAC80211
		    ("Leaving in AP mode because HostAPD is not ready.\n");
		return 0;
	}

5190
	if (!iwl_is_alive(priv))
5191 5192
		return -EAGAIN;

Z
Zhu Yi 已提交
5193 5194 5195
	mutex_lock(&priv->mutex);

	if (conf->bssid)
5196 5197
		IWL_DEBUG_MAC80211("bssid: %s\n",
				   print_mac(mac, conf->bssid));
Z
Zhu Yi 已提交
5198

5199 5200 5201
/*
 * very dubious code was here; the probe filtering flag is never set:
 *
Z
Zhu Yi 已提交
5202 5203
	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
5204
 */
Z
Zhu Yi 已提交
5205 5206 5207 5208 5209

	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
		if (!conf->bssid) {
			conf->bssid = priv->mac_addr;
			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
5210 5211
			IWL_DEBUG_MAC80211("bssid was set to: %s\n",
					   print_mac(mac, conf->bssid));
Z
Zhu Yi 已提交
5212 5213 5214 5215 5216 5217 5218
		}
		if (priv->ibss_beacon)
			dev_kfree_skb(priv->ibss_beacon);

		priv->ibss_beacon = conf->beacon;
	}

5219
	if (iwl_is_rfkill(priv))
5220 5221
		goto done;

Z
Zhu Yi 已提交
5222 5223 5224 5225
	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. */
C
Christoph Hellwig 已提交
5226
		if (iwl4965_scan_cancel_timeout(priv, 100)) {
Z
Zhu Yi 已提交
5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241
			IWL_WARNING("Aborted scan still in progress "
				    "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);

		if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
C
Christoph Hellwig 已提交
5242
			iwl4965_config_ap(priv);
Z
Zhu Yi 已提交
5243
		else {
C
Christoph Hellwig 已提交
5244
			rc = iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5245
			if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
5246
				iwl_rxon_add_station(
Z
Zhu Yi 已提交
5247 5248 5249 5250
					priv, priv->active_rxon.bssid_addr, 1);
		}

	} else {
C
Christoph Hellwig 已提交
5251
		iwl4965_scan_cancel_timeout(priv, 100);
Z
Zhu Yi 已提交
5252
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
5253
		iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5254 5255
	}

5256
 done:
Z
Zhu Yi 已提交
5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271
	spin_lock_irqsave(&priv->lock, flags);
	if (!conf->ssid_len)
		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
	else
		memcpy(priv->essid, conf->ssid, conf->ssid_len);

	priv->essid_len = conf->ssid_len;
	spin_unlock_irqrestore(&priv->lock, flags);

	IWL_DEBUG_MAC80211("leave\n");
	mutex_unlock(&priv->mutex);

	return 0;
}

C
Christoph Hellwig 已提交
5272
static void iwl4965_configure_filter(struct ieee80211_hw *hw,
5273 5274 5275 5276 5277 5278
				 unsigned int changed_flags,
				 unsigned int *total_flags,
				 int mc_count, struct dev_addr_list *mc_list)
{
	/*
	 * XXX: dummy
C
Christoph Hellwig 已提交
5279
	 * see also iwl4965_connection_init_rx_config
5280
	 */
5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296
	struct iwl_priv *priv = hw->priv;
	int new_flags = 0;
	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
		if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
			IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
					   IEEE80211_IF_TYPE_MNTR,
					   changed_flags, *total_flags);
			/* queue work 'cuz mac80211 is holding a lock which
			 * prevents us from issuing (synchronous) f/w cmds */
			queue_work(priv->workqueue, &priv->set_monitor);
			new_flags &= FIF_PROMISC_IN_BSS |
				     FIF_OTHER_BSS |
				     FIF_ALLMULTI;
		}
	}
	*total_flags = new_flags;
5297 5298
}

C
Christoph Hellwig 已提交
5299
static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
5300 5301
				     struct ieee80211_if_init_conf *conf)
{
5302
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5303 5304 5305 5306

	IWL_DEBUG_MAC80211("enter\n");

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

5308
	if (iwl_is_ready_rf(priv)) {
5309 5310 5311 5312 5313
		iwl4965_scan_cancel_timeout(priv, 100);
		cancel_delayed_work(&priv->post_associate);
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
		iwl4965_commit_rxon(priv);
	}
5314 5315
	if (priv->vif == conf->vif) {
		priv->vif = NULL;
Z
Zhu Yi 已提交
5316 5317 5318 5319 5320 5321 5322 5323 5324
		memset(priv->bssid, 0, ETH_ALEN);
		memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
		priv->essid_len = 0;
	}
	mutex_unlock(&priv->mutex);

	IWL_DEBUG_MAC80211("leave\n");

}
5325

5326
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
5327 5328 5329 5330
static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif,
				     struct ieee80211_bss_conf *bss_conf,
				     u32 changes)
5331
{
5332
	struct iwl_priv *priv = hw->priv;
5333

5334 5335
	IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);

5336
	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
5337 5338
		IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
				   bss_conf->use_short_preamble);
5339
		if (bss_conf->use_short_preamble)
5340 5341 5342 5343 5344
			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
	}

5345
	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
5346
		IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
5347
		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
5348 5349 5350 5351 5352
			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
		else
			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
	}

T
Tomas Winkler 已提交
5353
	if (changes & BSS_CHANGED_HT) {
5354
		IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
T
Tomas Winkler 已提交
5355
		iwl4965_ht_conf(priv, bss_conf);
R
Ron Rindjunsky 已提交
5356
		iwl_set_rxon_chain(priv);
T
Tomas Winkler 已提交
5357 5358
	}

5359
	if (changes & BSS_CHANGED_ASSOC) {
5360
		IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
5361 5362 5363 5364
		/* This should never happen as this function should
		 * never be called from interrupt context. */
		if (WARN_ON_ONCE(in_interrupt()))
			return;
5365 5366 5367 5368 5369 5370 5371
		if (bss_conf->assoc) {
			priv->assoc_id = bss_conf->aid;
			priv->beacon_int = bss_conf->beacon_int;
			priv->timestamp = bss_conf->timestamp;
			priv->assoc_capability = bss_conf->assoc_capability;
			priv->next_scan_jiffies = jiffies +
					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
5372 5373 5374
			mutex_lock(&priv->mutex);
			iwl4965_post_associate(priv);
			mutex_unlock(&priv->mutex);
5375 5376 5377 5378 5379 5380
		} 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);
5381
			iwl_send_rxon_assoc(priv);
5382 5383
	}

5384
}
Z
Zhu Yi 已提交
5385

C
Christoph Hellwig 已提交
5386
static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
Z
Zhu Yi 已提交
5387 5388 5389
{
	int rc = 0;
	unsigned long flags;
5390
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5391 5392 5393

	IWL_DEBUG_MAC80211("enter\n");

5394
	mutex_lock(&priv->mutex);
Z
Zhu Yi 已提交
5395 5396
	spin_lock_irqsave(&priv->lock, flags);

5397
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408
		rc = -EIO;
		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
		goto out_unlock;
	}

	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {	/* APs don't scan */
		rc = -EIO;
		IWL_ERROR("ERROR: APs don't scan\n");
		goto out_unlock;
	}

5409 5410 5411 5412 5413 5414
	/* we don't schedule scan within next_scan_jiffies period */
	if (priv->next_scan_jiffies &&
			time_after(priv->next_scan_jiffies, jiffies)) {
		rc = -EAGAIN;
		goto out_unlock;
	}
Z
Zhu Yi 已提交
5415
	/* if we just finished scan ask for delay */
5416 5417
	if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
				IWL_DELAY_NEXT_SCAN, jiffies)) {
Z
Zhu Yi 已提交
5418 5419 5420 5421
		rc = -EAGAIN;
		goto out_unlock;
	}
	if (len) {
5422
		IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
C
Christoph Hellwig 已提交
5423
			       iwl4965_escape_essid(ssid, len), (int)len);
Z
Zhu Yi 已提交
5424 5425 5426 5427 5428

		priv->one_direct_scan = 1;
		priv->direct_ssid_len = (u8)
		    min((u8) len, (u8) IW_ESSID_MAX_SIZE);
		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
M
Mohamed Abbas 已提交
5429 5430
	} else
		priv->one_direct_scan = 0;
Z
Zhu Yi 已提交
5431

C
Christoph Hellwig 已提交
5432
	rc = iwl4965_scan_initiate(priv);
Z
Zhu Yi 已提交
5433 5434 5435 5436 5437

	IWL_DEBUG_MAC80211("leave\n");

out_unlock:
	spin_unlock_irqrestore(&priv->lock, flags);
5438
	mutex_unlock(&priv->mutex);
Z
Zhu Yi 已提交
5439 5440 5441 5442

	return rc;
}

5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455
static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
			struct ieee80211_key_conf *keyconf, const u8 *addr,
			u32 iv32, u16 *phase1key)
{
	struct iwl_priv *priv = hw->priv;
	u8 sta_id = IWL_INVALID_STATION;
	unsigned long flags;
	__le16 key_flags = 0;
	int i;
	DECLARE_MAC_BUF(mac);

	IWL_DEBUG_MAC80211("enter\n");

5456
	sta_id = iwl_find_station(priv, addr);
5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468
	if (sta_id == IWL_INVALID_STATION) {
		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
				   print_mac(mac, addr));
		return;
	}

	iwl4965_scan_cancel_timeout(priv, 100);

	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
	key_flags &= ~STA_KEY_FLG_INVALID;

T
Tomas Winkler 已提交
5469
	if (sta_id == priv->hw_params.bcast_sta_id)
5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483
		key_flags |= STA_KEY_MULTICAST_MSK;

	spin_lock_irqsave(&priv->sta_lock, flags);

	priv->stations[sta_id].sta.key.key_flags = key_flags;
	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;

	for (i = 0; i < 5; i++)
		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
			cpu_to_le16(phase1key[i]);

	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

5484
	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
5485 5486 5487 5488 5489 5490

	spin_unlock_irqrestore(&priv->sta_lock, flags);

	IWL_DEBUG_MAC80211("leave\n");
}

C
Christoph Hellwig 已提交
5491
static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Z
Zhu Yi 已提交
5492 5493 5494
			   const u8 *local_addr, const u8 *addr,
			   struct ieee80211_key_conf *key)
{
5495
	struct iwl_priv *priv = hw->priv;
5496
	DECLARE_MAC_BUF(mac);
5497 5498
	int ret = 0;
	u8 sta_id = IWL_INVALID_STATION;
5499
	u8 is_default_wep_key = 0;
Z
Zhu Yi 已提交
5500 5501 5502

	IWL_DEBUG_MAC80211("enter\n");

5503
	if (priv->hw_params.sw_crypto) {
Z
Zhu Yi 已提交
5504 5505 5506 5507 5508 5509 5510 5511
		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
		return -EOPNOTSUPP;
	}

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

5512
	sta_id = iwl_find_station(priv, addr);
5513 5514 5515 5516
	if (sta_id == IWL_INVALID_STATION) {
		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
				   print_mac(mac, addr));
		return -EINVAL;
Z
Zhu Yi 已提交
5517

5518
	}
Z
Zhu Yi 已提交
5519

5520
	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
5521
	iwl4965_scan_cancel_timeout(priv, 100);
5522 5523 5524 5525 5526 5527
	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 已提交
5528
	if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
5529 5530 5531 5532 5533 5534
		priv->iw_mode != IEEE80211_IF_TYPE_AP) {
		if (cmd == SET_KEY)
			is_default_wep_key = !priv->key_mapping_key;
		else
			is_default_wep_key = priv->default_wep_key;
	}
5535

Z
Zhu Yi 已提交
5536
	switch (cmd) {
5537
	case SET_KEY:
5538 5539
		if (is_default_wep_key)
			ret = iwl_set_default_wep_key(priv, key);
5540
		else
5541
			ret = iwl_set_dynamic_key(priv, key, sta_id);
5542 5543

		IWL_DEBUG_MAC80211("enable hwcrypto key\n");
Z
Zhu Yi 已提交
5544 5545
		break;
	case DISABLE_KEY:
5546 5547
		if (is_default_wep_key)
			ret = iwl_remove_default_wep_key(priv, key);
5548
		else
5549
			ret = iwl_remove_dynamic_key(priv, key, sta_id);
5550 5551

		IWL_DEBUG_MAC80211("disable hwcrypto key\n");
Z
Zhu Yi 已提交
5552 5553
		break;
	default:
5554
		ret = -EINVAL;
Z
Zhu Yi 已提交
5555 5556 5557 5558
	}

	IWL_DEBUG_MAC80211("leave\n");

5559
	return ret;
Z
Zhu Yi 已提交
5560 5561
}

J
Johannes Berg 已提交
5562
static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
Z
Zhu Yi 已提交
5563 5564
			   const struct ieee80211_tx_queue_params *params)
{
5565
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5566 5567 5568 5569 5570
	unsigned long flags;
	int q;

	IWL_DEBUG_MAC80211("enter\n");

5571
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593
		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;
	}

	if (!priv->qos_data.qos_enable) {
		priv->qos_data.qos_active = 0;
		IWL_DEBUG_MAC80211("leave - qos not enabled\n");
		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 =
5594
			cpu_to_le16((params->txop * 32));
Z
Zhu Yi 已提交
5595 5596 5597 5598 5599 5600 5601 5602

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

	spin_unlock_irqrestore(&priv->lock, flags);

	mutex_lock(&priv->mutex);
	if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
C
Christoph Hellwig 已提交
5603
		iwl4965_activate_qos(priv, 1);
5604
	else if (priv->assoc_id && iwl_is_associated(priv))
C
Christoph Hellwig 已提交
5605
		iwl4965_activate_qos(priv, 0);
Z
Zhu Yi 已提交
5606 5607 5608 5609 5610 5611 5612

	mutex_unlock(&priv->mutex);

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

C
Christoph Hellwig 已提交
5613
static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
5614 5615
				struct ieee80211_tx_queue_stats *stats)
{
5616
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5617
	int i, avail;
5618
	struct iwl_tx_queue *txq;
5619
	struct iwl_queue *q;
Z
Zhu Yi 已提交
5620 5621 5622 5623
	unsigned long flags;

	IWL_DEBUG_MAC80211("enter\n");

5624
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
5625 5626 5627 5628 5629 5630 5631 5632 5633
		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;
5634
		avail = iwl_queue_space(q);
Z
Zhu Yi 已提交
5635

5636 5637 5638
		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 已提交
5639 5640 5641 5642 5643 5644 5645 5646 5647

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

	IWL_DEBUG_MAC80211("leave\n");

	return 0;
}

C
Christoph Hellwig 已提交
5648
static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
5649 5650
			     struct ieee80211_low_level_stats *stats)
{
5651 5652 5653
	struct iwl_priv *priv = hw->priv;

	priv = hw->priv;
Z
Zhu Yi 已提交
5654 5655 5656 5657 5658 5659
	IWL_DEBUG_MAC80211("enter\n");
	IWL_DEBUG_MAC80211("leave\n");

	return 0;
}

C
Christoph Hellwig 已提交
5660
static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
5661
{
5662 5663 5664
	struct iwl_priv *priv;

	priv = hw->priv;
Z
Zhu Yi 已提交
5665 5666 5667 5668 5669 5670
	IWL_DEBUG_MAC80211("enter\n");
	IWL_DEBUG_MAC80211("leave\n");

	return 0;
}

C
Christoph Hellwig 已提交
5671
static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
5672
{
5673
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5674 5675 5676 5677 5678 5679
	unsigned long flags;

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

	priv->lq_mngr.lq_ready = 0;
5680
#ifdef CONFIG_IWL4965_HT
Z
Zhu Yi 已提交
5681
	spin_lock_irqsave(&priv->lock, flags);
5682
	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
Z
Zhu Yi 已提交
5683
	spin_unlock_irqrestore(&priv->lock, flags);
5684
#endif /* CONFIG_IWL4965_HT */
Z
Zhu Yi 已提交
5685

R
Ron Rindjunsky 已提交
5686
	iwl_reset_qos(priv);
Z
Zhu Yi 已提交
5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701

	cancel_delayed_work(&priv->post_associate);

	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;
5702
	priv->timestamp = 0;
Z
Zhu Yi 已提交
5703 5704 5705 5706 5707
	if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
		priv->beacon_int = 0;

	spin_unlock_irqrestore(&priv->lock, flags);

5708
	if (!iwl_is_ready_rf(priv)) {
5709 5710 5711 5712 5713
		IWL_DEBUG_MAC80211("leave - not ready\n");
		mutex_unlock(&priv->mutex);
		return;
	}

5714 5715 5716 5717
	/* we are restarting association process
	 * clear RXON_FILTER_ASSOC_MSK bit
	 */
	if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
C
Christoph Hellwig 已提交
5718
		iwl4965_scan_cancel_timeout(priv, 100);
5719
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
5720
		iwl4965_commit_rxon(priv);
5721 5722
	}

M
Mohamed Abbas 已提交
5723 5724
	iwl_power_update_mode(priv, 0);

Z
Zhu Yi 已提交
5725 5726
	/* Per mac80211.h: This is only used in IBSS mode... */
	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
5727

Z
Zhu Yi 已提交
5728 5729 5730 5731 5732
		IWL_DEBUG_MAC80211("leave - not in IBSS\n");
		mutex_unlock(&priv->mutex);
		return;
	}

C
Christoph Hellwig 已提交
5733
	iwl4965_set_rate(priv);
Z
Zhu Yi 已提交
5734 5735 5736 5737 5738 5739

	mutex_unlock(&priv->mutex);

	IWL_DEBUG_MAC80211("leave\n");
}

C
Christoph Hellwig 已提交
5740
static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
Z
Zhu Yi 已提交
5741 5742
				 struct ieee80211_tx_control *control)
{
5743
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
5744 5745 5746 5747 5748
	unsigned long flags;

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

5749
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772
		IWL_DEBUG_MAC80211("leave - RF not ready\n");
		mutex_unlock(&priv->mutex);
		return -EIO;
	}

	if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
		IWL_DEBUG_MAC80211("leave - not IBSS\n");
		mutex_unlock(&priv->mutex);
		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;

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

R
Ron Rindjunsky 已提交
5773
	iwl_reset_qos(priv);
Z
Zhu Yi 已提交
5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787

	queue_work(priv->workqueue, &priv->post_associate.work);

	mutex_unlock(&priv->mutex);

	return 0;
}

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

5788
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
5789 5790 5791 5792 5793 5794 5795 5796 5797

/*
 * The following adds a new attribute to the sysfs representation
 * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
 * used for controlling the debug level.
 *
 * See the level definitions in iwl for details.
 */

5798 5799
static ssize_t show_debug_level(struct device *d,
				struct device_attribute *attr, char *buf)
Z
Zhu Yi 已提交
5800
{
5801 5802 5803
	struct iwl_priv *priv = d->driver_data;

	return sprintf(buf, "0x%08X\n", priv->debug_level);
Z
Zhu Yi 已提交
5804
}
5805 5806
static ssize_t store_debug_level(struct device *d,
				struct device_attribute *attr,
Z
Zhu Yi 已提交
5807 5808
				 const char *buf, size_t count)
{
5809
	struct iwl_priv *priv = d->driver_data;
Z
Zhu Yi 已提交
5810 5811 5812 5813 5814 5815 5816 5817
	char *p = (char *)buf;
	u32 val;

	val = simple_strtoul(p, &p, 0);
	if (p == buf)
		printk(KERN_INFO DRV_NAME
		       ": %s is not in hex or decimal form.\n", buf);
	else
5818
		priv->debug_level = val;
Z
Zhu Yi 已提交
5819 5820 5821 5822

	return strnlen(buf, count);
}

5823 5824 5825
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
			show_debug_level, store_debug_level);

Z
Zhu Yi 已提交
5826

5827
#endif /* CONFIG_IWLWIFI_DEBUG */
Z
Zhu Yi 已提交
5828 5829


5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848
static ssize_t show_version(struct device *d,
				struct device_attribute *attr, char *buf)
{
	struct iwl_priv *priv = d->driver_data;
	struct iwl4965_alive_resp *palive = &priv->card_alive;

	if (palive->is_valid)
		return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
				    "fw type: 0x%01X 0x%01X\n",
				palive->ucode_major, palive->ucode_minor,
				palive->sw_rev[0], palive->sw_rev[1],
				palive->ver_type, palive->ver_subtype);

	else
		return sprintf(buf, "fw not loaded\n");
}

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

Z
Zhu Yi 已提交
5849 5850 5851
static ssize_t show_temperature(struct device *d,
				struct device_attribute *attr, char *buf)
{
5852
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5853

5854
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
5855 5856
		return -EAGAIN;

C
Christoph Hellwig 已提交
5857
	return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
Z
Zhu Yi 已提交
5858 5859 5860 5861 5862 5863 5864 5865
}

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

static ssize_t show_rs_window(struct device *d,
			      struct device_attribute *attr,
			      char *buf)
{
5866
	struct iwl_priv *priv = d->driver_data;
C
Christoph Hellwig 已提交
5867
	return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID);
Z
Zhu Yi 已提交
5868 5869 5870 5871 5872 5873
}
static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);

static ssize_t show_tx_power(struct device *d,
			     struct device_attribute *attr, char *buf)
{
5874
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5875 5876 5877 5878 5879 5880 5881
	return sprintf(buf, "%d\n", priv->user_txpower_limit);
}

static ssize_t store_tx_power(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
5882
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5883 5884 5885 5886 5887 5888 5889 5890
	char *p = (char *)buf;
	u32 val;

	val = simple_strtoul(p, &p, 10);
	if (p == buf)
		printk(KERN_INFO DRV_NAME
		       ": %s is not in decimal form.\n", buf);
	else
C
Christoph Hellwig 已提交
5891
		iwl4965_hw_reg_set_txpower(priv, val);
Z
Zhu Yi 已提交
5892 5893 5894 5895 5896 5897 5898 5899 5900

	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)
{
5901
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5902 5903 5904 5905 5906 5907 5908 5909

	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)
{
5910
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5911 5912 5913 5914 5915
	u32 flags = simple_strtoul(buf, NULL, 0);

	mutex_lock(&priv->mutex);
	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
		/* Cancel any currently running scans... */
C
Christoph Hellwig 已提交
5916
		if (iwl4965_scan_cancel_timeout(priv, 100))
Z
Zhu Yi 已提交
5917 5918 5919 5920 5921
			IWL_WARNING("Could not cancel scan.\n");
		else {
			IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
				       flags);
			priv->staging_rxon.flags = cpu_to_le32(flags);
C
Christoph Hellwig 已提交
5922
			iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934
		}
	}
	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)
{
5935
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5936 5937 5938 5939 5940 5941 5942 5943 5944

	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)
{
5945
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
5946 5947 5948 5949 5950
	u32 filter_flags = simple_strtoul(buf, NULL, 0);

	mutex_lock(&priv->mutex);
	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
		/* Cancel any currently running scans... */
C
Christoph Hellwig 已提交
5951
		if (iwl4965_scan_cancel_timeout(priv, 100))
Z
Zhu Yi 已提交
5952 5953 5954 5955 5956 5957
			IWL_WARNING("Could not cancel scan.\n");
		else {
			IWL_DEBUG_INFO("Committing rxon.filter_flags = "
				       "0x%04X\n", filter_flags);
			priv->staging_rxon.filter_flags =
				cpu_to_le32(filter_flags);
C
Christoph Hellwig 已提交
5958
			iwl4965_commit_rxon(priv);
Z
Zhu Yi 已提交
5959 5960 5961 5962 5963 5964 5965 5966 5967 5968
		}
	}
	mutex_unlock(&priv->mutex);

	return count;
}

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

5969
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
5970 5971 5972 5973

static ssize_t show_measurement(struct device *d,
				struct device_attribute *attr, char *buf)
{
5974
	struct iwl_priv *priv = dev_get_drvdata(d);
C
Christoph Hellwig 已提交
5975
	struct iwl4965_spectrum_notification measure_report;
Z
Zhu Yi 已提交
5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006
	u32 size = sizeof(measure_report), len = 0, ofs = 0;
	u8 *data = (u8 *) & measure_report;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
	if (!(priv->measurement_status & MEASUREMENT_READY)) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return 0;
	}
	memcpy(&measure_report, &priv->measure_report, size);
	priv->measurement_status = 0;
	spin_unlock_irqrestore(&priv->lock, flags);

	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 ssize_t store_measurement(struct device *d,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
6007
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032
	struct ieee80211_measurement_params params = {
		.channel = le16_to_cpu(priv->active_rxon.channel),
		.start_time = cpu_to_le64(priv->last_tsf),
		.duration = cpu_to_le16(1),
	};
	u8 type = IWL_MEASURE_BASIC;
	u8 buffer[32];
	u8 channel;

	if (count) {
		char *p = buffer;
		strncpy(buffer, buf, min(sizeof(buffer), count));
		channel = simple_strtoul(p, NULL, 0);
		if (channel)
			params.channel = channel;

		p = buffer;
		while (*p && *p != ' ')
			p++;
		if (*p)
			type = simple_strtoul(p + 1, NULL, 0);
	}

	IWL_DEBUG_INFO("Invoking measurement of type %d on "
		       "channel %d (for '%s')\n", type, params.channel, buf);
C
Christoph Hellwig 已提交
6033
	iwl4965_get_measurement(priv, &params, type);
Z
Zhu Yi 已提交
6034 6035 6036 6037 6038 6039

	return count;
}

static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
		   show_measurement, store_measurement);
6040
#endif /* CONFIG_IWL4965_SPECTRUM_MEASUREMENT */
Z
Zhu Yi 已提交
6041 6042 6043 6044 6045

static ssize_t store_retry_rate(struct device *d,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
6046
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057

	priv->retry_rate = simple_strtoul(buf, NULL, 0);
	if (priv->retry_rate <= 0)
		priv->retry_rate = 1;

	return count;
}

static ssize_t show_retry_rate(struct device *d,
			       struct device_attribute *attr, char *buf)
{
6058
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
6059 6060 6061 6062 6063 6064 6065 6066 6067 6068
	return sprintf(buf, "%d", priv->retry_rate);
}

static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
		   store_retry_rate);

static ssize_t store_power_level(struct device *d,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
6069
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
6070 6071 6072 6073 6074 6075
	int rc;
	int mode;

	mode = simple_strtoul(buf, NULL, 0);
	mutex_lock(&priv->mutex);

6076
	if (!iwl_is_ready(priv)) {
Z
Zhu Yi 已提交
6077 6078 6079 6080
		rc = -EAGAIN;
		goto out;
	}

M
Mohamed Abbas 已提交
6081 6082 6083 6084
	rc = iwl_power_set_user_mode(priv, mode);
	if (rc) {
		IWL_DEBUG_MAC80211("failed setting power mode.\n");
		goto out;
Z
Zhu Yi 已提交
6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113
	}
	rc = count;

 out:
	mutex_unlock(&priv->mutex);
	return rc;
}

#define MAX_WX_STRING 80

/* Values are in microsecond */
static const s32 timeout_duration[] = {
	350000,
	250000,
	75000,
	37000,
	25000,
};
static const s32 period_duration[] = {
	400000,
	700000,
	1000000,
	1000000,
	1000000
};

static ssize_t show_power_level(struct device *d,
				struct device_attribute *attr, char *buf)
{
6114
	struct iwl_priv *priv = dev_get_drvdata(d);
M
Mohamed Abbas 已提交
6115
	int level = priv->power_data.power_mode;
Z
Zhu Yi 已提交
6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132
	char *p = buf;

	p += sprintf(p, "%d ", level);
	switch (level) {
	case IWL_POWER_MODE_CAM:
	case IWL_POWER_AC:
		p += sprintf(p, "(AC)");
		break;
	case IWL_POWER_BATTERY:
		p += sprintf(p, "(BATTERY)");
		break;
	default:
		p += sprintf(p,
			     "(Timeout %dms, Period %dms)",
			     timeout_duration[level - 1] / 1000,
			     period_duration[level - 1] / 1000);
	}
M
Mohamed Abbas 已提交
6133
/*
Z
Zhu Yi 已提交
6134 6135 6136 6137
	if (!(priv->power_mode & IWL_POWER_ENABLED))
		p += sprintf(p, " OFF\n");
	else
		p += sprintf(p, " \n");
M
Mohamed Abbas 已提交
6138 6139
*/
	p += sprintf(p, " \n");
Z
Zhu Yi 已提交
6140 6141 6142 6143 6144 6145 6146 6147 6148
	return (p - buf + 1);
}

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

static ssize_t show_channels(struct device *d,
			     struct device_attribute *attr, char *buf)
{
6149 6150
	/* all this shit doesn't belong into sysfs anyway */
	return 0;
Z
Zhu Yi 已提交
6151 6152 6153 6154 6155 6156 6157
}

static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);

static ssize_t show_statistics(struct device *d,
			       struct device_attribute *attr, char *buf)
{
6158
	struct iwl_priv *priv = dev_get_drvdata(d);
C
Christoph Hellwig 已提交
6159
	u32 size = sizeof(struct iwl4965_notif_statistics);
Z
Zhu Yi 已提交
6160 6161 6162 6163
	u32 len = 0, ofs = 0;
	u8 *data = (u8 *) & priv->statistics;
	int rc = 0;

6164
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
6165 6166 6167
		return -EAGAIN;

	mutex_lock(&priv->mutex);
6168
	rc = iwl_send_statistics_request(priv, 0);
Z
Zhu Yi 已提交
6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195
	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);

static ssize_t show_status(struct device *d,
			   struct device_attribute *attr, char *buf)
{
6196
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
6197
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210
		return -EAGAIN;
	return sprintf(buf, "0x%08x\n", (int)priv->status);
}

static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);

static ssize_t dump_error_log(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
	char *p = (char *)buf;

	if (p[0] == '1')
6211
		iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
Z
Zhu Yi 已提交
6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224

	return strnlen(buf, count);
}

static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);

static ssize_t dump_event_log(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
	char *p = (char *)buf;

	if (p[0] == '1')
6225
		iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
Z
Zhu Yi 已提交
6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237

	return strnlen(buf, count);
}

static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);

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

6238
static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
6239 6240 6241 6242 6243
{
	priv->workqueue = create_workqueue(DRV_NAME);

	init_waitqueue_head(&priv->wait_command_queue);

C
Christoph Hellwig 已提交
6244 6245 6246 6247 6248 6249 6250 6251
	INIT_WORK(&priv->up, iwl4965_bg_up);
	INIT_WORK(&priv->restart, iwl4965_bg_restart);
	INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
	INIT_WORK(&priv->scan_completed, iwl4965_bg_scan_completed);
	INIT_WORK(&priv->request_scan, iwl4965_bg_request_scan);
	INIT_WORK(&priv->abort_scan, iwl4965_bg_abort_scan);
	INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
	INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
6252
	INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
C
Christoph Hellwig 已提交
6253 6254 6255 6256 6257 6258
	INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
	INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
	INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
	INIT_DELAYED_WORK(&priv->scan_check, iwl4965_bg_scan_check);

	iwl4965_hw_setup_deferred_work(priv);
Z
Zhu Yi 已提交
6259 6260

	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
C
Christoph Hellwig 已提交
6261
		     iwl4965_irq_tasklet, (unsigned long)priv);
Z
Zhu Yi 已提交
6262 6263
}

6264
static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
6265
{
C
Christoph Hellwig 已提交
6266
	iwl4965_hw_cancel_deferred_work(priv);
Z
Zhu Yi 已提交
6267

6268
	cancel_delayed_work_sync(&priv->init_alive_start);
Z
Zhu Yi 已提交
6269 6270 6271 6272 6273 6274
	cancel_delayed_work(&priv->scan_check);
	cancel_delayed_work(&priv->alive_start);
	cancel_delayed_work(&priv->post_associate);
	cancel_work_sync(&priv->beacon_update);
}

C
Christoph Hellwig 已提交
6275
static struct attribute *iwl4965_sysfs_entries[] = {
Z
Zhu Yi 已提交
6276 6277 6278 6279 6280
	&dev_attr_channels.attr,
	&dev_attr_dump_errors.attr,
	&dev_attr_dump_events.attr,
	&dev_attr_flags.attr,
	&dev_attr_filter_flags.attr,
6281
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
6282 6283 6284 6285 6286 6287 6288 6289 6290
	&dev_attr_measurement.attr,
#endif
	&dev_attr_power_level.attr,
	&dev_attr_retry_rate.attr,
	&dev_attr_rs_window.attr,
	&dev_attr_statistics.attr,
	&dev_attr_status.attr,
	&dev_attr_temperature.attr,
	&dev_attr_tx_power.attr,
6291 6292 6293
#ifdef CONFIG_IWLWIFI_DEBUG
	&dev_attr_debug_level.attr,
#endif
6294
	&dev_attr_version.attr,
Z
Zhu Yi 已提交
6295 6296 6297 6298

	NULL
};

C
Christoph Hellwig 已提交
6299
static struct attribute_group iwl4965_attribute_group = {
Z
Zhu Yi 已提交
6300
	.name = NULL,		/* put in device directory */
C
Christoph Hellwig 已提交
6301
	.attrs = iwl4965_sysfs_entries,
Z
Zhu Yi 已提交
6302 6303
};

C
Christoph Hellwig 已提交
6304 6305 6306 6307 6308 6309 6310 6311 6312 6313
static struct ieee80211_ops iwl4965_hw_ops = {
	.tx = iwl4965_mac_tx,
	.start = iwl4965_mac_start,
	.stop = iwl4965_mac_stop,
	.add_interface = iwl4965_mac_add_interface,
	.remove_interface = iwl4965_mac_remove_interface,
	.config = iwl4965_mac_config,
	.config_interface = iwl4965_mac_config_interface,
	.configure_filter = iwl4965_configure_filter,
	.set_key = iwl4965_mac_set_key,
6314
	.update_tkip_key = iwl4965_mac_update_tkip_key,
C
Christoph Hellwig 已提交
6315 6316 6317 6318 6319 6320
	.get_stats = iwl4965_mac_get_stats,
	.get_tx_stats = iwl4965_mac_get_tx_stats,
	.conf_tx = iwl4965_mac_conf_tx,
	.get_tsf = iwl4965_mac_get_tsf,
	.reset_tsf = iwl4965_mac_reset_tsf,
	.beacon_update = iwl4965_mac_beacon_update,
6321
	.bss_info_changed = iwl4965_bss_info_changed,
6322
#ifdef CONFIG_IWL4965_HT
R
Ron Rindjunsky 已提交
6323
	.ampdu_action = iwl4965_mac_ampdu_action,
6324
#endif  /* CONFIG_IWL4965_HT */
C
Christoph Hellwig 已提交
6325
	.hw_scan = iwl4965_mac_hw_scan
Z
Zhu Yi 已提交
6326 6327
};

C
Christoph Hellwig 已提交
6328
static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Z
Zhu Yi 已提交
6329 6330
{
	int err = 0;
6331
	struct iwl_priv *priv;
Z
Zhu Yi 已提交
6332
	struct ieee80211_hw *hw;
T
Tomas Winkler 已提交
6333
	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
6334
	unsigned long flags;
6335
	DECLARE_MAC_BUF(mac);
Z
Zhu Yi 已提交
6336

6337 6338 6339 6340
	/************************
	 * 1. Allocating HW data
	 ************************/

6341 6342
	/* Disabling hardware scan means that mac80211 will perform scans
	 * "the hard way", rather than using device's scan. */
6343
	if (cfg->mod_params->disable_hw_scan) {
6344 6345 6346
		if (cfg->mod_params->debug & IWL_DL_INFO)
			dev_printk(KERN_DEBUG, &(pdev->dev),
				   "Disabling hw_scan\n");
C
Christoph Hellwig 已提交
6347
		iwl4965_hw_ops.hw_scan = NULL;
Z
Zhu Yi 已提交
6348 6349
	}

6350 6351
	hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
	if (!hw) {
Z
Zhu Yi 已提交
6352 6353 6354
		err = -ENOMEM;
		goto out;
	}
6355 6356 6357
	priv = hw->priv;
	/* At this point both hw and priv are allocated. */

Z
Zhu Yi 已提交
6358 6359 6360
	SET_IEEE80211_DEV(hw, &pdev->dev);

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

6364
#ifdef CONFIG_IWLWIFI_DEBUG
6365
	priv->debug_level = priv->cfg->mod_params->debug;
Z
Zhu Yi 已提交
6366 6367 6368
	atomic_set(&priv->restrict_refcnt, 0);
#endif

6369 6370 6371 6372 6373 6374 6375 6376 6377 6378
	/**************************
	 * 2. Initializing PCI bus
	 **************************/
	if (pci_enable_device(pdev)) {
		err = -ENODEV;
		goto out_ieee80211_free_hw;
	}

	pci_set_master(pdev);

6379
	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
6380
	if (!err)
6381 6382 6383 6384 6385 6386
		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
	if (err) {
		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
		if (!err)
			err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
		/* both attempts failed: */
6387
		if (err) {
6388 6389
			printk(KERN_WARNING "%s: No suitable DMA available.\n",
				DRV_NAME);
6390
			goto out_pci_disable_device;
6391
		}
6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416
	}

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

	pci_set_drvdata(pdev, priv);

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

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

6417
	iwl_hw_detect(priv);
6418
	printk(KERN_INFO DRV_NAME
6419 6420
		": Detected Intel Wireless WiFi Link %s REV=0x%X\n",
		priv->cfg->name, priv->hw_rev);
6421

T
Tomas Winkler 已提交
6422 6423
	/* amp init */
	err = priv->cfg->ops->lib->apm_ops.init(priv);
6424
	if (err < 0) {
T
Tomas Winkler 已提交
6425
		IWL_DEBUG_INFO("Failed to init APMG\n");
6426 6427
		goto out_iounmap;
	}
T
Tomas Winkler 已提交
6428 6429 6430
	/*****************
	 * 4. Read EEPROM
	 *****************/
6431 6432 6433 6434 6435 6436
	/* Read the EEPROM */
	err = iwl_eeprom_init(priv);
	if (err) {
		IWL_ERROR("Unable to init EEPROM\n");
		goto out_iounmap;
	}
6437 6438 6439 6440
	err = iwl_eeprom_check_version(priv);
	if (err)
		goto out_iounmap;

6441
	/* extract MAC Address */
6442 6443 6444 6445 6446 6447 6448 6449
	iwl_eeprom_get_mac(priv, priv->mac_addr);
	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);

	/************************
	 * 5. Setup HW constants
	 ************************/
	/* Device-specific setup */
T
Tomas Winkler 已提交
6450 6451
	if (priv->cfg->ops->lib->set_hw_params(priv)) {
		IWL_ERROR("failed to set hw parameters\n");
6452
		goto out_free_eeprom;
6453 6454 6455 6456 6457
	}

	/*******************
	 * 6. Setup hw/priv
	 *******************/
Z
Zhu Yi 已提交
6458

6459 6460
	err = iwl_setup(priv);
	if (err)
R
Ron Rindjunsky 已提交
6461
		goto out_free_eeprom;
6462
	/* At this point both hw and priv are initialized. */
6463 6464 6465 6466 6467 6468

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

	/* Disable radio (SW RF KILL) via parameter when loading driver */
6469
	if (priv->cfg->mod_params->disable) {
6470 6471 6472 6473
		set_bit(STATUS_RF_KILL_SW, &priv->status);
		IWL_DEBUG_INFO("Radio disabled.\n");
	}

6474
	if (priv->cfg->mod_params->enable_qos)
6475 6476 6477 6478 6479
		priv->qos_data.qos_enable = 1;

	/********************
	 * 8. Setup services
	 ********************/
6480
	spin_lock_irqsave(&priv->lock, flags);
6481
	iwl4965_disable_interrupts(priv);
6482
	spin_unlock_irqrestore(&priv->lock, flags);
6483 6484 6485 6486

	err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
	if (err) {
		IWL_ERROR("failed to create sysfs device attributes\n");
R
Ron Rindjunsky 已提交
6487
		goto out_free_eeprom;
6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501
	}

	err = iwl_dbgfs_register(priv, DRV_NAME);
	if (err) {
		IWL_ERROR("failed to create debugfs files\n");
		goto out_remove_sysfs;
	}

	iwl4965_setup_deferred_work(priv);
	iwl4965_setup_rx_handlers(priv);

	/********************
	 * 9. Conclude
	 ********************/
6502 6503
	pci_save_state(pdev);
	pci_disable_device(pdev);
Z
Zhu Yi 已提交
6504

6505 6506
	/* notify iwlcore to init */
	iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
Z
Zhu Yi 已提交
6507 6508
	return 0;

6509 6510
 out_remove_sysfs:
	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
6511 6512
 out_free_eeprom:
	iwl_eeprom_free(priv);
Z
Zhu Yi 已提交
6513 6514 6515 6516
 out_iounmap:
	pci_iounmap(pdev, priv->hw_base);
 out_pci_release_regions:
	pci_release_regions(pdev);
6517
	pci_set_drvdata(pdev, NULL);
Z
Zhu Yi 已提交
6518 6519 6520 6521 6522 6523 6524 6525
 out_pci_disable_device:
	pci_disable_device(pdev);
 out_ieee80211_free_hw:
	ieee80211_free_hw(priv->hw);
 out:
	return err;
}

6526
static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
Z
Zhu Yi 已提交
6527
{
6528
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
6529 6530
	struct list_head *p, *q;
	int i;
6531
	unsigned long flags;
Z
Zhu Yi 已提交
6532 6533 6534 6535 6536 6537

	if (!priv)
		return;

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

6538 6539 6540 6541 6542
	if (priv->mac80211_registered) {
		ieee80211_unregister_hw(priv->hw);
		priv->mac80211_registered = 0;
	}

Z
Zhu Yi 已提交
6543
	set_bit(STATUS_EXIT_PENDING, &priv->status);
6544

C
Christoph Hellwig 已提交
6545
	iwl4965_down(priv);
Z
Zhu Yi 已提交
6546

6547 6548 6549 6550 6551 6552 6553 6554 6555
	/* make sure we flush any pending irq or
	 * tasklet for the driver
	 */
	spin_lock_irqsave(&priv->lock, flags);
	iwl4965_disable_interrupts(priv);
	spin_unlock_irqrestore(&priv->lock, flags);

	iwl_synchronize_irq(priv);

Z
Zhu Yi 已提交
6556 6557 6558 6559
	/* Free MAC hash list for ADHOC */
	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
			list_del(p);
C
Christoph Hellwig 已提交
6560
			kfree(list_entry(p, struct iwl4965_ibss_seq, list));
Z
Zhu Yi 已提交
6561 6562 6563
		}
	}

6564
	iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT);
T
Tomas Winkler 已提交
6565
	iwl_dbgfs_unregister(priv);
C
Christoph Hellwig 已提交
6566
	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
Z
Zhu Yi 已提交
6567

C
Christoph Hellwig 已提交
6568
	iwl4965_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
6569 6570

	if (priv->rxq.bd)
6571
		iwl_rx_queue_free(priv, &priv->rxq);
6572
	iwl_hw_txq_ctx_free(priv);
Z
Zhu Yi 已提交
6573

6574
	iwlcore_clear_stations_table(priv);
6575
	iwl_eeprom_free(priv);
Z
Zhu Yi 已提交
6576 6577


M
Mohamed Abbas 已提交
6578 6579 6580
	/*netif_stop_queue(dev); */
	flush_workqueue(priv->workqueue);

C
Christoph Hellwig 已提交
6581
	/* ieee80211_unregister_hw calls iwl4965_mac_stop, which flushes
Z
Zhu Yi 已提交
6582 6583 6584 6585 6586 6587 6588 6589 6590 6591
	 * 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);

6592
	iwl_free_channel_map(priv);
R
Ron Rindjunsky 已提交
6593
	iwlcore_free_geos(priv);
Z
Zhu Yi 已提交
6594 6595 6596 6597 6598 6599 6600 6601 6602

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

	ieee80211_free_hw(priv->hw);
}

#ifdef CONFIG_PM

C
Christoph Hellwig 已提交
6603
static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
Z
Zhu Yi 已提交
6604
{
6605
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
6606

6607 6608 6609 6610 6611
	if (priv->is_open) {
		set_bit(STATUS_IN_SUSPEND, &priv->status);
		iwl4965_mac_stop(priv->hw);
		priv->is_open = 1;
	}
Z
Zhu Yi 已提交
6612 6613 6614 6615 6616 6617

	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

C
Christoph Hellwig 已提交
6618
static int iwl4965_pci_resume(struct pci_dev *pdev)
Z
Zhu Yi 已提交
6619
{
6620
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
6621 6622 6623

	pci_set_power_state(pdev, PCI_D0);

6624 6625
	if (priv->is_open)
		iwl4965_mac_start(priv->hw);
Z
Zhu Yi 已提交
6626

6627
	clear_bit(STATUS_IN_SUSPEND, &priv->status);
Z
Zhu Yi 已提交
6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638
	return 0;
}

#endif /* CONFIG_PM */

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

6639 6640 6641 6642
/* Hardware specific file defines the PCI IDs table for that hardware module */
static struct pci_device_id iwl_hw_card_ids[] = {
	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
6643 6644 6645 6646 6647
#ifdef CONFIG_IWL5000
	{IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
	{IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
	{IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
#endif /* CONFIG_IWL5000 */
6648 6649 6650 6651 6652
	{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);

static struct pci_driver iwl_driver = {
Z
Zhu Yi 已提交
6653
	.name = DRV_NAME,
6654
	.id_table = iwl_hw_card_ids,
C
Christoph Hellwig 已提交
6655 6656
	.probe = iwl4965_pci_probe,
	.remove = __devexit_p(iwl4965_pci_remove),
Z
Zhu Yi 已提交
6657
#ifdef CONFIG_PM
C
Christoph Hellwig 已提交
6658 6659
	.suspend = iwl4965_pci_suspend,
	.resume = iwl4965_pci_resume,
Z
Zhu Yi 已提交
6660 6661 6662
#endif
};

C
Christoph Hellwig 已提交
6663
static int __init iwl4965_init(void)
Z
Zhu Yi 已提交
6664 6665 6666 6667 6668
{

	int ret;
	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
6669 6670 6671 6672 6673 6674 6675

	ret = iwl4965_rate_control_register();
	if (ret) {
		IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
		return ret;
	}

6676
	ret = pci_register_driver(&iwl_driver);
Z
Zhu Yi 已提交
6677 6678
	if (ret) {
		IWL_ERROR("Unable to initialize PCI module\n");
6679
		goto error_register;
Z
Zhu Yi 已提交
6680 6681 6682
	}

	return ret;
6683 6684 6685 6686

error_register:
	iwl4965_rate_control_unregister();
	return ret;
Z
Zhu Yi 已提交
6687 6688
}

C
Christoph Hellwig 已提交
6689
static void __exit iwl4965_exit(void)
Z
Zhu Yi 已提交
6690
{
6691
	pci_unregister_driver(&iwl_driver);
6692
	iwl4965_rate_control_unregister();
Z
Zhu Yi 已提交
6693 6694
}

C
Christoph Hellwig 已提交
6695 6696
module_exit(iwl4965_exit);
module_init(iwl4965_init);