iwl4965-base.c 190 KB
Newer Older
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
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>

48
#include "iwl-eeprom.h"
49
#include "iwl-dev.h"
50
#include "iwl-core.h"
51
#include "iwl-io.h"
52
#include "iwl-helpers.h"
53
#include "iwl-sta.h"
54
#include "iwl-calib.h"
55

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

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
73 74 75 76 77
#define VD "d"
#else
#define VD
#endif

78
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
79 80 81 82 83
#define VS "s"
#else
#define VS
#endif

Tomas Winkler's avatar
Tomas Winkler committed
84
#define DRV_VERSION     IWLWIFI_VERSION VD VS
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101


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

__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
{
	u16 fc = le16_to_cpu(hdr->frame_control);
	int hdr_len = ieee80211_get_hdrlen(fc);

	if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA))
		return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN);
	return NULL;
}

102
static const struct ieee80211_supported_band *iwl_get_hw_mode(
103
		struct iwl_priv *priv, enum ieee80211_band band)
104
{
105
	return priv->hw->wiphy->bands[band];
106 107
}

Christoph Hellwig's avatar
Christoph Hellwig committed
108
static int iwl4965_is_empty_essid(const char *essid, int essid_len)
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
{
	/* 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;
}

Christoph Hellwig's avatar
Christoph Hellwig committed
124
static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
125 126 127 128 129
{
	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
	const char *s = essid;
	char *d = escaped;

Christoph Hellwig's avatar
Christoph Hellwig committed
130
	if (iwl4965_is_empty_essid(essid, essid_len)) {
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
		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;
}

148

149 150 151 152 153
/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
 * DMA services
 *
 * Theory of operation
 *
154 155 156 157 158 159 160 161 162
 * 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.
163 164 165 166 167 168
 *
 * 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.
 *
169 170 171
 * 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.
172 173
 *
 * See more detailed info in iwl-4965-hw.h.
174 175
 ***************************************************/

176
int iwl4965_queue_space(const struct iwl4965_queue *q)
177
{
178
	int s = q->read_ptr - q->write_ptr;
179

180
	if (q->read_ptr > q->write_ptr)
181 182 183 184 185 186 187 188 189 190 191 192
		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;
}


Christoph Hellwig's avatar
Christoph Hellwig committed
193
static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
194
{
195 196 197
	return q->write_ptr > q->read_ptr ?
		(i >= q->read_ptr && i < q->write_ptr) :
		!(i < q->read_ptr && i >= q->write_ptr);
198 199
}

Christoph Hellwig's avatar
Christoph Hellwig committed
200
static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
201
{
202
	/* This is for scan command, the big buffer at end of command array */
203
	if (is_huge)
204
		return q->n_window;	/* must be power of 2 */
205

206
	/* Otherwise, use normal size buffers */
207 208 209
	return index & (q->n_window - 1);
}

Christoph Hellwig's avatar
Christoph Hellwig committed
210
const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
211 212

/*************** STATION TABLE MANAGEMENT ****
213
 * mac80211 should be examined to determine if sta_info is duplicating
214 215 216 217 218
 * the functionality provided here
 */

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

219
#if 0 /* temporary disable till we add real remove station */
220 221 222 223 224
/**
 * iwl4965_remove_station - Remove driver's knowledge of station.
 *
 * NOTE:  This does not remove station from device's station table.
 */
225
static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
226 227 228 229 230 231 232 233 234 235
{
	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))
Tomas Winkler's avatar
Tomas Winkler committed
236
		index = priv->hw_params.bcast_sta_id;
237
	else
Tomas Winkler's avatar
Tomas Winkler committed
238
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
			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;
}
260
#endif
261

262 263 264
/**
 * iwl4965_add_station_flags - Add station to tables in driver and device
 */
265
u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
266
				int is_ap, u8 flags, void *ht_data)
267 268 269
{
	int i;
	int index = IWL_INVALID_STATION;
270
	struct iwl_station_entry *station;
271
	unsigned long flags_spin;
272
	DECLARE_MAC_BUF(mac);
273 274 275 276 277

	spin_lock_irqsave(&priv->sta_lock, flags_spin);
	if (is_ap)
		index = IWL_AP_ID;
	else if (is_broadcast_ether_addr(addr))
Tomas Winkler's avatar
Tomas Winkler committed
278
		index = priv->hw_params.bcast_sta_id;
279
	else
Tomas Winkler's avatar
Tomas Winkler committed
280
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
281 282 283 284 285 286 287 288 289 290 291 292
			if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
						addr)) {
				index = i;
				break;
			}

			if (!priv->stations[i].used &&
			    index == IWL_INVALID_STATION)
				index = i;
		}


293 294
	/* These two conditions have the same outcome, but keep them separate
	  since they have different meanings */
295 296 297 298 299 300 301 302 303 304 305 306
	if (unlikely(index == IWL_INVALID_STATION)) {
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return index;
	}

	if (priv->stations[index].used &&
	    !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return index;
	}


307
	IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
308 309 310 311
	station = &priv->stations[index];
	station->used = 1;
	priv->num_stations++;

312
	/* Set up the REPLY_ADD_STA command to send to device */
313
	memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
314 315 316 317 318
	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
	station->sta.mode = 0;
	station->sta.sta.sta_id = index;
	station->sta.station_flags = 0;

319
#ifdef CONFIG_IWL4965_HT
320
	/* BCAST station and IBSS stations do not work in HT mode */
Tomas Winkler's avatar
Tomas Winkler committed
321
	if (index != priv->hw_params.bcast_sta_id &&
322
	    priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
323 324
		iwl4965_set_ht_add_station(priv, index,
				 (struct ieee80211_ht_info *) ht_data);
325
#endif /*CONFIG_IWL4965_HT*/
326 327

	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
328 329

	/* Add station to device's station table */
330
	iwl_send_add_sta(priv, &station->sta, flags);
331 332 333 334 335 336 337 338 339
	return index;

}



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

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
340
 * iwl4965_enqueue_hcmd - enqueue a uCode command
341 342 343 344 345 346 347
 * @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.
 */
348
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
349
{
350
	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
Christoph Hellwig's avatar
Christoph Hellwig committed
351
	struct iwl4965_queue *q = &txq->q;
352
	struct iwl_tfd_frame *tfd;
353
	u32 *control_flags;
354
	struct iwl_cmd *out_cmd;
355 356 357 358 359 360 361 362 363 364 365 366
	u32 idx;
	u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
	dma_addr_t phys_addr;
	int ret;
	unsigned long flags;

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

367
	if (iwl_is_rfkill(priv)) {
368 369 370 371
		IWL_DEBUG_INFO("Not sending command - RF KILL");
		return -EIO;
	}

Christoph Hellwig's avatar
Christoph Hellwig committed
372
	if (iwl4965_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
373 374 375 376 377 378
		IWL_ERROR("No space for Tx\n");
		return -ENOSPC;
	}

	spin_lock_irqsave(&priv->hcmd_lock, flags);

379
	tfd = &txq->bd[q->write_ptr];
380 381 382 383
	memset(tfd, 0, sizeof(*tfd));

	control_flags = (u32 *) tfd;

384
	idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
385 386 387 388 389 390 391 392 393 394 395
	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) |
396
			INDEX_TO_SEQ(q->write_ptr));
397 398 399 400
	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 +
401
			offsetof(struct iwl_cmd, hdr);
Christoph Hellwig's avatar
Christoph Hellwig committed
402
	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
403 404 405 406 407

	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),
408
		     fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
409 410

	txq->need_update = 1;
411 412

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

	/* Increment and update queue's write index */
416
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
417
	ret = iwl4965_tx_queue_update_write_ptr(priv, txq);
418 419 420 421 422

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

423 424 425 426 427 428 429 430 431 432 433
static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
	struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;

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

}

434
/**
Christoph Hellwig's avatar
Christoph Hellwig committed
435
 * iwl4965_rxon_add_station - add station into station table.
436 437
 *
 * there is only one AP station with id= IWL_AP_ID
438 439
 * NOTE: mutex must be held before calling this fnction
 */
440
static int iwl4965_rxon_add_station(struct iwl_priv *priv,
441 442
				const u8 *addr, int is_ap)
{
443
	u8 sta_id;
444

445
	/* Add station to device's station table */
446 447 448 449 450 451 452 453 454 455 456 457 458
#ifdef CONFIG_IWL4965_HT
	struct ieee80211_conf *conf = &priv->hw->conf;
	struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;

	if ((is_ap) &&
	    (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
	    (priv->iw_mode == IEEE80211_IF_TYPE_STA))
		sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
						   0, cur_ht_config);
	else
#endif /* CONFIG_IWL4965_HT */
		sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
						   0, NULL);
459 460

	/* Set up default rate scaling table in device's station table */
461 462
	iwl4965_add_station(priv, addr, is_ap);

463
	return sta_id;
464 465 466
}

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
467
 * iwl4965_check_rxon_cmd - validate RXON structure is valid
468 469 470 471 472
 *
 * 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
 */
Christoph Hellwig's avatar
Christoph Hellwig committed
473
static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon)
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
{
	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) {
Christoph Hellwig's avatar
Christoph Hellwig committed
533
		IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
534 535 536 537 538 539
		return -1;
	}
	return 0;
}

/**
540
 * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
541
 * @priv: staging_rxon is compared to active_rxon
542
 *
543 544 545
 * 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.
546
 */
547
static int iwl4965_full_rxon_required(struct iwl_priv *priv)
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
{

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

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
588
 * iwl4965_commit_rxon - commit staging_rxon to hardware
589
 *
590
 * The RXON command in staging_rxon is committed to the hardware and
591 592 593 594
 * 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.
 */
595
static int iwl4965_commit_rxon(struct iwl_priv *priv)
596 597
{
	/* cast away the const for active_rxon in this function */
Christoph Hellwig's avatar
Christoph Hellwig committed
598
	struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
599
	DECLARE_MAC_BUF(mac);
600 601
	int rc = 0;

602
	if (!iwl_is_alive(priv))
603 604 605 606 607
		return -1;

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

Christoph Hellwig's avatar
Christoph Hellwig committed
608
	rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
609 610 611 612 613 614
	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
Christoph Hellwig's avatar
Christoph Hellwig committed
615
	 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
616
	 * and other flags for the current radio configuration. */
Christoph Hellwig's avatar
Christoph Hellwig committed
617
	if (!iwl4965_full_rxon_required(priv)) {
618
		rc = iwl_send_rxon_assoc(priv);
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
		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 */
637
	if (iwl_is_associated(priv) &&
638 639 640 641
	    (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;

642
		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
Christoph Hellwig's avatar
Christoph Hellwig committed
643
				      sizeof(struct iwl4965_rxon_cmd),
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
				      &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"
659
		       "* bssid = %s\n",
660 661 662
		       ((priv->staging_rxon.filter_flags &
			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
		       le16_to_cpu(priv->staging_rxon.channel),
663
		       print_mac(mac, priv->staging_rxon.bssid_addr));
664

665
	iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
666
	/* Apply the new configuration */
667
	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
Christoph Hellwig's avatar
Christoph Hellwig committed
668
			      sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
669 670 671 672 673
	if (rc) {
		IWL_ERROR("Error setting new configuration (%d).\n", rc);
		return rc;
	}

674
	iwlcore_clear_stations_table(priv);
675

676 677 678
	if (!priv->error_recovering)
		priv->start_calib = 0;

679
	iwl_init_sensitivity(priv);
680 681 682 683 684

	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 */
Christoph Hellwig's avatar
Christoph Hellwig committed
685
	rc = iwl4965_hw_reg_send_txpower(priv);
686 687 688 689 690 691
	if (rc) {
		IWL_ERROR("Error setting Tx power (%d).\n", rc);
		return rc;
	}

	/* Add the broadcast address so we can send broadcast frames */
Christoph Hellwig's avatar
Christoph Hellwig committed
692
	if (iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0) ==
693 694 695 696 697 698 699
	    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 */
700
	if (iwl_is_associated(priv) &&
701
	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
Christoph Hellwig's avatar
Christoph Hellwig committed
702
		if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
703 704 705 706 707
		    == IWL_INVALID_STATION) {
			IWL_ERROR("Error adding AP address for transmit.\n");
			return -EIO;
		}
		priv->assoc_station_added = 1;
708 709 710
		if (priv->default_wep_key &&
		    iwl_send_static_wepkey_cmd(priv, 0))
			IWL_ERROR("Could not send WEP static key.\n");
711 712 713 714 715
	}

	return 0;
}

716 717 718
void iwl4965_update_chain_flags(struct iwl_priv *priv)
{

719
	iwl_set_rxon_chain(priv);
720 721 722
	iwl4965_commit_rxon(priv);
}

723
static int iwl4965_send_bt_config(struct iwl_priv *priv)
724
{
Christoph Hellwig's avatar
Christoph Hellwig committed
725
	struct iwl4965_bt_cmd bt_cmd = {
726 727 728 729 730 731 732
		.flags = 3,
		.lead_time = 0xAA,
		.max_kill = 1,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

733
	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
Christoph Hellwig's avatar
Christoph Hellwig committed
734
				sizeof(struct iwl4965_bt_cmd), &bt_cmd);
735 736
}

737
static int iwl4965_send_scan_abort(struct iwl_priv *priv)
738
{
739 740
	int ret = 0;
	struct iwl_rx_packet *res;
741
	struct iwl_host_cmd cmd = {
742 743 744 745 746 747 748 749 750 751 752 753
		.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;
	}

754 755
	ret = iwl_send_cmd_sync(priv, &cmd);
	if (ret) {
756
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
757
		return ret;
758 759
	}

760
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
761 762 763 764 765 766 767 768 769 770 771 772 773 774
	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);

775
	return ret;
776 777 778 779 780
}

/*
 * CARD_STATE_CMD
 *
781
 * Use: Sets the device's internal card state to enable, disable, or halt
782 783 784 785 786 787
 *
 * 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.
 */
788
static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
789
{
790
	struct iwl_host_cmd cmd = {
791 792 793 794 795 796
		.id = REPLY_CARD_STATE_CMD,
		.len = sizeof(u32),
		.data = &flags,
		.meta.flags = meta_flag,
	};

797
	return iwl_send_cmd(priv, &cmd);
798 799
}

800
static void iwl4965_clear_free_frames(struct iwl_priv *priv)
801 802 803 804 805 806 807 808 809
{
	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);
Christoph Hellwig's avatar
Christoph Hellwig committed
810
		kfree(list_entry(element, struct iwl4965_frame, list));
811 812 813 814 815 816 817 818 819 820
		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;
	}
}

821
static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
822
{
Christoph Hellwig's avatar
Christoph Hellwig committed
823
	struct iwl4965_frame *frame;
824 825 826 827 828 829 830 831 832 833 834 835 836 837
	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);
Christoph Hellwig's avatar
Christoph Hellwig committed
838
	return list_entry(element, struct iwl4965_frame, list);
839 840
}

841
static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame)
842 843 844 845 846
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

847
unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
848 849 850 851
				struct ieee80211_hdr *hdr,
				const u8 *dest, int left)
{

852
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
853 854 855 856 857 858 859 860 861 862 863 864
	    ((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;
}

Guy Cohen's avatar
Guy Cohen committed
865
static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
866
{
Guy Cohen's avatar
Guy Cohen committed
867 868 869 870 871 872 873 874
	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;
875

Guy Cohen's avatar
Guy Cohen committed
876
	/* Find lowest valid rate */
877
	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
Guy Cohen's avatar
Guy Cohen committed
878
					i = iwl4965_rates[i].next_ieee) {
879
		if (rate_mask & (1 << i))
Christoph Hellwig's avatar
Christoph Hellwig committed
880
			return iwl4965_rates[i].plcp;
881 882
	}

Guy Cohen's avatar
Guy Cohen committed
883 884 885 886 887
	/* 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;
888 889
}

890
static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
891
{
Christoph Hellwig's avatar
Christoph Hellwig committed
892
	struct iwl4965_frame *frame;
893 894 895 896
	unsigned int frame_size;
	int rc;
	u8 rate;

Christoph Hellwig's avatar
Christoph Hellwig committed
897
	frame = iwl4965_get_free_frame(priv);
898 899 900 901 902 903 904

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

Guy Cohen's avatar
Guy Cohen committed
905
	rate = iwl4965_rate_get_lowest_plcp(priv);
906

Christoph Hellwig's avatar
Christoph Hellwig committed
907
	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
908

909
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
910 911
			      &frame->u.cmd[0]);

Christoph Hellwig's avatar
Christoph Hellwig committed
912
	iwl4965_free_frame(priv, frame);
913 914 915 916 917 918 919 920 921 922 923

	return rc;
}

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

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
924
 * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
925 926 927
 *
 * return : set the bit for each supported rate insert in ie
 */
Christoph Hellwig's avatar
Christoph Hellwig committed
928
static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
929
				    u16 basic_rate, int *left)
930 931 932
{
	u16 ret_rates = 0, bit;
	int i;
933 934
	u8 *cnt = ie;
	u8 *rates = ie + 1;
935 936 937 938

	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
		if (bit & supported_rate) {
			ret_rates |= bit;
Christoph Hellwig's avatar
Christoph Hellwig committed
939
			rates[*cnt] = iwl4965_rates[i].ieee |
940 941 942 943 944
				((bit & basic_rate) ? 0x80 : 0x00);
			(*cnt)++;
			(*left)--;
			if ((*left <= 0) ||
			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
945 946 947 948 949 950 951
				break;
		}
	}

	return ret_rates;
}

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 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
#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


1037
/**
Christoph Hellwig's avatar
Christoph Hellwig committed
1038
 * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
1039
 */
1040
static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
1041 1042 1043
				  enum ieee80211_band band,
				  struct ieee80211_mgmt *frame,
				  int left, int is_direct)
1044 1045 1046
{
	int len = 0;
	u8 *pos = NULL;
1047
	u16 active_rates, ret_rates, cck_rates, active_rate_basic;
1048
	const struct ieee80211_supported_band *sband =
1049
						iwl_get_hw_mode(priv, band);
1050 1051 1052 1053 1054 1055 1056 1057 1058

	/* 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);
Christoph Hellwig's avatar
Christoph Hellwig committed
1059
	memcpy(frame->da, iwl4965_broadcast_addr, ETH_ALEN);
1060
	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
Christoph Hellwig's avatar
Christoph Hellwig committed
1061
	memcpy(frame->bssid, iwl4965_broadcast_addr, ETH_ALEN);
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
	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;
1094

1095 1096 1097
	/* ... fill it in... */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos = 0;
1098

1099 1100 1101 1102 1103
	/* exclude 60M rate */
	active_rates = priv->rates_mask;
	active_rates &= ~IWL_RATE_60M_MASK;