iwl3945-base.c 118 KB
Newer Older
1
2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2009 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
 *
 * Portions of this file are derived from the ipw3945 project, as well
 * as portions of the ieee80211 subsystem header files.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

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

#include <net/ieee80211_radiotap.h>
44
#include <net/lib80211.h>
45
46
47
48
#include <net/mac80211.h>

#include <asm/div64.h>

49
50
#define DRV_NAME	"iwl3945"

Winkler, Tomas's avatar
Winkler, Tomas committed
51
52
#include "iwl-fh.h"
#include "iwl-3945-fh.h"
53
#include "iwl-commands.h"
54
#include "iwl-sta.h"
55
56
#include "iwl-3945.h"
#include "iwl-helpers.h"
57
#include "iwl-core.h"
58
#include "iwl-dev.h"
59
60
61
62
63
64
65
66

/*
 * module name, copyright, version, etc.
 */

#define DRV_DESCRIPTION	\
"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"

Samuel Ortiz's avatar
Samuel Ortiz committed
67
#ifdef CONFIG_IWLWIFI_DEBUG
68
69
70
71
72
#define VD "d"
#else
#define VD
#endif

73
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
74
75
76
77
78
#define VS "s"
#else
#define VS
#endif

79
#define IWL39_VERSION "1.2.26k" VD VS
80
#define DRV_COPYRIGHT	"Copyright(c) 2003-2009 Intel Corporation"
81
#define DRV_AUTHOR     "<ilw@linux.intel.com>"
82
#define DRV_VERSION     IWL39_VERSION
83
84
85
86


MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
87
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
88
89
MODULE_LICENSE("GPL");

90
91
 /* module parameters */
struct iwl_mod_params iwl3945_mod_params = {
92
	.num_of_queues = IWL39_NUM_QUEUES, /* Not used */
93
	.sw_crypto = 1,
94
	.restart_fw = 1,
95
96
97
	/* the rest are 0 by default */
};

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * iwl3945_get_antenna_flags - Get antenna flags for RXON command
 * @priv: eeprom and antenna fields are used to determine antenna flags
 *
 * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
 * iwl3945_mod_params.antenna specifies the antenna diversity mode:
 *
 * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
 * IWL_ANTENNA_MAIN      - Force MAIN antenna
 * IWL_ANTENNA_AUX       - Force AUX antenna
 */
__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
{
	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;

	switch (iwl3945_mod_params.antenna) {
	case IWL_ANTENNA_DIVERSITY:
		return 0;

	case IWL_ANTENNA_MAIN:
		if (eeprom->antenna_switch_type)
			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;

	case IWL_ANTENNA_AUX:
		if (eeprom->antenna_switch_type)
			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
	}

	/* bad antenna selector value */
	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
		iwl3945_mod_params.antenna);

	return 0;		/* "diversity" is default if error */
}

135
static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
136
137
138
139
140
				   struct ieee80211_key_conf *keyconf,
				   u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
141
142
143
144
145
146
147
148
149
150
151
	int ret;

	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);

	if (sta_id == priv->hw_params.bcast_sta_id)
		key_flags |= STA_KEY_MULTICAST_MSK;

	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
	keyconf->hw_key_idx = keyconf->keyidx;
	key_flags &= ~STA_KEY_FLG_INVALID;
152
153

	spin_lock_irqsave(&priv->sta_lock, flags);
154
155
156
	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
157
158
	       keyconf->keylen);

159
	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
160
	       keyconf->keylen);
161

162
	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
163
			== STA_KEY_FLG_NO_ENC)
164
		priv->stations[sta_id].sta.key.key_offset =
165
166
167
168
				 iwl_get_free_ucode_key_index(priv);
	/* else, we are overriding an existing key => no need to allocated room
	* in uCode. */

169
	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
170
171
		"no space for a new key");

172
173
174
	priv->stations[sta_id].sta.key.key_flags = key_flags;
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
175

176
177
	IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");

178
	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
179

180
181
	spin_unlock_irqrestore(&priv->sta_lock, flags);

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	return ret;
}

static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
				  struct ieee80211_key_conf *keyconf,
				  u8 sta_id)
{
	return -EOPNOTSUPP;
}

static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
				  struct ieee80211_key_conf *keyconf,
				  u8 sta_id)
{
	return -EOPNOTSUPP;
197
198
}

199
static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
200
201
202
203
{
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);
204
205
	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
	memset(&priv->stations[sta_id].sta.key, 0,
206
		sizeof(struct iwl4965_keyinfo));
207
208
209
	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
210
211
	spin_unlock_irqrestore(&priv->sta_lock, flags);

212
	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
213
	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
214
215
216
	return 0;
}

Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
217
static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
			struct ieee80211_key_conf *keyconf, u8 sta_id)
{
	int ret = 0;

	keyconf->hw_key_idx = HW_KEY_DYNAMIC;

	switch (keyconf->alg) {
	case ALG_CCMP:
		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
		break;
	case ALG_TKIP:
		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
		break;
	case ALG_WEP:
		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
		break;
	default:
235
		IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
		ret = -EINVAL;
	}

	IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
		      keyconf->alg, keyconf->keylen, keyconf->keyidx,
		      sta_id, ret);

	return ret;
}

static int iwl3945_remove_static_key(struct iwl_priv *priv)
{
	int ret = -EOPNOTSUPP;

	return ret;
}

static int iwl3945_set_static_key(struct iwl_priv *priv,
				struct ieee80211_key_conf *key)
{
	if (key->alg == ALG_WEP)
		return -EOPNOTSUPP;

	IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg);
	return -EINVAL;
}

263
static void iwl3945_clear_free_frames(struct iwl_priv *priv)
264
265
266
{
	struct list_head *element;

267
	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
268
269
270
271
272
		       priv->frames_count);

	while (!list_empty(&priv->free_frames)) {
		element = priv->free_frames.next;
		list_del(element);
Christoph Hellwig's avatar
Christoph Hellwig committed
273
		kfree(list_entry(element, struct iwl3945_frame, list));
274
275
276
277
		priv->frames_count--;
	}

	if (priv->frames_count) {
278
		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
279
280
281
282
283
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

284
static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
285
{
Christoph Hellwig's avatar
Christoph Hellwig committed
286
	struct iwl3945_frame *frame;
287
288
289
290
	struct list_head *element;
	if (list_empty(&priv->free_frames)) {
		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
		if (!frame) {
291
			IWL_ERR(priv, "Could not allocate frame!\n");
292
293
294
295
296
297
298
299
300
			return NULL;
		}

		priv->frames_count++;
		return frame;
	}

	element = priv->free_frames.next;
	list_del(element);
Christoph Hellwig's avatar
Christoph Hellwig committed
301
	return list_entry(element, struct iwl3945_frame, list);
302
303
}

304
static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
305
306
307
308
309
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

310
unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
311
				struct ieee80211_hdr *hdr,
312
				int left)
313
314
{

315
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
316
317
	    ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
	     (priv->iw_mode != NL80211_IFTYPE_AP)))
318
319
320
321
322
323
324
325
326
327
		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;
}

328
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
329
{
Christoph Hellwig's avatar
Christoph Hellwig committed
330
	struct iwl3945_frame *frame;
331
332
333
334
	unsigned int frame_size;
	int rc;
	u8 rate;

Christoph Hellwig's avatar
Christoph Hellwig committed
335
	frame = iwl3945_get_free_frame(priv);
336
337

	if (!frame) {
338
		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
339
340
341
342
			  "command.\n");
		return -ENOMEM;
	}

343
	rate = iwl_rate_get_lowest_plcp(priv);
344

Christoph Hellwig's avatar
Christoph Hellwig committed
345
	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
346

347
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
348
349
			      &frame->u.cmd[0]);

Christoph Hellwig's avatar
Christoph Hellwig committed
350
	iwl3945_free_frame(priv, frame);
351
352
353
354

	return rc;
}

355
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
356
{
357
	if (priv->shared_virt)
358
		pci_free_consistent(priv->pci_dev,
Christoph Hellwig's avatar
Christoph Hellwig committed
359
				    sizeof(struct iwl3945_shared),
360
361
				    priv->shared_virt,
				    priv->shared_phys);
362
363
}

364
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
365
				      struct ieee80211_tx_info *info,
366
				      struct iwl_cmd *cmd,
367
				      struct sk_buff *skb_frag,
368
				      int sta_id)
369
{
370
	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
371
	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
372
373
374

	switch (keyinfo->alg) {
	case ALG_CCMP:
375
376
		tx->sec_ctl = TX_CMD_SEC_CCM;
		memcpy(tx->key, keyinfo->key, keyinfo->keylen);
377
		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
378
379
380
381
382
383
		break;

	case ALG_TKIP:
		break;

	case ALG_WEP:
384
		tx->sec_ctl = TX_CMD_SEC_WEP |
385
		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
386
387

		if (keyinfo->keylen == 13)
388
			tx->sec_ctl |= TX_CMD_SEC_KEY128;
389

390
		memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen);
391

392
		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
393
			     "with key %d\n", info->control.hw_key->hw_key_idx);
394
395
396
		break;

	default:
Tomas Winkler's avatar
Tomas Winkler committed
397
		IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
398
399
400
401
402
403
404
		break;
	}
}

/*
 * handle build REPLY_TX command notification.
 */
405
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
406
				  struct iwl_cmd *cmd,
407
				  struct ieee80211_tx_info *info,
408
				  struct ieee80211_hdr *hdr, u8 std_id)
409
{
410
411
	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
	__le32 tx_flags = tx->tx_flags;
412
	__le16 fc = hdr->frame_control;
413
	u8 rc_flags = info->control.rates[0].flags;
414

415
	tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
416
	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
417
		tx_flags |= TX_CMD_FLG_ACK_MSK;
418
		if (ieee80211_is_mgmt(fc))
419
			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
420
		if (ieee80211_is_probe_resp(fc) &&
421
422
423
424
425
426
427
		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
			tx_flags |= TX_CMD_FLG_TSF_MSK;
	} else {
		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
	}

428
	tx->sta_id = std_id;
429
	if (ieee80211_has_morefrags(fc))
430
431
		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

432
433
	if (ieee80211_is_data_qos(fc)) {
		u8 *qc = ieee80211_get_qos_ctl(hdr);
434
		tx->tid_tspec = qc[0] & 0xf;
435
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
436
	} else {
437
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
438
	}
439

440
	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
441
442
		tx_flags |= TX_CMD_FLG_RTS_MSK;
		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
443
	} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
444
445
446
447
448
449
450
451
		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
		tx_flags |= TX_CMD_FLG_CTS_MSK;
	}

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

	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
452
453
	if (ieee80211_is_mgmt(fc)) {
		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
454
			tx->timeout.pm_frame_timeout = cpu_to_le16(3);
455
		else
456
			tx->timeout.pm_frame_timeout = cpu_to_le16(2);
Mohamed Abbas's avatar
Mohamed Abbas committed
457
	} else {
458
		tx->timeout.pm_frame_timeout = 0;
459
#ifdef CONFIG_IWLWIFI_LEDS
Mohamed Abbas's avatar
Mohamed Abbas committed
460
461
462
		priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
#endif
	}
463

464
465
466
	tx->driver_txop = 0;
	tx->tx_flags = tx_flags;
	tx->next_frame_len = 0;
467
468
469
470
471
}

/*
 * start REPLY_TX command process
 */
472
static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
473
474
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
475
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
476
	struct iwl3945_tx_cmd *tx;
477
	struct iwl_tx_queue *txq = NULL;
478
	struct iwl_queue *q = NULL;
479
	struct iwl_cmd *out_cmd = NULL;
480
481
	dma_addr_t phys_addr;
	dma_addr_t txcmd_phys;
482
	int txq_id = skb_get_queue_mapping(skb);
Reinette Chatre's avatar
Reinette Chatre committed
483
	u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
484
485
	u8 id;
	u8 unicast;
486
	u8 sta_id;
487
	u8 tid = 0;
488
	u16 seq_number = 0;
489
	__le16 fc;
490
	u8 wait_write_ptr = 0;
491
	u8 *qc = NULL;
492
493
494
495
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&priv->lock, flags);
496
	if (iwl_is_rfkill(priv)) {
497
		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
498
499
500
		goto drop_unlock;
	}

501
	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
502
		IWL_ERR(priv, "ERROR: No TX rate available.\n");
503
504
505
506
507
508
		goto drop_unlock;
	}

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

509
	fc = hdr->frame_control;
510

Samuel Ortiz's avatar
Samuel Ortiz committed
511
#ifdef CONFIG_IWLWIFI_DEBUG
512
	if (ieee80211_is_auth(fc))
513
		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
514
	else if (ieee80211_is_assoc_req(fc))
515
		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
516
	else if (ieee80211_is_reassoc_req(fc))
517
		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
518
519
#endif

520
	/* drop all data frame if we are not associated */
521
	if (ieee80211_is_data(fc) &&
522
	    (!iwl_is_monitor_mode(priv)) && /* packet injection */
523
	    (!iwl_is_associated(priv) ||
524
	     ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
525
		IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
526
527
528
529
530
		goto drop_unlock;
	}

	spin_unlock_irqrestore(&priv->lock, flags);

531
	hdr_len = ieee80211_hdrlen(fc);
532
533

	/* Find (or create) index into station table for destination station */
534
	sta_id = iwl_get_sta_id(priv, hdr);
535
	if (sta_id == IWL_INVALID_STATION) {
536
		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
Johannes Berg's avatar
Johannes Berg committed
537
			       hdr->addr1);
538
539
540
		goto drop;
	}

541
	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
542

543
544
	if (ieee80211_is_data_qos(fc)) {
		qc = ieee80211_get_qos_ctl(hdr);
545
		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
546
		seq_number = priv->stations[sta_id].tid[tid].seq_number &
547
548
549
				IEEE80211_SCTL_SEQ;
		hdr->seq_ctrl = cpu_to_le16(seq_number) |
			(hdr->seq_ctrl &
550
				cpu_to_le16(IEEE80211_SCTL_FRAG));
551
552
		seq_number += 0x10;
	}
553
554

	/* Descriptor for chosen Tx queue */
555
	txq = &priv->txq[txq_id];
556
557
558
559
	q = &txq->q;

	spin_lock_irqsave(&priv->lock, flags);

560
	idx = get_cmd_index(q, q->write_ptr, 0);
561

562
	/* Set up driver data for this TFD */
Winkler, Tomas's avatar
Winkler, Tomas committed
563
	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
564
	txq->txb[q->write_ptr].skb[0] = skb;
565
566

	/* Init first empty entry in queue's array of Tx/cmd buffers */
567
	out_cmd = txq->cmd[idx];
568
	tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
569
	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
570
	memset(tx, 0, sizeof(*tx));
571
572
573
574
575
576
577

	/*
	 * Set up the Tx-command (not MAC!) header.
	 * Store the chosen Tx queue and TFD index within the sequence field;
	 * after Tx, uCode's Tx response will return this value so driver can
	 * locate the frame within the tx queue and do post-tx processing.
	 */
578
579
	out_cmd->hdr.cmd = REPLY_TX;
	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
580
				INDEX_TO_SEQ(q->write_ptr)));
581
582

	/* Copy MAC header from skb into command buffer */
583
	memcpy(tx->hdr, hdr, hdr_len);
584

Reinette Chatre's avatar
Reinette Chatre committed
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

	if (info->control.hw_key)
		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);

	/* TODO need this for burst mode later on */
	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);

	/* set is_hcca to 0; it probably will never be implemented */
	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);

	/* Total # bytes to be transmitted */
	len = (u16)skb->len;
	tx->len = cpu_to_le16(len);


	tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
	tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;

	if (!ieee80211_has_morefrags(hdr->frame_control)) {
		txq->need_update = 1;
		if (qc)
606
			priv->stations[sta_id].tid[tid].seq_number = seq_number;
Reinette Chatre's avatar
Reinette Chatre committed
607
608
609
610
611
612
613
614
	} else {
		wait_write_ptr = 1;
		txq->need_update = 0;
	}

	IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
		     le16_to_cpu(out_cmd->hdr.sequence));
	IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
615
616
	iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx));
	iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr,
Reinette Chatre's avatar
Reinette Chatre committed
617
618
			   ieee80211_hdrlen(fc));

619
620
621
622
623
624
625
626
627
	/*
	 * Use the first empty entry in this queue's command buffer array
	 * to contain the Tx command and MAC header concatenated together
	 * (payload data will be in another buffer).
	 * Size of this varies, due to varying MAC header length.
	 * If end is not dword aligned, we'll have 2 extra bytes at the end
	 * of the MAC header (device reads on dword boundaries).
	 * We'll tell device about this padding later.
	 */
628
	len = sizeof(struct iwl3945_tx_cmd) +
629
			sizeof(struct iwl_cmd_header) + hdr_len;
630
631
632
633
634
635
636
637
638

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

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

639
640
	/* Physical address of this Tx command's header (not MAC header!),
	 * within command buffer array. */
Reinette Chatre's avatar
Reinette Chatre committed
641
642
643
644
	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
				    len, PCI_DMA_TODEVICE);
	/* we do not map meta data ... so we can safely access address to
	 * provide to unmap command*/
645
	pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
Reinette Chatre's avatar
Reinette Chatre committed
646
	pci_unmap_len_set(&out_cmd->meta, len, len);
647

648
649
	/* Add buffer containing Tx command and MAC(!) header to TFD's
	 * first entry */
650
651
	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
						   txcmd_phys, len, 1, 0);
652
653


654
655
	/* Set up TFD's 2nd entry to point directly to remainder of skb,
	 * if any (802.11 null frames have no payload). */
656
657
658
659
	len = skb->len - hdr_len;
	if (len) {
		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
					   len, PCI_DMA_TODEVICE);
660
661
662
		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
							   phys_addr, len,
							   0, U32_PAD(len));
663
664
665
	}


666
	/* Tell device the write index *just past* this latest filled TFD */
667
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
668
	rc = iwl_txq_update_write_ptr(priv, txq);
669
670
671
672
673
	spin_unlock_irqrestore(&priv->lock, flags);

	if (rc)
		return rc;

674
	if ((iwl_queue_space(q) < q->high_mark)
675
676
677
678
	    && priv->mac80211_registered) {
		if (wait_write_ptr) {
			spin_lock_irqsave(&priv->lock, flags);
			txq->need_update = 1;
679
			iwl_txq_update_write_ptr(priv, txq);
680
681
682
			spin_unlock_irqrestore(&priv->lock, flags);
		}

683
		iwl_stop_queue(priv, skb_get_queue_mapping(skb));
684
685
686
687
688
689
690
691
692
693
	}

	return 0;

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

694
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
695
696
697
698
699
700
701
702
703
704
705
706
707
708

#include "iwl-spectrum.h"

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

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

Christoph Hellwig's avatar
Christoph Hellwig committed
709
static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval)
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
{
	u32 quot;
	u32 rem;
	u32 interval = beacon_interval * 1024;

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

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

	return (quot << 24) + rem;
}

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

Christoph Hellwig's avatar
Christoph Hellwig committed
728
static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
{
	u32 base_low = base & BEACON_TIME_MASK_LOW;
	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
	u32 interval = beacon_interval * TIME_UNIT;
	u32 res = (base & BEACON_TIME_MASK_HIGH) +
	    (addon & BEACON_TIME_MASK_HIGH);

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

	return cpu_to_le32(res);
}

747
static int iwl3945_get_measurement(struct iwl_priv *priv,
748
749
750
			       struct ieee80211_measurement_params *params,
			       u8 type)
{
751
	struct iwl_spectrum_cmd spectrum;
752
	struct iwl_rx_packet *res;
753
	struct iwl_host_cmd cmd = {
754
755
756
757
758
759
760
761
762
		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
		.data = (void *)&spectrum,
		.meta.flags = CMD_WANT_SKB,
	};
	u32 add_time = le64_to_cpu(params->start_time);
	int rc;
	int spectrum_resp_status;
	int duration = le16_to_cpu(params->duration);

763
	if (iwl_is_associated(priv))
764
		add_time =
Christoph Hellwig's avatar
Christoph Hellwig committed
765
		    iwl3945_usecs_to_beacons(
766
767
768
769
770
771
772
773
774
775
776
777
			le64_to_cpu(params->start_time) - priv->last_tsf,
			le16_to_cpu(priv->rxon_timing.beacon_interval));

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

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

778
	if (iwl_is_associated(priv))
779
		spectrum.start_time =
Christoph Hellwig's avatar
Christoph Hellwig committed
780
		    iwl3945_add_beacon_time(priv->last_beacon_time,
781
782
783
784
785
786
787
788
				add_time,
				le16_to_cpu(priv->rxon_timing.beacon_interval));
	else
		spectrum.start_time = 0;

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

793
	rc = iwl_send_cmd_sync(priv, &cmd);
794
795
796
	if (rc)
		return rc;

797
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
798
	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
799
		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
800
801
802
803
804
805
806
		rc = -EIO;
	}

	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
	switch (spectrum_resp_status) {
	case 0:		/* Command will be handled */
		if (res->u.spectrum.id != 0xff) {
807
			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
808
						res->u.spectrum.id);
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
			priv->measurement_status &= ~MEASUREMENT_READY;
		}
		priv->measurement_status |= MEASUREMENT_ACTIVE;
		rc = 0;
		break;

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

	dev_kfree_skb_any(cmd.meta.u.skb);

	return rc;
}
#endif

826
static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
827
			       struct iwl_rx_mem_buffer *rxb)
828
{
829
830
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
	struct iwl_alive_resp *palive;
831
832
833
834
	struct delayed_work *pwork;

	palive = &pkt->u.alive_frame;

835
	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
836
837
838
839
840
		       "0x%01X 0x%01X\n",
		       palive->is_valid, palive->ver_type,
		       palive->ver_subtype);

	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
841
		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
842
843
		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
		       sizeof(struct iwl_alive_resp));
844
845
		pwork = &priv->init_alive_start;
	} else {
846
		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
847
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
848
		       sizeof(struct iwl_alive_resp));
849
		pwork = &priv->alive_start;
Christoph Hellwig's avatar
Christoph Hellwig committed
850
		iwl3945_disable_events(priv);
851
852
853
854
855
856
857
858
	}

	/* We delay the ALIVE response by 5ms to
	 * give the HW RF Kill time to activate... */
	if (palive->is_valid == UCODE_VALID_OK)
		queue_delayed_work(priv->workqueue, pwork,
				   msecs_to_jiffies(5));
	else
859
		IWL_WARN(priv, "uCode did not respond OK.\n");
860
861
}

862
static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
863
				 struct iwl_rx_mem_buffer *rxb)
864
{
865
#ifdef CONFIG_IWLWIFI_DEBUG
866
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
867
#endif
868

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

Christoph Hellwig's avatar
Christoph Hellwig committed
873
static void iwl3945_bg_beacon_update(struct work_struct *work)
874
{
875
876
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
877
878
879
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
880
	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
881
882

	if (!beacon) {
883
		IWL_ERR(priv, "update beacon failed\n");
884
885
886
887
888
889
890
891
892
893
894
		return;
	}

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

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

Christoph Hellwig's avatar
Christoph Hellwig committed
895
	iwl3945_send_beacon_cmd(priv);
896
897
}

898
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
899
				struct iwl_rx_mem_buffer *rxb)
900
{
Samuel Ortiz's avatar
Samuel Ortiz committed
901
#ifdef CONFIG_IWLWIFI_DEBUG
902
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
Christoph Hellwig's avatar
Christoph Hellwig committed
903
	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
904
905
	u8 rate = beacon->beacon_notify_hdr.rate;

906
	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
907
908
909
910
911
912
913
914
		"tsf %d %d rate %d\n",
		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
		beacon->beacon_notify_hdr.failure_frame,
		le32_to_cpu(beacon->ibss_mgr_status),
		le32_to_cpu(beacon->high_tsf),
		le32_to_cpu(beacon->low_tsf), rate);
#endif

915
	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
916
917
918
919
920
921
	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
		queue_work(priv->workqueue, &priv->beacon_update);
}

/* Handle notification from uCode that card's power state is changing
 * due to software, hardware, or critical temperature RFKILL */
922
static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
923
				    struct iwl_rx_mem_buffer *rxb)
924
{
925
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
926
927
928
	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
	unsigned long status = priv->status;

929
	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
930
931
932
			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");

933
	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
934
935
936
937
938
939
940
941
		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

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


942
	iwl_scan_cancel(priv);
943
944

	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
945
946
947
	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
				test_bit(STATUS_RF_KILL_HW, &priv->status));
948
949
950
951
952
	else
		wake_up_interruptible(&priv->wait_command_queue);
}

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
953
 * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
954
955
956
957
958
959
960
 *
 * Setup the RX handlers for each of the reply types sent from the uCode
 * to the host.
 *
 * This function chains into the hardware specific files for them to setup
 * any hardware specific handlers as well.
 */
961
static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
962
{
Christoph Hellwig's avatar
Christoph Hellwig committed
963
964
	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
965
	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
966
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
967
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
968
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
969
	    iwl_rx_pm_debug_statistics_notif;
Christoph Hellwig's avatar
Christoph Hellwig committed
970
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
971

972
973
974
975
	/*
	 * The same handler is used for both the REPLY to a discrete
	 * statistics request from the host as well as for the periodic
	 * statistics notifications (after received beacons) from the uCode.
976
	 */
Christoph Hellwig's avatar
Christoph Hellwig committed
977
978
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
979

980
	iwl_setup_spectrum_handlers(priv);
981
	iwl_setup_rx_scan_handlers(priv);
Christoph Hellwig's avatar
Christoph Hellwig committed
982
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
983

984
	/* Set up hardware specific Rx handlers */
Christoph Hellwig's avatar
Christoph Hellwig committed
985
	iwl3945_hw_rx_handler_setup(priv);
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
}

/************************** RX-FUNCTIONS ****************************/
/*
 * Rx theory of operation
 *
 * The host allocates 32 DMA target addresses and passes the host address
 * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
 * 0 to 31
 *
 * Rx Queue Indexes
 * The host/firmware share two index registers for managing the Rx buffers.
 *
 * The READ index maps to the first position that the firmware may be writing
 * to -- the driver can read up to (but not including) this position and get
 * good data.
 * The READ index is managed by the firmware once the card is enabled.
 *
 * The WRITE index maps to the last position the driver has read from -- the
 * position preceding WRITE is the last slot the firmware can place a packet.
 *
 * The queue is empty (no good data) if WRITE = READ - 1, and is full if
 * WRITE = READ.
 *
1010
 * During initialization, the host sets up the READ queue position to the first
1011
1012
 * INDEX position, and WRITE to the last (READ - 1 wrapped)
 *
1013
 * When the firmware places a packet in a buffer, it will advance the READ index
1014
1015
1016
1017
1018
1019
1020
 * and fire the RX interrupt.  The driver can then query the READ index and
 * process as many packets as possible, moving the WRITE index forward as it
 * resets the Rx queue buffers with new memory.
 *
 * The management in the driver is as follows:
 * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
 *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
1021
 *   to replenish the iwl->rxq->rx_free.
Christoph Hellwig's avatar
Christoph Hellwig committed
1022
 * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
 *   iwl->rxq is replenished and the READ INDEX is updated (updating the
 *   'processed' and 'read' driver indexes as well)
 * + A received packet is processed and handed to the kernel network stack,
 *   detached from the iwl->rxq.  The driver 'processed' index is updated.
 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
 *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
 *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
 *   were enough free buffers and RX_STALLED is set it is cleared.
 *
 *
 * Driver sequence:
 *
1035
 * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
Christoph Hellwig's avatar
Christoph Hellwig committed
1036
 *                            iwl3945_rx_queue_restock
1037
 * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
1038
1039
 *                            queue, updates firmware pointers, and updates
 *                            the WRITE index.  If insufficient rx_free buffers
Christoph Hellwig's avatar
Christoph Hellwig committed
1040
 *                            are available, schedules iwl3945_rx_replenish