iwl4965-base.c 185 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 iwl_txq_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 iwl_queue_space(const struct iwl_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;
}


193
static inline int iwl_queue_used(const struct iwl_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
}

200
static inline u8 get_cmd_index(struct iwl_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 210 211
	return index & (q->n_window - 1);
}


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

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

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



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

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
266
 * iwl4965_enqueue_hcmd - enqueue a uCode command
267 268 269 270 271 272 273
 * @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.
 */
274
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
275
{
276
	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
277
	struct iwl_queue *q = &txq->q;
278
	struct iwl_tfd_frame *tfd;
279
	u32 *control_flags;
280
	struct iwl_cmd *out_cmd;
281
	u32 idx;
Gregory Greenman's avatar
Gregory Greenman committed
282
	u16 fix_size;
283 284 285 286
	dma_addr_t phys_addr;
	int ret;
	unsigned long flags;

Gregory Greenman's avatar
Gregory Greenman committed
287 288 289
	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));

290 291 292 293 294 295
	/* 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));

296
	if (iwl_is_rfkill(priv)) {
297 298 299 300
		IWL_DEBUG_INFO("Not sending command - RF KILL");
		return -EIO;
	}

301
	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
302 303 304 305 306 307
		IWL_ERROR("No space for Tx\n");
		return -ENOSPC;
	}

	spin_lock_irqsave(&priv->hcmd_lock, flags);

308
	tfd = &txq->bd[q->write_ptr];
309 310 311 312
	memset(tfd, 0, sizeof(*tfd));

	control_flags = (u32 *) tfd;

313
	idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
314 315 316 317 318 319 320 321 322 323 324
	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) |
325
			INDEX_TO_SEQ(q->write_ptr));
326 327 328 329
	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 +
330
			offsetof(struct iwl_cmd, hdr);
Christoph Hellwig's avatar
Christoph Hellwig committed
331
	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
332 333 334 335 336

	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),
337
		     fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
338 339

	txq->need_update = 1;
340 341

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

	/* Increment and update queue's write index */
345
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
346
	ret = iwl_txq_update_write_ptr(priv, txq);
347 348 349 350 351

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

352 353
static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
Gregory Greenman's avatar
Gregory Greenman committed
354
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
355 356 357 358 359 360 361 362

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

}

363
/**
Christoph Hellwig's avatar
Christoph Hellwig committed
364
 * iwl4965_check_rxon_cmd - validate RXON structure is valid
365 366 367 368 369
 *
 * 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
 */
Gregory Greenman's avatar
Gregory Greenman committed
370
static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
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 420 421 422 423 424 425 426 427 428 429
{
	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
430
		IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
431 432 433 434 435 436
		return -1;
	}
	return 0;
}

/**
437
 * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
438
 * @priv: staging_rxon is compared to active_rxon
439
 *
440 441 442
 * 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.
443
 */
444
static int iwl4965_full_rxon_required(struct iwl_priv *priv)
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 475 476 477 478 479 480 481 482 483 484
{

	/* 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
485
 * iwl4965_commit_rxon - commit staging_rxon to hardware
486
 *
487
 * The RXON command in staging_rxon is committed to the hardware and
488 489 490 491
 * 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.
 */
492
static int iwl4965_commit_rxon(struct iwl_priv *priv)
493 494
{
	/* cast away the const for active_rxon in this function */
Gregory Greenman's avatar
Gregory Greenman committed
495
	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
496
	DECLARE_MAC_BUF(mac);
497 498
	int rc = 0;

499
	if (!iwl_is_alive(priv))
500 501 502 503 504
		return -1;

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

Christoph Hellwig's avatar
Christoph Hellwig committed
505
	rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
506 507 508 509 510 511
	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
512
	 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
513
	 * and other flags for the current radio configuration. */
Christoph Hellwig's avatar
Christoph Hellwig committed
514
	if (!iwl4965_full_rxon_required(priv)) {
515
		rc = iwl_send_rxon_assoc(priv);
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
		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 */
534
	if (iwl_is_associated(priv) &&
535 536 537 538
	    (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;

539
		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
Gregory Greenman's avatar
Gregory Greenman committed
540
				      sizeof(struct iwl_rxon_cmd),
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
				      &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"
556
		       "* bssid = %s\n",
557 558 559
		       ((priv->staging_rxon.filter_flags &
			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
		       le16_to_cpu(priv->staging_rxon.channel),
560
		       print_mac(mac, priv->staging_rxon.bssid_addr));
561

562
	iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
563
	/* Apply the new configuration */
564
	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
Gregory Greenman's avatar
Gregory Greenman committed
565
			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
566 567 568 569 570
	if (rc) {
		IWL_ERROR("Error setting new configuration (%d).\n", rc);
		return rc;
	}

571
	iwlcore_clear_stations_table(priv);
572

573 574 575
	if (!priv->error_recovering)
		priv->start_calib = 0;

576
	iwl_init_sensitivity(priv);
577 578 579 580 581

	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
582
	rc = iwl4965_hw_reg_send_txpower(priv);
583 584 585 586 587 588
	if (rc) {
		IWL_ERROR("Error setting Tx power (%d).\n", rc);
		return rc;
	}

	/* Add the broadcast address so we can send broadcast frames */
589
	if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
590 591 592 593 594 595 596
	    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 */
597
	if (iwl_is_associated(priv) &&
598
	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
599
		if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
600 601 602 603 604
		    == IWL_INVALID_STATION) {
			IWL_ERROR("Error adding AP address for transmit.\n");
			return -EIO;
		}
		priv->assoc_station_added = 1;
605 606 607
		if (priv->default_wep_key &&
		    iwl_send_static_wepkey_cmd(priv, 0))
			IWL_ERROR("Could not send WEP static key.\n");
608 609 610 611 612
	}

	return 0;
}

613 614 615
void iwl4965_update_chain_flags(struct iwl_priv *priv)
{

616
	iwl_set_rxon_chain(priv);
617 618 619
	iwl4965_commit_rxon(priv);
}

620
static int iwl4965_send_bt_config(struct iwl_priv *priv)
621
{
Christoph Hellwig's avatar
Christoph Hellwig committed
622
	struct iwl4965_bt_cmd bt_cmd = {
623 624 625 626 627 628 629
		.flags = 3,
		.lead_time = 0xAA,
		.max_kill = 1,
		.kill_ack_mask = 0,
		.kill_cts_mask = 0,
	};

630
	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
Christoph Hellwig's avatar
Christoph Hellwig committed
631
				sizeof(struct iwl4965_bt_cmd), &bt_cmd);
632 633
}

634
static int iwl4965_send_scan_abort(struct iwl_priv *priv)
635
{
636 637
	int ret = 0;
	struct iwl_rx_packet *res;
638
	struct iwl_host_cmd cmd = {
639 640 641 642 643 644 645 646 647 648 649 650
		.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;
	}

651 652
	ret = iwl_send_cmd_sync(priv, &cmd);
	if (ret) {
653
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
654
		return ret;
655 656
	}

657
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
658 659 660 661 662 663 664 665 666 667 668 669 670 671
	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);

672
	return ret;
673 674 675 676 677
}

/*
 * CARD_STATE_CMD
 *
678
 * Use: Sets the device's internal card state to enable, disable, or halt
679 680 681 682 683 684
 *
 * 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.
 */
685
static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
686
{
687
	struct iwl_host_cmd cmd = {
688 689 690 691 692 693
		.id = REPLY_CARD_STATE_CMD,
		.len = sizeof(u32),
		.data = &flags,
		.meta.flags = meta_flag,
	};

694
	return iwl_send_cmd(priv, &cmd);
695 696
}

697
static void iwl_clear_free_frames(struct iwl_priv *priv)
698 699 700 701 702 703 704 705 706
{
	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);
707
		kfree(list_entry(element, struct iwl_frame, list));
708 709 710 711 712 713 714 715 716 717
		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;
	}
}

718
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
719
{
720
	struct iwl_frame *frame;
721 722 723 724 725 726 727 728 729 730 731 732 733 734
	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);
735
	return list_entry(element, struct iwl_frame, list);
736 737
}

738
static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
739 740 741 742 743
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

744
unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
745 746 747 748
				struct ieee80211_hdr *hdr,
				const u8 *dest, int left)
{

749
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
750 751 752 753 754 755 756 757 758 759 760 761
	    ((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
762
static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
763
{
Guy Cohen's avatar
Guy Cohen committed
764 765 766 767 768 769 770 771
	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;
772

Guy Cohen's avatar
Guy Cohen committed
773
	/* Find lowest valid rate */
774
	for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
775
					i = iwl_rates[i].next_ieee) {
776
		if (rate_mask & (1 << i))
777
			return iwl_rates[i].plcp;
778 779
	}

Guy Cohen's avatar
Guy Cohen committed
780 781 782 783 784
	/* 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;
785 786
}

787
static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
788
{
789
	struct iwl_frame *frame;
790 791 792 793
	unsigned int frame_size;
	int rc;
	u8 rate;

794
	frame = iwl_get_free_frame(priv);
795 796 797 798 799 800 801

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

Guy Cohen's avatar
Guy Cohen committed
802
	rate = iwl4965_rate_get_lowest_plcp(priv);
803

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

806
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
807 808
			      &frame->u.cmd[0]);

809
	iwl_free_frame(priv, frame);
810 811 812 813 814 815 816 817 818 819 820

	return rc;
}

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

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
821
 * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
822 823 824
 *
 * return : set the bit for each supported rate insert in ie
 */
Christoph Hellwig's avatar
Christoph Hellwig committed
825
static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
826
				    u16 basic_rate, int *left)
827 828 829
{
	u16 ret_rates = 0, bit;
	int i;
830 831
	u8 *cnt = ie;
	u8 *rates = ie + 1;
832 833 834 835

	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
		if (bit & supported_rate) {
			ret_rates |= bit;
836
			rates[*cnt] = iwl_rates[i].ieee |
837 838 839 840 841
				((bit & basic_rate) ? 0x80 : 0x00);
			(*cnt)++;
			(*left)--;
			if ((*left <= 0) ||
			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
842 843 844 845 846 847 848
				break;
		}
	}

	return ret_rates;
}

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 924 925 926 927 928 929 930 931 932 933
#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


934
/**
Christoph Hellwig's avatar
Christoph Hellwig committed
935
 * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
936
 */
937
static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
938 939 940
				  enum ieee80211_band band,
				  struct ieee80211_mgmt *frame,
				  int left, int is_direct)
941 942 943
{
	int len = 0;
	u8 *pos = NULL;
944
	u16 active_rates, ret_rates, cck_rates, active_rate_basic;
945
	const struct ieee80211_supported_band *sband =
946
						iwl_get_hw_mode(priv, band);
947 948 949 950 951 952 953 954 955

	/* 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);
956
	memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
957
	memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
958
	memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
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
	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;
991

992 993 994
	/* ... fill it in... */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos = 0;
995

996 997 998 999 1000
	/* exclude 60M rate */
	active_rates = priv->rates_mask;
	active_rates &= ~IWL_RATE_60M_MASK;

	active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
1001

1002
	cck_rates = IWL_CCK_RATES_MASK & active_rates;
Christoph Hellwig's avatar
Christoph Hellwig committed
1003
	ret_rates = iwl4965_supported_rate_to_ie(pos, cck_rates,
1004
			active_rate_basic, &left);
1005 1006
	active_rates &= ~ret_rates;

Christoph Hellwig's avatar
Christoph Hellwig committed
1007
	ret_rates = iwl4965_supported_rate_to_ie(pos, active_rates,
1008
				 active_rate_basic, &left);
1009 1010
	active_rates &= ~ret_rates;

1011 1012
	len += 2 + *pos;
	pos += (*pos) + 1;
1013
	if (active_rates == 0)
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
		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;
Christoph Hellwig's avatar
Christoph Hellwig committed
1024
	iwl4965_supported_rate_to_ie(pos, active_rates,
1025
				 active_rate_basic, &left);
1026 1027 1028 1029
	if (*pos > 0)
		len += 2 + *pos;

 fill_end:
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	/* 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;
1042 1043 1044 1045 1046 1047
	return (u16)len;
}

/*
 * QoS  support
*/
1048
static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
Christoph Hellwig's avatar
Christoph Hellwig committed
1049
				       struct iwl4965_qosparam_cmd *qos)
1050 1051
{

1052
	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
Christoph Hellwig's avatar
Christoph Hellwig committed
1053
				sizeof(struct iwl4965_qosparam_cmd), qos);
1054 1055
}

1056
static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
{
	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;

1077
#ifdef CONFIG_IWL4965_HT
1078
	if (priv->current_ht_config.is_ht)
1079
		priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
1080
#endif /* CONFIG_IWL4965_HT */
1081

1082 1083
	spin_unlock_irqrestore(&priv->lock, flags);

1084
	if (force || iwl_is_associated(priv)) {
1085 1086 1087
		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);
1088

Christoph Hellwig's avatar
Christoph Hellwig committed
1089
		iwl4965_send_qos_params_command(priv,
1090 1091 1092 1093
				&(priv->qos_data.def_qos_parm));
	}
}

1094
int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114