iwl4965-base.c 189 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
/**
 * iwl4965_add_station_flags - Add station to tables in driver and device
 */
264
u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
265
				int is_ap, u8 flags, void *ht_data)
266
267
268
{
	int i;
	int index = IWL_INVALID_STATION;
269
	struct iwl_station_entry *station;
270
	unsigned long flags_spin;
271
	DECLARE_MAC_BUF(mac);
272
273
274
275
276

	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
277
		index = priv->hw_params.bcast_sta_id;
278
	else
Tomas Winkler's avatar
Tomas Winkler committed
279
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
280
281
282
283
284
285
286
287
288
289
290
291
			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;
		}


292
293
	/* These two conditions have the same outcome, but keep them separate
	  since they have different meanings */
294
295
296
297
298
299
300
301
302
303
304
305
	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;
	}


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

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

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

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

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

}



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

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

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

363
364
365
366
367
368
	/* 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));

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

374
	if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
375
376
377
378
379
380
		IWL_ERROR("No space for Tx\n");
		return -ENOSPC;
	}

	spin_lock_irqsave(&priv->hcmd_lock, flags);

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

	control_flags = (u32 *) tfd;

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

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

	txq->need_update = 1;
413
414

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

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

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

425
426
static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
Gregory Greenman's avatar
Gregory Greenman committed
427
	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
428
429
430
431
432
433
434
435

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

}

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

447
	/* Add station to device's station table */
448
449
450
451
452
453
454
455
456
457
458
459
460
#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);
461
462

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

465
	return sta_id;
466
467
468
}

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
469
 * iwl4965_check_rxon_cmd - validate RXON structure is valid
470
471
472
473
474
 *
 * 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
475
static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
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
533
534
{
	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
535
		IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
536
537
538
539
540
541
		return -1;
	}
	return 0;
}

/**
542
 * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
543
 * @priv: staging_rxon is compared to active_rxon
544
 *
545
546
547
 * 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.
548
 */
549
static int iwl4965_full_rxon_required(struct iwl_priv *priv)
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
588
589
{

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

604
	if (!iwl_is_alive(priv))
605
606
607
608
609
		return -1;

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

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

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

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

676
	iwlcore_clear_stations_table(priv);
677

678
679
680
	if (!priv->error_recovering)
		priv->start_calib = 0;

681
	iwl_init_sensitivity(priv);
682
683
684
685
686

	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
687
	rc = iwl4965_hw_reg_send_txpower(priv);
688
689
690
691
692
693
	if (rc) {
		IWL_ERROR("Error setting Tx power (%d).\n", rc);
		return rc;
	}

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

	return 0;
}

718
719
720
void iwl4965_update_chain_flags(struct iwl_priv *priv)
{

721
	iwl_set_rxon_chain(priv);
722
723
724
	iwl4965_commit_rxon(priv);
}

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

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

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

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

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

777
	return ret;
778
779
780
781
782
}

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

799
	return iwl_send_cmd(priv, &cmd);
800
801
}

802
static void iwl_clear_free_frames(struct iwl_priv *priv)
803
804
805
806
807
808
809
810
811
{
	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);
812
		kfree(list_entry(element, struct iwl_frame, list));
813
814
815
816
817
818
819
820
821
822
		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;
	}
}

823
static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
824
{
825
	struct iwl_frame *frame;
826
827
828
829
830
831
832
833
834
835
836
837
838
839
	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);
840
	return list_entry(element, struct iwl_frame, list);
841
842
}

843
static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
844
845
846
847
848
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

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

854
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
855
856
857
858
859
860
861
862
863
864
865
866
	    ((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
867
static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
868
{
Guy Cohen's avatar
Guy Cohen committed
869
870
871
872
873
874
875
876
	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;
877

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

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

892
static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
893
{
894
	struct iwl_frame *frame;
895
896
897
898
	unsigned int frame_size;
	int rc;
	u8 rate;

899
	frame = iwl_get_free_frame(priv);
900
901
902
903
904
905
906

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

Guy Cohen's avatar
Guy Cohen committed
907
	rate = iwl4965_rate_get_lowest_plcp(priv);
908

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

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

914
	iwl_free_frame(priv, frame);
915
916
917
918
919
920
921
922
923
924
925

	return rc;
}

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

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

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

	return ret_rates;
}

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