iwl3945-base.c 122 KB
Newer Older
1
2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2010 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
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

30
31
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

32
33
34
35
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
36
#include <linux/pci-aspm.h>
37
#include <linux/slab.h>
38
39
#include <linux/dma-mapping.h>
#include <linux/delay.h>
40
#include <linux/sched.h>
41
42
43
44
45
46
47
48
49
50
51
52
#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>
#include <net/mac80211.h>

#include <asm/div64.h>

53
54
#define DRV_NAME	"iwl3945"

Winkler, Tomas's avatar
Winkler, Tomas committed
55
56
#include "iwl-fh.h"
#include "iwl-3945-fh.h"
57
#include "iwl-commands.h"
58
#include "iwl-sta.h"
59
#include "iwl-3945.h"
60
#include "iwl-core.h"
61
#include "iwl-helpers.h"
62
#include "iwl-dev.h"
63
#include "iwl-spectrum.h"
64
#include "iwl-legacy.h"
65
66
67
68
69
70
71
72

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

79
80
81
82
83
84
/*
 * add "s" to indicate spectrum measurement included.
 * we add it here to be consistent with previous releases in which
 * this was configurable.
 */
#define DRV_VERSION  IWLWIFI_VERSION VD "s"
85
#define DRV_COPYRIGHT	"Copyright(c) 2003-2010 Intel Corporation"
86
#define DRV_AUTHOR     "<ilw@linux.intel.com>"
87
88
89

MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
90
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
91
92
MODULE_LICENSE("GPL");

93
94
 /* module parameters */
struct iwl_mod_params iwl3945_mod_params = {
95
	.sw_crypto = 1,
96
	.restart_fw = 1,
97
98
99
	/* the rest are 0 by default */
};

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
135
136
/**
 * 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 */
}

137
static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
138
139
140
141
142
				   struct ieee80211_key_conf *keyconf,
				   u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
143
144
145
146
147
	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);

148
	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
149
150
151
152
153
		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;
154
155

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

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

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

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

174
175
176
	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;
177

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

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

182
183
	spin_unlock_irqrestore(&priv->sta_lock, flags);

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	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;
199
200
}

201
static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
202
203
{
	unsigned long flags;
204
	struct iwl_addsta_cmd sta_cmd;
205
206

	spin_lock_irqsave(&priv->sta_lock, flags);
207
208
	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
	memset(&priv->stations[sta_id].sta.key, 0,
209
		sizeof(struct iwl4965_keyinfo));
210
211
212
	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;
213
	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
214
215
	spin_unlock_irqrestore(&priv->sta_lock, flags);

216
	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
217
	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
218
219
}

Abhijeet Kolekar's avatar
Abhijeet Kolekar committed
220
static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
221
222
223
224
225
226
			struct ieee80211_key_conf *keyconf, u8 sta_id)
{
	int ret = 0;

	keyconf->hw_key_idx = HW_KEY_DYNAMIC;

227
228
	switch (keyconf->cipher) {
	case WLAN_CIPHER_SUITE_CCMP:
229
230
		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
		break;
231
	case WLAN_CIPHER_SUITE_TKIP:
232
233
		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
		break;
234
235
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
236
237
238
		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
		break;
	default:
239
240
		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
			keyconf->cipher);
241
242
243
		ret = -EINVAL;
	}

244
245
	IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
		      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)
{
261
262
	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
263
264
		return -EOPNOTSUPP;

265
	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
266
267
268
	return -EINVAL;
}

269
static void iwl3945_clear_free_frames(struct iwl_priv *priv)
270
271
272
{
	struct list_head *element;

273
	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
274
275
276
277
278
		       priv->frames_count);

	while (!list_empty(&priv->free_frames)) {
		element = priv->free_frames.next;
		list_del(element);
Christoph Hellwig's avatar
Christoph Hellwig committed
279
		kfree(list_entry(element, struct iwl3945_frame, list));
280
281
282
283
		priv->frames_count--;
	}

	if (priv->frames_count) {
284
		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
285
286
287
288
289
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

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

		priv->frames_count++;
		return frame;
	}

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

310
static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
311
312
313
314
315
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

316
unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
317
				struct ieee80211_hdr *hdr,
318
				int left)
319
320
{

321
	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
322
323
		return 0;

324
	if (priv->beacon_skb->len > left)
325
326
		return 0;

327
	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
328

329
	return priv->beacon_skb->len;
330
331
}

332
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
333
{
Christoph Hellwig's avatar
Christoph Hellwig committed
334
	struct iwl3945_frame *frame;
335
336
337
338
	unsigned int frame_size;
	int rc;
	u8 rate;

Christoph Hellwig's avatar
Christoph Hellwig committed
339
	frame = iwl3945_get_free_frame(priv);
340
341

	if (!frame) {
342
		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
343
344
345
346
			  "command.\n");
		return -ENOMEM;
	}

347
348
	rate = iwl_rate_get_lowest_plcp(priv,
				&priv->contexts[IWL_RXON_CTX_BSS]);
349

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

352
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
353
354
			      &frame->u.cmd[0]);

Christoph Hellwig's avatar
Christoph Hellwig committed
355
	iwl3945_free_frame(priv, frame);
356
357
358
359

	return rc;
}

360
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
361
{
362
	if (priv->_3945.shared_virt)
363
364
		dma_free_coherent(&priv->pci_dev->dev,
				  sizeof(struct iwl3945_shared),
365
366
				  priv->_3945.shared_virt,
				  priv->_3945.shared_phys);
367
368
}

369
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
370
				      struct ieee80211_tx_info *info,
371
				      struct iwl_device_cmd *cmd,
372
				      struct sk_buff *skb_frag,
373
				      int sta_id)
374
{
375
	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
376
	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
377

378
379
380
381
	tx_cmd->sec_ctl = 0;

	switch (keyinfo->cipher) {
	case WLAN_CIPHER_SUITE_CCMP:
382
383
		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
		memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
384
		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
385
386
		break;

387
	case WLAN_CIPHER_SUITE_TKIP:
388
389
		break;

390
391
392
393
394
	case WLAN_CIPHER_SUITE_WEP104:
		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
		/* fall through */
	case WLAN_CIPHER_SUITE_WEP40:
		tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
395
		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
396

397
		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
398

399
		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
400
			     "with key %d\n", info->control.hw_key->hw_key_idx);
401
402
403
		break;

	default:
404
		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
405
406
407
408
409
410
411
		break;
	}
}

/*
 * handle build REPLY_TX command notification.
 */
412
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
413
				  struct iwl_device_cmd *cmd,
414
				  struct ieee80211_tx_info *info,
415
				  struct ieee80211_hdr *hdr, u8 std_id)
416
{
417
418
	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
	__le32 tx_flags = tx_cmd->tx_flags;
419
	__le16 fc = hdr->frame_control;
420

421
	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
422
	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
423
		tx_flags |= TX_CMD_FLG_ACK_MSK;
424
		if (ieee80211_is_mgmt(fc))
425
			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
426
		if (ieee80211_is_probe_resp(fc) &&
427
428
429
430
431
432
433
		    !(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;
	}

434
	tx_cmd->sta_id = std_id;
435
	if (ieee80211_has_morefrags(fc))
436
437
		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

438
439
	if (ieee80211_is_data_qos(fc)) {
		u8 *qc = ieee80211_get_qos_ctl(hdr);
440
		tx_cmd->tid_tspec = qc[0] & 0xf;
441
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
442
	} else {
443
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
444
	}
445

Johannes Berg's avatar
Johannes Berg committed
446
	priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
447
448

	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
449
450
	if (ieee80211_is_mgmt(fc)) {
		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
451
			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
452
		else
453
			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
Mohamed Abbas's avatar
Mohamed Abbas committed
454
	} else {
455
		tx_cmd->timeout.pm_frame_timeout = 0;
Mohamed Abbas's avatar
Mohamed Abbas committed
456
	}
457

458
459
460
	tx_cmd->driver_txop = 0;
	tx_cmd->tx_flags = tx_flags;
	tx_cmd->next_frame_len = 0;
461
462
463
464
465
}

/*
 * start REPLY_TX command process
 */
466
static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
467
468
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
469
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
470
	struct iwl3945_tx_cmd *tx_cmd;
471
	struct iwl_tx_queue *txq = NULL;
472
	struct iwl_queue *q = NULL;
473
474
	struct iwl_device_cmd *out_cmd;
	struct iwl_cmd_meta *out_meta;
475
476
	dma_addr_t phys_addr;
	dma_addr_t txcmd_phys;
477
	int txq_id = skb_get_queue_mapping(skb);
478
	u16 len, idx, hdr_len;
479
480
	u8 id;
	u8 unicast;
481
	u8 sta_id;
482
	u8 tid = 0;
483
	__le16 fc;
484
485
486
487
	u8 wait_write_ptr = 0;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
488
	if (iwl_is_rfkill(priv)) {
489
		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
490
491
492
		goto drop_unlock;
	}

493
	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
494
		IWL_ERR(priv, "ERROR: No TX rate available.\n");
495
496
497
498
499
500
		goto drop_unlock;
	}

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

501
	fc = hdr->frame_control;
502

Samuel Ortiz's avatar
Samuel Ortiz committed
503
#ifdef CONFIG_IWLWIFI_DEBUG
504
	if (ieee80211_is_auth(fc))
505
		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
506
	else if (ieee80211_is_assoc_req(fc))
507
		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
508
	else if (ieee80211_is_reassoc_req(fc))
509
		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
510
511
512
513
#endif

	spin_unlock_irqrestore(&priv->lock, flags);

514
	hdr_len = ieee80211_hdrlen(fc);
515

516
	/* Find index into station table for destination station */
517
518
519
	sta_id = iwl_sta_id_or_broadcast(
			priv, &priv->contexts[IWL_RXON_CTX_BSS],
			info->control.sta);
520
	if (sta_id == IWL_INVALID_STATION) {
521
		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
Johannes Berg's avatar
Johannes Berg committed
522
			       hdr->addr1);
523
524
525
		goto drop;
	}

526
	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
527

528
	if (ieee80211_is_data_qos(fc)) {
529
		u8 *qc = ieee80211_get_qos_ctl(hdr);
530
		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
531
532
		if (unlikely(tid >= MAX_TID_COUNT))
			goto drop;
533
	}
534
535

	/* Descriptor for chosen Tx queue */
536
	txq = &priv->txq[txq_id];
537
538
	q = &txq->q;

Zhu Yi's avatar
Zhu Yi committed
539
540
541
	if ((iwl_queue_space(q) < q->high_mark))
		goto drop;

542
543
	spin_lock_irqsave(&priv->lock, flags);

544
	idx = get_cmd_index(q, q->write_ptr, 0);
545

546
	/* Set up driver data for this TFD */
Winkler, Tomas's avatar
Winkler, Tomas committed
547
	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
548
	txq->txb[q->write_ptr].skb = skb;
549
	txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
550
551

	/* Init first empty entry in queue's array of Tx/cmd buffers */
552
	out_cmd = txq->cmd[idx];
553
	out_meta = &txq->meta[idx];
554
	tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
555
	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
556
	memset(tx_cmd, 0, sizeof(*tx_cmd));
557
558
559
560
561
562
563

	/*
	 * 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.
	 */
564
565
	out_cmd->hdr.cmd = REPLY_TX;
	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
566
				INDEX_TO_SEQ(q->write_ptr)));
567
568

	/* Copy MAC header from skb into command buffer */
569
	memcpy(tx_cmd->hdr, hdr, hdr_len);
570

Reinette Chatre's avatar
Reinette Chatre committed
571
572
573
574
575
576
577
578
579
580
581
582

	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;
583
	tx_cmd->len = cpu_to_le16(len);
Reinette Chatre's avatar
Reinette Chatre committed
584

585
	iwl_dbg_log_tx_data_frame(priv, len, hdr);
586
	iwl_update_stats(priv, true, fc, len);
587
588
	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
Reinette Chatre's avatar
Reinette Chatre committed
589
590
591
592
593
594
595
596

	if (!ieee80211_has_morefrags(hdr->frame_control)) {
		txq->need_update = 1;
	} else {
		wait_write_ptr = 1;
		txq->need_update = 0;
	}

597
	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
Reinette Chatre's avatar
Reinette Chatre committed
598
		     le16_to_cpu(out_cmd->hdr.sequence));
599
	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
600
601
	iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
Reinette Chatre's avatar
Reinette Chatre committed
602
603
			   ieee80211_hdrlen(fc));

604
605
606
607
608
609
610
611
612
	/*
	 * 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.
	 */
613
	len = sizeof(struct iwl3945_tx_cmd) +
614
			sizeof(struct iwl_cmd_header) + hdr_len;
615
616
	len = (len + 3) & ~3;

617
618
	/* Physical address of this Tx command's header (not MAC header!),
	 * within command buffer array. */
Reinette Chatre's avatar
Reinette Chatre committed
619
620
621
622
	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*/
623
624
	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
	dma_unmap_len_set(out_meta, len, len);
625

626
627
	/* Add buffer containing Tx command and MAC(!) header to TFD's
	 * first entry */
628
629
	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
						   txcmd_phys, len, 1, 0);
630
631


632
633
	/* Set up TFD's 2nd entry to point directly to remainder of skb,
	 * if any (802.11 null frames have no payload). */
634
635
636
637
	len = skb->len - hdr_len;
	if (len) {
		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
					   len, PCI_DMA_TODEVICE);
638
639
640
		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
							   phys_addr, len,
							   0, U32_PAD(len));
641
642
643
	}


644
	/* Tell device the write index *just past* this latest filled TFD */
645
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
646
	iwl_txq_update_write_ptr(priv, txq);
647
648
	spin_unlock_irqrestore(&priv->lock, flags);

649
	if ((iwl_queue_space(q) < q->high_mark)
650
651
652
653
	    && priv->mac80211_registered) {
		if (wait_write_ptr) {
			spin_lock_irqsave(&priv->lock, flags);
			txq->need_update = 1;
654
			iwl_txq_update_write_ptr(priv, txq);
655
656
657
			spin_unlock_irqrestore(&priv->lock, flags);
		}

658
		iwl_stop_queue(priv, txq);
659
660
661
662
663
664
665
666
667
668
	}

	return 0;

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

669
static int iwl3945_get_measurement(struct iwl_priv *priv,
670
671
672
			       struct ieee80211_measurement_params *params,
			       u8 type)
{
673
	struct iwl_spectrum_cmd spectrum;
Zhu Yi's avatar
Zhu Yi committed
674
	struct iwl_rx_packet *pkt;
675
	struct iwl_host_cmd cmd = {
676
677
		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
		.data = (void *)&spectrum,
678
		.flags = CMD_WANT_SKB,
679
680
681
682
683
	};
	u32 add_time = le64_to_cpu(params->start_time);
	int rc;
	int spectrum_resp_status;
	int duration = le16_to_cpu(params->duration);
684
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
685

686
	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
687
		add_time = iwl_usecs_to_beacons(priv,
688
			le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
689
			le16_to_cpu(ctx->timing.beacon_interval));
690
691
692
693
694
695
696
697
698
699

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

700
	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
701
		spectrum.start_time =
702
703
			iwl_add_beacon_time(priv,
				priv->_3945.last_beacon_time, add_time,
704
				le16_to_cpu(ctx->timing.beacon_interval));
705
706
707
708
709
710
	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;
711
	if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
712
713
714
		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;

715
	rc = iwl_send_cmd_sync(priv, &cmd);
716
717
718
	if (rc)
		return rc;

Zhu Yi's avatar
Zhu Yi committed
719
720
	pkt = (struct iwl_rx_packet *)cmd.reply_page;
	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
721
		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
722
723
724
		rc = -EIO;
	}

Zhu Yi's avatar
Zhu Yi committed
725
	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
726
727
	switch (spectrum_resp_status) {
	case 0:		/* Command will be handled */
Zhu Yi's avatar
Zhu Yi committed
728
		if (pkt->u.spectrum.id != 0xff) {
729
			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
Zhu Yi's avatar
Zhu Yi committed
730
						pkt->u.spectrum.id);
731
732
733
734
735
736
737
738
739
740
741
			priv->measurement_status &= ~MEASUREMENT_READY;
		}
		priv->measurement_status |= MEASUREMENT_ACTIVE;
		rc = 0;
		break;

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

742
	iwl_free_pages(priv, cmd.reply_page);
743
744
745
746

	return rc;
}

747
static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
748
			       struct iwl_rx_mem_buffer *rxb)
749
{
Zhu Yi's avatar
Zhu Yi committed
750
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
751
	struct iwl_alive_resp *palive;
752
753
754
755
	struct delayed_work *pwork;

	palive = &pkt->u.alive_frame;

756
	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
757
758
759
760
761
		       "0x%01X 0x%01X\n",
		       palive->is_valid, palive->ver_type,
		       palive->ver_subtype);

	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
762
		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
763
764
		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
		       sizeof(struct iwl_alive_resp));
765
766
		pwork = &priv->init_alive_start;
	} else {
767
		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
768
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
769
		       sizeof(struct iwl_alive_resp));
770
		pwork = &priv->alive_start;
Christoph Hellwig's avatar
Christoph Hellwig committed
771
		iwl3945_disable_events(priv);
772
773
774
775
776
777
778
779
	}

	/* 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
780
		IWL_WARN(priv, "uCode did not respond OK.\n");
781
782
}

783
static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
784
				 struct iwl_rx_mem_buffer *rxb)
785
{
786
#ifdef CONFIG_IWLWIFI_DEBUG
Zhu Yi's avatar
Zhu Yi committed
787
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
788
#endif
789

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

Christoph Hellwig's avatar
Christoph Hellwig committed
793
static void iwl3945_bg_beacon_update(struct work_struct *work)
794
{
795
796
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
797
798
799
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
800
801
	beacon = ieee80211_beacon_get(priv->hw,
			priv->contexts[IWL_RXON_CTX_BSS].vif);
802
803

	if (!beacon) {
804
		IWL_ERR(priv, "update beacon failed\n");
805
806
807
808
809
		return;
	}

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

813
	priv->beacon_skb = beacon;
814
815
	mutex_unlock(&priv->mutex);

Christoph Hellwig's avatar
Christoph Hellwig committed
816
	iwl3945_send_beacon_cmd(priv);
817
818
}

819
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
820
				struct iwl_rx_mem_buffer *rxb)
821
{
Zhu Yi's avatar
Zhu Yi committed
822
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
Christoph Hellwig's avatar
Christoph Hellwig committed
823
	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
824
#ifdef CONFIG_IWLWIFI_DEBUG
825
826
	u8 rate = beacon->beacon_notify_hdr.rate;

827
	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
828
829
830
831
832
833
834
835
		"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

836
837
	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);

838
	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
839
840
841
842
843
844
	    (!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 */
845
static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
846
				    struct iwl_rx_mem_buffer *rxb)
847
{
Zhu Yi's avatar
Zhu Yi committed
848
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
849
850
851
	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
	unsigned long status = priv->status;

852
	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
853
854
855
			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");

856
	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
857
858
859
860
861
862
863
864
		    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);


865
	iwl_scan_cancel(priv);
866
867

	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
868
869
870
	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
				test_bit(STATUS_RF_KILL_HW, &priv->status));
871
872
873
874
875
	else
		wake_up_interruptible(&priv->wait_command_queue);
}

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
876
 * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
877
878
879
880
881
882
883
 *
 * 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.
 */
884
static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
885
{
Christoph Hellwig's avatar
Christoph Hellwig committed
886
887
	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
888
	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
889
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
890
891
	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
			iwl_rx_spectrum_measure_notif;
892
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
893
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
894
	    iwl_rx_pm_debug_statistics_notif;
Christoph Hellwig's avatar
Christoph Hellwig committed
895
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
896

897
898
899
900
	/*
	 * 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.
901
	 */
902
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
Christoph Hellwig's avatar
Christoph Hellwig committed
903
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
904

905
	iwl_setup_rx_scan_handlers(priv);
Christoph Hellwig's avatar
Christoph Hellwig committed
906
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
907

908
	/* Set up hardware specific Rx handlers */
Christoph Hellwig's avatar
Christoph Hellwig committed
909
	iwl3945_hw_rx_handler_setup(priv);
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
}

/************************** 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.
 *
934
 * During initialization, the host sets up the READ queue position to the first
935
936
 * INDEX position, and WRITE to the last (READ - 1 wrapped)
 *
937
 * When the firmware places a packet in a buffer, it will advance the READ index
938
939
940
941
942
943
944
 * 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
945
 *   to replenish the iwl->rxq->rx_free.
Christoph Hellwig's avatar
Christoph Hellwig committed
946
 * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
947
948
949
950
951
952
953
954
955
956
957
958
 *   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:
 *
959
 * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
Christoph Hellwig's avatar
Christoph Hellwig committed
960
 *                            iwl3945_rx_queue_restock
961
 * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
962
963
 *                            queue, updates firmware pointers, and updates
 *                            the WRITE index.  If insufficient rx_free buffers
Christoph Hellwig's avatar
Christoph Hellwig committed
964
 *                            are available, schedules iwl3945_rx_replenish
965
966
 *
 * -- enable interrupts --
967
 * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
968
969
 *                            READ INDEX, detaching the SKB from the pool.
 *                            Moves the packet buffer from queue to rx_used.
Christoph Hellwig's avatar
Christoph Hellwig committed
970
 *                            Calls iwl3945_rx_queue_restock to refill any empty
971
972
973
974
975
976
 *                            slots.
 * ...
 *
 */

/**
977
 * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
978
 */
979
static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
980
981
982
983
984
985
					  dma_addr_t dma_addr)
{
	return cpu_to_le32((u32)dma_addr);
}

/**
Christoph Hellwig's avatar
Christoph Hellwig committed
986
 * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool