3945.c 75.7 KB
Newer Older
Z
Zhu Yi 已提交
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
Z
Zhu Yi 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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:
22
 *  Intel Linux Wireless <ilw@linux.intel.com>
Z
Zhu Yi 已提交
23 24 25 26 27 28 29
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
30
#include <linux/slab.h>
Z
Zhu Yi 已提交
31 32 33
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
34
#include <linux/sched.h>
Z
Zhu Yi 已提交
35 36 37 38
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>
Z
Zhu Yi 已提交
39 40
#include <asm/unaligned.h>
#include <net/mac80211.h>
Z
Zhu Yi 已提交
41

42
#include "common.h"
43
#include "3945.h"
Z
Zhu Yi 已提交
44

45
/* Send led command */
46 47
static int
il3945_send_led_cmd(struct il_priv *il, struct il_led_cmd *led_cmd)
48 49
{
	struct il_host_cmd cmd = {
50
		.id = C_LEDS,
51 52 53 54 55 56 57 58 59 60 61 62 63
		.len = sizeof(struct il_led_cmd),
		.data = led_cmd,
		.flags = CMD_ASYNC,
		.callback = NULL,
	};

	return il_send_cmd(il, &cmd);
}

const struct il_led_ops il3945_led_ops = {
	.cmd = il3945_send_led_cmd,
};

S
Stanislaw Gruszka 已提交
64
#define IL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
S
Stanislaw Gruszka 已提交
65
	[RATE_##r##M_IDX] = { RATE_##r##M_PLCP,   \
S
Stanislaw Gruszka 已提交
66
				    RATE_##r##M_IEEE,   \
S
Stanislaw Gruszka 已提交
67 68 69 70 71 72
				    RATE_##ip##M_IDX, \
				    RATE_##in##M_IDX, \
				    RATE_##rp##M_IDX, \
				    RATE_##rn##M_IDX, \
				    RATE_##pp##M_IDX, \
				    RATE_##np##M_IDX, \
S
Stanislaw Gruszka 已提交
73 74
				    RATE_##r##M_IDX_TBL, \
				    RATE_##ip##M_IDX_TBL }
Z
Zhu Yi 已提交
75 76 77 78 79 80

/*
 * Parameter order:
 *   rate, prev rate, next rate, prev tgg rate, next tgg rate
 *
 * If there isn't a valid next or previous rate then INV is used which
S
Stanislaw Gruszka 已提交
81
 * maps to RATE_INVALID
Z
Zhu Yi 已提交
82 83
 *
 */
S
Stanislaw Gruszka 已提交
84
const struct il3945_rate_info il3945_rates[RATE_COUNT_3945] = {
85 86 87 88 89 90 91 92 93 94 95 96
	IL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),	/*  1mbps */
	IL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),	/*  2mbps */
	IL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),	/*5.5mbps */
	IL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),	/* 11mbps */
	IL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),	/*  6mbps */
	IL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),	/*  9mbps */
	IL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),	/* 12mbps */
	IL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),	/* 18mbps */
	IL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),	/* 24mbps */
	IL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),	/* 36mbps */
	IL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),	/* 48mbps */
	IL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),	/* 54mbps */
Z
Zhu Yi 已提交
97 98
};

99 100
static inline u8
il3945_get_prev_ieee_rate(u8 rate_idx)
101
{
S
Stanislaw Gruszka 已提交
102
	u8 rate = il3945_rates[rate_idx].prev_ieee;
103

S
Stanislaw Gruszka 已提交
104
	if (rate == RATE_INVALID)
S
Stanislaw Gruszka 已提交
105
		rate = rate_idx;
106 107 108
	return rate;
}

S
Stanislaw Gruszka 已提交
109 110 111
/* 1 = enable the il3945_disable_events() function */
#define IL_EVT_DISABLE (0)
#define IL_EVT_DISABLE_SIZE (1532/32)
Z
Zhu Yi 已提交
112 113

/**
S
Stanislaw Gruszka 已提交
114
 * il3945_disable_events - Disable selected events in uCode event log
Z
Zhu Yi 已提交
115 116 117 118 119 120
 *
 * Disable an event by writing "1"s into "disable"
 *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
 *   Default values of 0 enable uCode events to be logged.
 * Use for only special debugging.  This function is just a placeholder as-is,
 *   you'll need to provide the special bits! ...
S
Stanislaw Gruszka 已提交
121
 *   ... and set IL_EVT_DISABLE to 1. */
122 123
void
il3945_disable_events(struct il_priv *il)
Z
Zhu Yi 已提交
124 125 126 127 128
{
	int i;
	u32 base;		/* SRAM address of event log header */
	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
	u32 array_size;		/* # of u32 entries in array */
S
Stanislaw Gruszka 已提交
129
	static const u32 evt_disable[IL_EVT_DISABLE_SIZE] = {
Z
Zhu Yi 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
		0x00000000,	/*   31 -    0  Event id numbers */
		0x00000000,	/*   63 -   32 */
		0x00000000,	/*   95 -   64 */
		0x00000000,	/*  127 -   96 */
		0x00000000,	/*  159 -  128 */
		0x00000000,	/*  191 -  160 */
		0x00000000,	/*  223 -  192 */
		0x00000000,	/*  255 -  224 */
		0x00000000,	/*  287 -  256 */
		0x00000000,	/*  319 -  288 */
		0x00000000,	/*  351 -  320 */
		0x00000000,	/*  383 -  352 */
		0x00000000,	/*  415 -  384 */
		0x00000000,	/*  447 -  416 */
		0x00000000,	/*  479 -  448 */
		0x00000000,	/*  511 -  480 */
		0x00000000,	/*  543 -  512 */
		0x00000000,	/*  575 -  544 */
		0x00000000,	/*  607 -  576 */
		0x00000000,	/*  639 -  608 */
		0x00000000,	/*  671 -  640 */
		0x00000000,	/*  703 -  672 */
		0x00000000,	/*  735 -  704 */
		0x00000000,	/*  767 -  736 */
		0x00000000,	/*  799 -  768 */
		0x00000000,	/*  831 -  800 */
		0x00000000,	/*  863 -  832 */
		0x00000000,	/*  895 -  864 */
		0x00000000,	/*  927 -  896 */
		0x00000000,	/*  959 -  928 */
		0x00000000,	/*  991 -  960 */
		0x00000000,	/* 1023 -  992 */
		0x00000000,	/* 1055 - 1024 */
		0x00000000,	/* 1087 - 1056 */
		0x00000000,	/* 1119 - 1088 */
		0x00000000,	/* 1151 - 1120 */
		0x00000000,	/* 1183 - 1152 */
		0x00000000,	/* 1215 - 1184 */
		0x00000000,	/* 1247 - 1216 */
		0x00000000,	/* 1279 - 1248 */
		0x00000000,	/* 1311 - 1280 */
		0x00000000,	/* 1343 - 1312 */
		0x00000000,	/* 1375 - 1344 */
		0x00000000,	/* 1407 - 1376 */
		0x00000000,	/* 1439 - 1408 */
		0x00000000,	/* 1471 - 1440 */
		0x00000000,	/* 1503 - 1472 */
	};

S
Stanislaw Gruszka 已提交
179
	base = le32_to_cpu(il->card_alive.log_event_table_ptr);
S
Stanislaw Gruszka 已提交
180
	if (!il3945_hw_valid_rtc_data_addr(base)) {
181
		IL_ERR("Invalid event log pointer 0x%08X\n", base);
Z
Zhu Yi 已提交
182 183 184
		return;
	}

S
Stanislaw Gruszka 已提交
185 186
	disable_ptr = il_read_targ_mem(il, base + (4 * sizeof(u32)));
	array_size = il_read_targ_mem(il, base + (5 * sizeof(u32)));
Z
Zhu Yi 已提交
187

188
	if (IL_EVT_DISABLE && array_size == IL_EVT_DISABLE_SIZE) {
189
		D_INFO("Disabling selected uCode log events at 0x%x\n",
190
		       disable_ptr);
S
Stanislaw Gruszka 已提交
191
		for (i = 0; i < IL_EVT_DISABLE_SIZE; i++)
192 193
			il_write_targ_mem(il, disable_ptr + (i * sizeof(u32)),
					  evt_disable[i]);
Z
Zhu Yi 已提交
194 195

	} else {
196 197
		D_INFO("Selected uCode log events may be disabled\n");
		D_INFO("  by writing \"1\"s into disable bitmap\n");
198 199
		D_INFO("  in SRAM at 0x%x, size %d u32s\n", disable_ptr,
		       array_size);
Z
Zhu Yi 已提交
200 201 202 203
	}

}

204 205
static int
il3945_hwrate_to_plcp_idx(u8 plcp)
206 207 208
{
	int idx;

S
Stanislaw Gruszka 已提交
209
	for (idx = 0; idx < RATE_COUNT_3945; idx++)
S
Stanislaw Gruszka 已提交
210
		if (il3945_rates[idx].plcp == plcp)
211 212 213 214
			return idx;
	return -1;
}

215
#ifdef CONFIG_IWLEGACY_DEBUG
216
#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
217

218 219
static const char *
il3945_get_tx_fail_reason(u32 status)
220 221
{
	switch (status & TX_STATUS_MSK) {
222
	case TX_3945_STATUS_SUCCESS:
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
		return "SUCCESS";
		TX_STATUS_ENTRY(SHORT_LIMIT);
		TX_STATUS_ENTRY(LONG_LIMIT);
		TX_STATUS_ENTRY(FIFO_UNDERRUN);
		TX_STATUS_ENTRY(MGMNT_ABORT);
		TX_STATUS_ENTRY(NEXT_FRAG);
		TX_STATUS_ENTRY(LIFE_EXPIRE);
		TX_STATUS_ENTRY(DEST_PS);
		TX_STATUS_ENTRY(ABORTED);
		TX_STATUS_ENTRY(BT_RETRY);
		TX_STATUS_ENTRY(STA_INVALID);
		TX_STATUS_ENTRY(FRAG_DROPPED);
		TX_STATUS_ENTRY(TID_DISABLE);
		TX_STATUS_ENTRY(FRAME_FLUSHED);
		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
		TX_STATUS_ENTRY(TX_LOCKED);
		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
	}

	return "UNKNOWN";
}
#else
245 246
static inline const char *
il3945_get_tx_fail_reason(u32 status)
247 248 249 250 251
{
	return "";
}
#endif

252 253 254 255 256
/*
 * get ieee prev rate from rate scale table.
 * for A and B mode we need to overright prev
 * value
 */
257 258
int
il3945_rs_next_rate(struct il_priv *il, int rate)
259
{
S
Stanislaw Gruszka 已提交
260
	int next_rate = il3945_get_prev_ieee_rate(rate);
261

S
Stanislaw Gruszka 已提交
262
	switch (il->band) {
263
	case IEEE80211_BAND_5GHZ:
S
Stanislaw Gruszka 已提交
264 265 266 267
		if (rate == RATE_12M_IDX)
			next_rate = RATE_9M_IDX;
		else if (rate == RATE_6M_IDX)
			next_rate = RATE_6M_IDX;
268
		break;
269
	case IEEE80211_BAND_2GHZ:
S
Stanislaw Gruszka 已提交
270
		if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
271
		    il_is_associated(il)) {
S
Stanislaw Gruszka 已提交
272 273
			if (rate == RATE_11M_IDX)
				next_rate = RATE_5M_IDX;
274
		}
275
		break;
276

277 278 279 280 281 282 283
	default:
		break;
	}

	return next_rate;
}

284
/**
S
Stanislaw Gruszka 已提交
285
 * il3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
286
 *
S
Stanislaw Gruszka 已提交
287
 * When FW advances 'R' idx, all entries between old and new 'R' idx
288 289 290
 * need to be reclaimed. As result, some free space forms. If there is
 * enough free space (> low mark), wake the stack that feeds us.
 */
291 292
static void
il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx)
293
{
S
Stanislaw Gruszka 已提交
294
	struct il_tx_queue *txq = &il->txq[txq_id];
S
Stanislaw Gruszka 已提交
295 296
	struct il_queue *q = &txq->q;
	struct il_tx_info *tx_info;
297

298
	BUG_ON(txq_id == IL39_CMD_QUEUE_NUM);
299

300 301
	for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
	     q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
302 303

		tx_info = &txq->txb[txq->q.read_ptr];
S
Stanislaw Gruszka 已提交
304
		ieee80211_tx_status_irqsafe(il->hw, tx_info->skb);
305
		tx_info->skb = NULL;
S
Stanislaw Gruszka 已提交
306
		il->cfg->ops->lib->txq_free_tfd(il, txq);
307 308
	}

309
	if (il_queue_space(q) > q->low_mark && txq_id >= 0 &&
310
	    txq_id != IL39_CMD_QUEUE_NUM && il->mac80211_registered)
S
Stanislaw Gruszka 已提交
311
		il_wake_queue(il, txq);
312 313 314
}

/**
S
Stanislaw Gruszka 已提交
315
 * il3945_hdl_tx - Handle Tx response
316
 */
317 318
static void
il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)
319
{
320
	struct il_rx_pkt *pkt = rxb_addr(rxb);
321 322
	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
	int txq_id = SEQ_TO_QUEUE(sequence);
S
Stanislaw Gruszka 已提交
323
	int idx = SEQ_TO_IDX(sequence);
S
Stanislaw Gruszka 已提交
324
	struct il_tx_queue *txq = &il->txq[txq_id];
325
	struct ieee80211_tx_info *info;
S
Stanislaw Gruszka 已提交
326
	struct il3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
327
	u32 status = le32_to_cpu(tx_resp->status);
328
	int rate_idx;
329
	int fail;
330

S
Stanislaw Gruszka 已提交
331 332
	if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) {
		IL_ERR("Read idx for DMA queue txq_id (%d) idx %d "
333 334
		       "is out of range [0-%d] %d %d\n", txq_id, idx,
		       txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr);
335 336 337
		return;
	}

338
	txq->time_stamp = jiffies;
339
	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
340 341 342
	ieee80211_tx_info_clear_status(info);

	/* Fill the MRR chain with some info about on-chip retransmissions */
S
Stanislaw Gruszka 已提交
343
	rate_idx = il3945_hwrate_to_plcp_idx(tx_resp->rate);
344
	if (info->band == IEEE80211_BAND_5GHZ)
S
Stanislaw Gruszka 已提交
345
		rate_idx -= IL_FIRST_OFDM_RATE;
346 347

	fail = tx_resp->failure_frame;
348 349

	info->status.rates[0].idx = rate_idx;
350
	info->status.rates[0].count = fail + 1;	/* add final attempt */
351 352

	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
353 354 355
	info->flags |=
	    ((status & TX_STATUS_MSK) ==
	     TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0;
356

357 358 359
	D_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", txq_id,
	     il3945_get_tx_fail_reason(status), status, tx_resp->rate,
	     tx_resp->failure_frame);
360

S
Stanislaw Gruszka 已提交
361 362
	D_TX_REPLY("Tx queue reclaim %d\n", idx);
	il3945_tx_queue_reclaim(il, txq_id, idx);
363

J
Johannes Berg 已提交
364
	if (status & TX_ABORT_REQUIRED_MSK)
365
		IL_ERR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
366 367
}

Z
Zhu Yi 已提交
368 369 370 371 372 373 374
/*****************************************************************************
 *
 * Intel PRO/Wireless 3945ABG/BG Network Connection
 *
 *  RX handler implementations
 *
 *****************************************************************************/
375
#ifdef CONFIG_IWLEGACY_DEBUGFS
376 377
static void
il3945_accumulative_stats(struct il_priv *il, __le32 * stats)
A
Abhijeet Kolekar 已提交
378 379 380 381 382 383
{
	int i;
	__le32 *prev_stats;
	u32 *accum_stats;
	u32 *delta, *max_delta;

S
Stanislaw Gruszka 已提交
384 385 386 387
	prev_stats = (__le32 *) &il->_3945.stats;
	accum_stats = (u32 *) &il->_3945.accum_stats;
	delta = (u32 *) &il->_3945.delta_stats;
	max_delta = (u32 *) &il->_3945.max_delta;
A
Abhijeet Kolekar 已提交
388

S
Stanislaw Gruszka 已提交
389
	for (i = sizeof(__le32); i < sizeof(struct il3945_notif_stats);
390 391 392
	     i +=
	     sizeof(__le32), stats++, prev_stats++, delta++, max_delta++,
	     accum_stats++) {
A
Abhijeet Kolekar 已提交
393
		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
394 395
			*delta =
			    (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats));
A
Abhijeet Kolekar 已提交
396 397 398 399 400 401
			*accum_stats += *delta;
			if (*delta > *max_delta)
				*max_delta = *delta;
		}
	}

S
Stanislaw Gruszka 已提交
402 403
	/* reset accumulative stats for "no-counter" type stats */
	il->_3945.accum_stats.general.temperature =
404
	    il->_3945.stats.general.temperature;
S
Stanislaw Gruszka 已提交
405
	il->_3945.accum_stats.general.ttl_timestamp =
406
	    il->_3945.stats.general.ttl_timestamp;
A
Abhijeet Kolekar 已提交
407 408
}
#endif
Z
Zhu Yi 已提交
409

410 411
void
il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
Z
Zhu Yi 已提交
412
{
413
	struct il_rx_pkt *pkt = rxb_addr(rxb);
A
Abhijeet Kolekar 已提交
414

415
	D_RX("Statistics notification received (%d vs %d).\n",
416 417
	     (int)sizeof(struct il3945_notif_stats),
	     le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK);
418
#ifdef CONFIG_IWLEGACY_DEBUGFS
S
Stanislaw Gruszka 已提交
419
	il3945_accumulative_stats(il, (__le32 *) &pkt->u.raw);
A
Abhijeet Kolekar 已提交
420
#endif
Z
Zhu Yi 已提交
421

S
Stanislaw Gruszka 已提交
422
	memcpy(&il->_3945.stats, pkt->u.raw, sizeof(il->_3945.stats));
Z
Zhu Yi 已提交
423 424
}

425 426
void
il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
A
Abhijeet Kolekar 已提交
427
{
428
	struct il_rx_pkt *pkt = rxb_addr(rxb);
S
Stanislaw Gruszka 已提交
429
	__le32 *flag = (__le32 *) &pkt->u.raw;
A
Abhijeet Kolekar 已提交
430

S
Stanislaw Gruszka 已提交
431
	if (le32_to_cpu(*flag) & UCODE_STATS_CLEAR_MSK) {
432
#ifdef CONFIG_IWLEGACY_DEBUGFS
S
Stanislaw Gruszka 已提交
433
		memset(&il->_3945.accum_stats, 0,
434
		       sizeof(struct il3945_notif_stats));
S
Stanislaw Gruszka 已提交
435
		memset(&il->_3945.delta_stats, 0,
436
		       sizeof(struct il3945_notif_stats));
S
Stanislaw Gruszka 已提交
437
		memset(&il->_3945.max_delta, 0,
438
		       sizeof(struct il3945_notif_stats));
A
Abhijeet Kolekar 已提交
439
#endif
440
		D_RX("Statistics have been cleared\n");
A
Abhijeet Kolekar 已提交
441
	}
442
	il3945_hdl_stats(il, rxb);
A
Abhijeet Kolekar 已提交
443 444
}

445 446 447 448 449 450
/******************************************************************************
 *
 * Misc. internal state and helper functions
 *
 ******************************************************************************/

S
Stanislaw Gruszka 已提交
451
/* This is necessary only for a number of stats, see the caller. */
452 453
static int
il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
454 455 456
{
	/* Filter incoming packets to determine if they are targeted toward
	 * this network, discarding packets coming from ourselves */
S
Stanislaw Gruszka 已提交
457
	switch (il->iw_mode) {
458
	case NL80211_IFTYPE_ADHOC:	/* Header: Dest. | Source    | BSSID */
459
		/* packets to our IBSS update information */
S
Stanislaw Gruszka 已提交
460
		return !compare_ether_addr(header->addr3, il->bssid);
461
	case NL80211_IFTYPE_STATION:	/* Header: Dest. | AP{BSSID} | Source */
462
		/* packets to our IBSS update information */
S
Stanislaw Gruszka 已提交
463
		return !compare_ether_addr(header->addr2, il->bssid);
464 465 466 467
	default:
		return 1;
	}
}
468

469 470 471
static void
il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
			       struct ieee80211_rx_status *stats)
Z
Zhu Yi 已提交
472
{
473
	struct il_rx_pkt *pkt = rxb_addr(rxb);
S
Stanislaw Gruszka 已提交
474 475 476
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
	struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
	struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
Z
Zhu Yi 已提交
477 478
	u16 len = le16_to_cpu(rx_hdr->len);
	struct sk_buff *skb;
479
	__le16 fc = hdr->frame_control;
Z
Zhu Yi 已提交
480 481

	/* We received data from the HW, so stop the watchdog */
482 483 484
	if (unlikely
	    (len + IL39_RX_FRAME_SIZE >
	     PAGE_SIZE << il->hw_params.rx_page_order)) {
485
		D_DROP("Corruption detected!\n");
Z
Zhu Yi 已提交
486 487 488 489
		return;
	}

	/* We only process data packets if the interface is open */
S
Stanislaw Gruszka 已提交
490
	if (unlikely(!il->is_open)) {
491
		D_DROP("Dropping packet while interface is not open.\n");
Z
Zhu Yi 已提交
492 493 494
		return;
	}

495
	skb = dev_alloc_skb(128);
Z
Zhu Yi 已提交
496
	if (!skb) {
497
		IL_ERR("dev_alloc_skb failed\n");
Z
Zhu Yi 已提交
498 499
		return;
	}
Z
Zhu Yi 已提交
500

S
Stanislaw Gruszka 已提交
501
	if (!il3945_mod_params.sw_crypto)
502 503
		il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
				      le32_to_cpu(rx_end->status), stats);
Z
Zhu Yi 已提交
504

Z
Zhu Yi 已提交
505 506 507
	skb_add_rx_frag(skb, 0, rxb->page,
			(void *)rx_hdr->payload - (void *)pkt, len);

S
Stanislaw Gruszka 已提交
508
	il_update_stats(il, false, fc, len);
Z
Zhu Yi 已提交
509 510
	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));

S
Stanislaw Gruszka 已提交
511 512
	ieee80211_rx(il->hw, skb);
	il->alloc_rxb_page--;
Z
Zhu Yi 已提交
513
	rxb->page = NULL;
Z
Zhu Yi 已提交
514 515
}

S
Stanislaw Gruszka 已提交
516
#define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
517

518 519
static void
il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
Z
Zhu Yi 已提交
520
{
521 522
	struct ieee80211_hdr *header;
	struct ieee80211_rx_status rx_status;
523
	struct il_rx_pkt *pkt = rxb_addr(rxb);
S
Stanislaw Gruszka 已提交
524 525 526
	struct il3945_rx_frame_stats *rx_stats = IL_RX_STATS(pkt);
	struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
	struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
527
	u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
528 529
	u16 rx_stats_noise_diff __maybe_unused =
	    le16_to_cpu(rx_stats->noise_diff);
Z
Zhu Yi 已提交
530
	u8 network_packet;
531 532 533

	rx_status.flag = 0;
	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
534 535 536 537
	rx_status.band =
	    (rx_hdr->
	     phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ :
	    IEEE80211_BAND_5GHZ;
538
	rx_status.freq =
539 540
	    ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
					   rx_status.band);
541

S
Stanislaw Gruszka 已提交
542
	rx_status.rate_idx = il3945_hwrate_to_plcp_idx(rx_hdr->rate);
543
	if (rx_status.band == IEEE80211_BAND_5GHZ)
S
Stanislaw Gruszka 已提交
544
		rx_status.rate_idx -= IL_FIRST_OFDM_RATE;
Z
Zhu Yi 已提交
545

546 547 548
	rx_status.antenna =
	    (le16_to_cpu(rx_hdr->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) >>
	    4;
549 550 551 552 553

	/* set the preamble flag if appropriate */
	if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
		rx_status.flag |= RX_FLAG_SHORTPRE;

Z
Zhu Yi 已提交
554
	if ((unlikely(rx_stats->phy_count > 20))) {
555
		D_DROP("dsp size out of range [0,20]: %d/n",
556
		       rx_stats->phy_count);
Z
Zhu Yi 已提交
557 558 559
		return;
	}

560 561
	if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) ||
	    !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
562
		D_RX("Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
Z
Zhu Yi 已提交
563 564 565 566
		return;
	}

	/* Convert 3945's rssi indicator to dBm */
567
	rx_status.signal = rx_stats->rssi - IL39_RSSI_OFFSET;
Z
Zhu Yi 已提交
568

569 570
	D_STATS("Rssi %d sig_avg %d noise_diff %d\n", rx_status.signal,
		rx_stats_sig_avg, rx_stats_noise_diff);
Z
Zhu Yi 已提交
571

S
Stanislaw Gruszka 已提交
572
	header = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
Z
Zhu Yi 已提交
573

S
Stanislaw Gruszka 已提交
574
	network_packet = il3945_is_network_packet(il, header);
Z
Zhu Yi 已提交
575

576
	D_STATS("[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
577 578
		network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel),
		rx_status.signal, rx_status.signal, rx_status.rate_idx);
Z
Zhu Yi 已提交
579

580
	il_dbg_log_rx_data_frame(il, le16_to_cpu(rx_hdr->len), header);
Z
Zhu Yi 已提交
581 582

	if (network_packet) {
S
Stanislaw Gruszka 已提交
583
		il->_3945.last_beacon_time =
584
		    le32_to_cpu(rx_end->beacon_timestamp);
S
Stanislaw Gruszka 已提交
585 586
		il->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
		il->_3945.last_rx_rssi = rx_status.signal;
Z
Zhu Yi 已提交
587 588
	}

S
Stanislaw Gruszka 已提交
589
	il3945_pass_packet_to_mac80211(il, rxb, &rx_status);
Z
Zhu Yi 已提交
590 591
}

592 593 594
int
il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
				dma_addr_t addr, u16 len, u8 reset, u8 pad)
Z
Zhu Yi 已提交
595 596
{
	int count;
S
Stanislaw Gruszka 已提交
597 598
	struct il_queue *q;
	struct il3945_tfd *tfd, *tfd_tmp;
599 600

	q = &txq->q;
S
Stanislaw Gruszka 已提交
601
	tfd_tmp = (struct il3945_tfd *)txq->tfds;
602
	tfd = &tfd_tmp[q->write_ptr];
603 604 605

	if (reset)
		memset(tfd, 0, sizeof(*tfd));
Z
Zhu Yi 已提交
606 607 608

	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));

609
	if (count >= NUM_TFD_CHUNKS || count < 0) {
610
		IL_ERR("Error can not send more than %d chunks\n",
611
		       NUM_TFD_CHUNKS);
Z
Zhu Yi 已提交
612 613 614
		return -EINVAL;
	}

W
Winkler, Tomas 已提交
615 616
	tfd->tbs[count].addr = cpu_to_le32(addr);
	tfd->tbs[count].len = cpu_to_le32(len);
Z
Zhu Yi 已提交
617 618 619

	count++;

620 621
	tfd->control_flags =
	    cpu_to_le32(TFD_CTL_COUNT_SET(count) | TFD_CTL_PAD_SET(pad));
Z
Zhu Yi 已提交
622 623 624 625 626

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
627
 * il3945_hw_txq_free_tfd - Free one TFD, those at idx [txq->q.read_ptr]
Z
Zhu Yi 已提交
628
 *
S
Stanislaw Gruszka 已提交
629
 * Does NOT advance any idxes
Z
Zhu Yi 已提交
630
 */
631 632
void
il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
Z
Zhu Yi 已提交
633
{
S
Stanislaw Gruszka 已提交
634
	struct il3945_tfd *tfd_tmp = (struct il3945_tfd *)txq->tfds;
S
Stanislaw Gruszka 已提交
635 636
	int idx = txq->q.read_ptr;
	struct il3945_tfd *tfd = &tfd_tmp[idx];
S
Stanislaw Gruszka 已提交
637
	struct pci_dev *dev = il->pci_dev;
Z
Zhu Yi 已提交
638 639 640 641
	int i;
	int counter;

	/* sanity check */
W
Winkler, Tomas 已提交
642
	counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
Z
Zhu Yi 已提交
643
	if (counter > NUM_TFD_CHUNKS) {
644
		IL_ERR("Too many chunks: %i\n", counter);
Z
Zhu Yi 已提交
645
		/* @todo issue fatal error, it is quite serious situation */
646
		return;
Z
Zhu Yi 已提交
647 648
	}

649 650
	/* Unmap tx_cmd */
	if (counter)
651 652 653
		pci_unmap_single(dev, dma_unmap_addr(&txq->meta[idx], mapping),
				 dma_unmap_len(&txq->meta[idx], len),
				 PCI_DMA_TODEVICE);
654

Z
Zhu Yi 已提交
655 656
	/* unmap chunks if any */

657
	for (i = 1; i < counter; i++)
W
Winkler, Tomas 已提交
658
		pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
659 660
				 le32_to_cpu(tfd->tbs[i].len),
				 PCI_DMA_TODEVICE);
J
Johannes Berg 已提交
661

662 663 664
	/* free SKB */
	if (txq->txb) {
		struct sk_buff *skb;
J
Johannes Berg 已提交
665

666 667 668 669 670 671
		skb = txq->txb[txq->q.read_ptr].skb;

		/* can be called from irqs-disabled context */
		if (skb) {
			dev_kfree_skb_any(skb);
			txq->txb[txq->q.read_ptr].skb = NULL;
Z
Zhu Yi 已提交
672 673 674 675 676
		}
	}
}

/**
S
Stanislaw Gruszka 已提交
677
 * il3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
Z
Zhu Yi 已提交
678 679
 *
*/
680 681 682 683
void
il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
			    struct ieee80211_tx_info *info,
			    struct ieee80211_hdr *hdr, int sta_id, int tx_id)
Z
Zhu Yi 已提交
684
{
S
Stanislaw Gruszka 已提交
685
	u16 hw_value = ieee80211_get_tx_rate(il->hw, info)->hw_value;
S
Stanislaw Gruszka 已提交
686
	u16 rate_idx = min(hw_value & 0xffff, RATE_COUNT_3945);
Z
Zhu Yi 已提交
687 688 689 690 691
	u16 rate_mask;
	int rate;
	u8 rts_retry_limit;
	u8 data_retry_limit;
	__le32 tx_flags;
692
	__le16 fc = hdr->frame_control;
S
Stanislaw Gruszka 已提交
693
	struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
Z
Zhu Yi 已提交
694

S
Stanislaw Gruszka 已提交
695
	rate = il3945_rates[rate_idx].plcp;
A
Abhijeet Kolekar 已提交
696
	tx_flags = tx_cmd->tx_flags;
Z
Zhu Yi 已提交
697 698

	/* We need to figure out how to get the sta->supp_rates while
699
	 * in this running context */
S
Stanislaw Gruszka 已提交
700
	rate_mask = RATES_MASK_3945;
A
Abhijeet Kolekar 已提交
701

702
	/* Set retry limit on DATA packets and Probe Responses */
A
Abhijeet Kolekar 已提交
703 704 705
	if (ieee80211_is_probe_resp(fc))
		data_retry_limit = 3;
	else
S
Stanislaw Gruszka 已提交
706
		data_retry_limit = IL_DEFAULT_TX_RETRY;
A
Abhijeet Kolekar 已提交
707 708
	tx_cmd->data_retry_limit = data_retry_limit;

709
	if (tx_id >= IL39_CMD_QUEUE_NUM)
Z
Zhu Yi 已提交
710 711 712 713
		rts_retry_limit = 3;
	else
		rts_retry_limit = 7;

A
Abhijeet Kolekar 已提交
714 715 716
	if (data_retry_limit < rts_retry_limit)
		rts_retry_limit = data_retry_limit;
	tx_cmd->rts_retry_limit = rts_retry_limit;
Z
Zhu Yi 已提交
717

A
Abhijeet Kolekar 已提交
718 719
	tx_cmd->rate = rate;
	tx_cmd->tx_flags = tx_flags;
Z
Zhu Yi 已提交
720 721

	/* OFDM */
A
Abhijeet Kolekar 已提交
722
	tx_cmd->supp_rates[0] =
723
	    ((rate_mask & IL_OFDM_RATES_MASK) >> IL_FIRST_OFDM_RATE) & 0xFF;
Z
Zhu Yi 已提交
724 725

	/* CCK */
A
Abhijeet Kolekar 已提交
726
	tx_cmd->supp_rates[1] = (rate_mask & 0xF);
Z
Zhu Yi 已提交
727

728
	D_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
729 730 731
	       "cck/ofdm mask: 0x%x/0x%x\n", sta_id, tx_cmd->rate,
	       le32_to_cpu(tx_cmd->tx_flags), tx_cmd->supp_rates[1],
	       tx_cmd->supp_rates[0]);
Z
Zhu Yi 已提交
732 733
}

734 735
static u8
il3945_sync_sta(struct il_priv *il, int sta_id, u16 tx_rate)
Z
Zhu Yi 已提交
736 737
{
	unsigned long flags_spin;
S
Stanislaw Gruszka 已提交
738
	struct il_station_entry *station;
Z
Zhu Yi 已提交
739

S
Stanislaw Gruszka 已提交
740 741
	if (sta_id == IL_INVALID_STATION)
		return IL_INVALID_STATION;
Z
Zhu Yi 已提交
742

S
Stanislaw Gruszka 已提交
743 744
	spin_lock_irqsave(&il->sta_lock, flags_spin);
	station = &il->stations[sta_id];
Z
Zhu Yi 已提交
745 746 747 748

	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
	station->sta.mode = STA_CONTROL_MODIFY_MSK;
S
Stanislaw Gruszka 已提交
749 750
	il_send_add_sta(il, &station->sta, CMD_ASYNC);
	spin_unlock_irqrestore(&il->sta_lock, flags_spin);
Z
Zhu Yi 已提交
751

752
	D_RATE("SCALE sync station %d to rate %d\n", sta_id, tx_rate);
Z
Zhu Yi 已提交
753 754 755
	return sta_id;
}

756 757
static void
il3945_set_pwr_vmain(struct il_priv *il)
Z
Zhu Yi 已提交
758
{
759 760 761 762
/*
 * (for documentation purposes)
 * to set power to V_AUX, do

S
Stanislaw Gruszka 已提交
763 764
		if (pci_pme_capable(il->pci_dev, PCI_D3cold)) {
			il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
Z
Zhu Yi 已提交
765 766 767
					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
					~APMG_PS_CTRL_MSK_PWR_SRC);

768
			_il_poll_bit(il, CSR_GPIO_IN,
Z
Zhu Yi 已提交
769 770
				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
771
		}
772
 */
Z
Zhu Yi 已提交
773

S
Stanislaw Gruszka 已提交
774
	il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
775 776
			      APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
			      ~APMG_PS_CTRL_MSK_PWR_SRC);
Z
Zhu Yi 已提交
777

S
Stanislaw Gruszka 已提交
778 779
	_il_poll_bit(il, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
Z
Zhu Yi 已提交
780 781
}

782 783
static int
il3945_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
Z
Zhu Yi 已提交
784
{
785
	il_wr(il, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
786
	il_wr(il, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
787 788
	il_wr(il, FH39_RCSR_WPTR(0), 0);
	il_wr(il, FH39_RCSR_CONFIG(0),
789 790 791 792 793 794 795 796 797
	      FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
	      FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
	      FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
	      FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | (RX_QUEUE_SIZE_LOG
							       <<
							       FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE)
	      | FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | (1 <<
								 FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH)
	      | FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
Z
Zhu Yi 已提交
798 799

	/* fake read to flush all prev I/O */
800
	il_rd(il, FH39_RSSR_CTRL);
Z
Zhu Yi 已提交
801 802 803 804

	return 0;
}

805 806
static int
il3945_tx_reset(struct il_priv *il)
Z
Zhu Yi 已提交
807 808 809
{

	/* bypass mode */
810
	il_wr_prph(il, ALM_SCD_MODE_REG, 0x2);
Z
Zhu Yi 已提交
811 812

	/* RA 0 is active */
813
	il_wr_prph(il, ALM_SCD_ARASTAT_REG, 0x01);
Z
Zhu Yi 已提交
814 815

	/* all 6 fifo are active */
816
	il_wr_prph(il, ALM_SCD_TXFACT_REG, 0x3f);
Z
Zhu Yi 已提交
817

818 819 820 821
	il_wr_prph(il, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
	il_wr_prph(il, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
	il_wr_prph(il, ALM_SCD_TXF4MF_REG, 0x000004);
	il_wr_prph(il, ALM_SCD_TXF5MF_REG, 0x000005);
Z
Zhu Yi 已提交
822

823
	il_wr(il, FH39_TSSR_CBB_BASE, il->_3945.shared_phys);
Z
Zhu Yi 已提交
824

825
	il_wr(il, FH39_TSSR_MSG_CONFIG,
826 827 828 829 830 831 832
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
	      FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
Z
Zhu Yi 已提交
833 834 835 836 837

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
838
 * il3945_txq_ctx_reset - Reset TX queue context
Z
Zhu Yi 已提交
839 840 841
 *
 * Destroys all DMA structures and initialize them again
 */
842 843
static int
il3945_txq_ctx_reset(struct il_priv *il)
Z
Zhu Yi 已提交
844 845 846 847
{
	int rc;
	int txq_id, slots_num;

S
Stanislaw Gruszka 已提交
848
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
849

850
	/* allocate tx queue structure */
S
Stanislaw Gruszka 已提交
851
	rc = il_alloc_txq_mem(il);
852 853 854
	if (rc)
		return rc;

Z
Zhu Yi 已提交
855
	/* Tx CMD queue */
S
Stanislaw Gruszka 已提交
856
	rc = il3945_tx_reset(il);
Z
Zhu Yi 已提交
857 858 859 860
	if (rc)
		goto error;

	/* Tx queue(s) */
S
Stanislaw Gruszka 已提交
861
	for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
862 863 864 865
		slots_num =
		    (txq_id ==
		     IL39_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
		rc = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id);
Z
Zhu Yi 已提交
866
		if (rc) {
867
			IL_ERR("Tx %d queue init failed\n", txq_id);
Z
Zhu Yi 已提交
868 869 870 871 872 873
			goto error;
		}
	}

	return rc;

874
error:
S
Stanislaw Gruszka 已提交
875
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
876 877 878
	return rc;
}

B
Ben Cahill 已提交
879
/*
880
 * Start up 3945's basic functionality after it has been reset
S
Stanislaw Gruszka 已提交
881
 * (e.g. after platform boot, or shutdown via il_apm_stop())
B
Ben Cahill 已提交
882 883
 * NOTE:  This does not load uCode nor start the embedded processor
 */
884 885
static int
il3945_apm_init(struct il_priv *il)
Z
Zhu Yi 已提交
886
{
S
Stanislaw Gruszka 已提交
887
	int ret = il_apm_init(il);
K
Kolekar, Abhijeet 已提交
888

B
Ben Cahill 已提交
889
	/* Clear APMG (NIC's internal power management) interrupts */
890 891
	il_wr_prph(il, APMG_RTC_INT_MSK_REG, 0x0);
	il_wr_prph(il, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
B
Ben Cahill 已提交
892 893

	/* Reset radio chip */
894
	il_set_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
B
Ben Cahill 已提交
895
	udelay(5);
896
	il_clear_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
B
Ben Cahill 已提交
897

K
Kolekar, Abhijeet 已提交
898 899
	return ret;
}
Z
Zhu Yi 已提交
900

901 902
static void
il3945_nic_config(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
903
{
S
Stanislaw Gruszka 已提交
904
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
K
Kolekar, Abhijeet 已提交
905
	unsigned long flags;
S
Stanislaw Gruszka 已提交
906
	u8 rev_id = il->pci_dev->revision;
Z
Zhu Yi 已提交
907

S
Stanislaw Gruszka 已提交
908
	spin_lock_irqsave(&il->lock, flags);
Z
Zhu Yi 已提交
909

910
	/* Determine HW type */
911
	D_INFO("HW Revision ID = 0x%X\n", rev_id);
912

Z
Zhu Yi 已提交
913
	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
914
		D_INFO("RTP type\n");
Z
Zhu Yi 已提交
915
	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
916
		D_INFO("3945 RADIO-MB type\n");
S
Stanislaw Gruszka 已提交
917
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
918
			   CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
Z
Zhu Yi 已提交
919
	} else {
920
		D_INFO("3945 RADIO-MM type\n");
S
Stanislaw Gruszka 已提交
921
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
922
			   CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
Z
Zhu Yi 已提交
923 924
	}

925
	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
926
		D_INFO("SKU OP mode is mrc\n");
S
Stanislaw Gruszka 已提交
927
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
928
			   CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
Z
Zhu Yi 已提交
929
	} else
930
		D_INFO("SKU OP mode is basic\n");
Z
Zhu Yi 已提交
931

932
	if ((eeprom->board_revision & 0xF0) == 0xD0) {
933
		D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
S
Stanislaw Gruszka 已提交
934
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
935
			   CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
Z
Zhu Yi 已提交
936
	} else {
937
		D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
S
Stanislaw Gruszka 已提交
938
		il_clear_bit(il, CSR_HW_IF_CONFIG_REG,
939
			     CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
Z
Zhu Yi 已提交
940 941
	}

942
	if (eeprom->almgor_m_version <= 1) {
S
Stanislaw Gruszka 已提交
943
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
944
			   CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
945
		D_INFO("Card M type A version is 0x%X\n",
946
		       eeprom->almgor_m_version);
Z
Zhu Yi 已提交
947
	} else {
948
		D_INFO("Card M type B version is 0x%X\n",
949
		       eeprom->almgor_m_version);
S
Stanislaw Gruszka 已提交
950
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
951
			   CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
Z
Zhu Yi 已提交
952
	}
S
Stanislaw Gruszka 已提交
953
	spin_unlock_irqrestore(&il->lock, flags);
Z
Zhu Yi 已提交
954

955
	if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
956
		D_RF_KILL("SW RF KILL supported in EEPROM.\n");
Z
Zhu Yi 已提交
957

958
	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
959
		D_RF_KILL("HW RF KILL supported in EEPROM.\n");
K
Kolekar, Abhijeet 已提交
960 961
}

962 963
int
il3945_hw_nic_init(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
964 965 966
{
	int rc;
	unsigned long flags;
S
Stanislaw Gruszka 已提交
967
	struct il_rx_queue *rxq = &il->rxq;
K
Kolekar, Abhijeet 已提交
968

S
Stanislaw Gruszka 已提交
969 970 971
	spin_lock_irqsave(&il->lock, flags);
	il->cfg->ops->lib->apm_ops.init(il);
	spin_unlock_irqrestore(&il->lock, flags);
K
Kolekar, Abhijeet 已提交
972

S
Stanislaw Gruszka 已提交
973
	il3945_set_pwr_vmain(il);
K
Kolekar, Abhijeet 已提交
974

S
Stanislaw Gruszka 已提交
975
	il->cfg->ops->lib->apm_ops.config(il);
Z
Zhu Yi 已提交
976 977 978

	/* Allocate the RX queue, or reset if it is already allocated */
	if (!rxq->bd) {
S
Stanislaw Gruszka 已提交
979
		rc = il_rx_queue_alloc(il);
Z
Zhu Yi 已提交
980
		if (rc) {
981
			IL_ERR("Unable to initialize Rx queue\n");
Z
Zhu Yi 已提交
982 983 984
			return -ENOMEM;
		}
	} else
S
Stanislaw Gruszka 已提交
985
		il3945_rx_queue_reset(il, rxq);
Z
Zhu Yi 已提交
986

S
Stanislaw Gruszka 已提交
987
	il3945_rx_replenish(il);
Z
Zhu Yi 已提交
988

S
Stanislaw Gruszka 已提交
989
	il3945_rx_init(il, rxq);
Z
Zhu Yi 已提交
990 991

	/* Look at using this instead:
992 993 994
	   rxq->need_update = 1;
	   il_rx_queue_update_write_ptr(il, rxq);
	 */
Z
Zhu Yi 已提交
995

996
	il_wr(il, FH39_RCSR_WPTR(0), rxq->write & ~7);
Z
Zhu Yi 已提交
997

S
Stanislaw Gruszka 已提交
998
	rc = il3945_txq_ctx_reset(il);
Z
Zhu Yi 已提交
999 1000 1001
	if (rc)
		return rc;

S
Stanislaw Gruszka 已提交
1002
	set_bit(S_INIT, &il->status);
Z
Zhu Yi 已提交
1003 1004 1005 1006 1007

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
1008
 * il3945_hw_txq_ctx_free - Free TXQ Context
Z
Zhu Yi 已提交
1009 1010 1011
 *
 * Destroy all TX DMA queues and structures
 */
1012 1013
void
il3945_hw_txq_ctx_free(struct il_priv *il)
Z
Zhu Yi 已提交
1014 1015 1016 1017
{
	int txq_id;

	/* Tx queues */
S
Stanislaw Gruszka 已提交
1018
	if (il->txq)
1019
		for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
1020
			if (txq_id == IL39_CMD_QUEUE_NUM)
S
Stanislaw Gruszka 已提交
1021
				il_cmd_queue_free(il);
1022
			else
S
Stanislaw Gruszka 已提交
1023
				il_tx_queue_free(il, txq_id);
1024

1025
	/* free tx queue structure */
S
Stanislaw Gruszka 已提交
1026
	il_txq_mem(il);
Z
Zhu Yi 已提交
1027 1028
}

1029 1030
void
il3945_hw_txq_ctx_stop(struct il_priv *il)
Z
Zhu Yi 已提交
1031
{
1032
	int txq_id;
Z
Zhu Yi 已提交
1033 1034

	/* stop SCD */
1035 1036
	il_wr_prph(il, ALM_SCD_MODE_REG, 0);
	il_wr_prph(il, ALM_SCD_TXFACT_REG, 0);
Z
Zhu Yi 已提交
1037 1038

	/* reset TFD queues */
S
Stanislaw Gruszka 已提交
1039
	for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
1040 1041
		il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0);
		il_poll_bit(il, FH39_TSSR_TX_STATUS,
1042 1043
			    FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
			    1000);
Z
Zhu Yi 已提交
1044 1045
	}

S
Stanislaw Gruszka 已提交
1046
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
1047 1048 1049
}

/**
S
Stanislaw Gruszka 已提交
1050
 * il3945_hw_reg_adjust_power_by_temp
S
Stanislaw Gruszka 已提交
1051
 * return idx delta into power gain settings table
1052
*/
1053 1054
static int
il3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
Z
Zhu Yi 已提交
1055 1056 1057 1058 1059
{
	return (new_reading - old_reading) * (-11) / 100;
}

/**
S
Stanislaw Gruszka 已提交
1060
 * il3945_hw_reg_temp_out_of_range - Keep temperature in sane range
Z
Zhu Yi 已提交
1061
 */
1062 1063
static inline int
il3945_hw_reg_temp_out_of_range(int temperature)
Z
Zhu Yi 已提交
1064
{
1065
	return (temperature < -260 || temperature > 25) ? 1 : 0;
Z
Zhu Yi 已提交
1066 1067
}

1068 1069
int
il3945_hw_get_temperature(struct il_priv *il)
Z
Zhu Yi 已提交
1070
{
1071
	return _il_rd(il, CSR_UCODE_DRV_GP2);
Z
Zhu Yi 已提交
1072 1073 1074
}

/**
S
Stanislaw Gruszka 已提交
1075
 * il3945_hw_reg_txpower_get_temperature
1076 1077
 * get the current temperature by reading from NIC
*/
1078 1079
static int
il3945_hw_reg_txpower_get_temperature(struct il_priv *il)
Z
Zhu Yi 已提交
1080
{
S
Stanislaw Gruszka 已提交
1081
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Z
Zhu Yi 已提交
1082 1083
	int temperature;

S
Stanislaw Gruszka 已提交
1084
	temperature = il3945_hw_get_temperature(il);
Z
Zhu Yi 已提交
1085 1086 1087

	/* driver's okay range is -260 to +25.
	 *   human readable okay range is 0 to +285 */
1088
	D_INFO("Temperature: %d\n", temperature + IL_TEMP_CONVERT);
Z
Zhu Yi 已提交
1089 1090

	/* handle insane temp reading */
S
Stanislaw Gruszka 已提交
1091
	if (il3945_hw_reg_temp_out_of_range(temperature)) {
1092
		IL_ERR("Error bad temperature value  %d\n", temperature);
Z
Zhu Yi 已提交
1093 1094 1095

		/* if really really hot(?),
		 *   substitute the 3rd band/group's temp measured at factory */
S
Stanislaw Gruszka 已提交
1096
		if (il->last_temperature > 100)
1097
			temperature = eeprom->groups[2].temperature;
1098
		else		/* else use most recent "sane" value from driver */
S
Stanislaw Gruszka 已提交
1099
			temperature = il->last_temperature;
Z
Zhu Yi 已提交
1100 1101 1102 1103 1104 1105 1106 1107
	}

	return temperature;	/* raw, not "human readable" */
}

/* Adjust Txpower only if temperature variance is greater than threshold.
 *
 * Both are lower than older versions' 9 degrees */
S
Stanislaw Gruszka 已提交
1108
#define IL_TEMPERATURE_LIMIT_TIMER   6
Z
Zhu Yi 已提交
1109 1110

/**
S
Stanislaw Gruszka 已提交
1111
 * il3945_is_temp_calib_needed - determines if new calibration is needed
Z
Zhu Yi 已提交
1112 1113 1114 1115
 *
 * records new temperature in tx_mgr->temperature.
 * replaces tx_mgr->last_temperature *only* if calib needed
 *    (assumes caller will actually do the calibration!). */
1116 1117
static int
il3945_is_temp_calib_needed(struct il_priv *il)
Z
Zhu Yi 已提交
1118 1119 1120
{
	int temp_diff;

S
Stanislaw Gruszka 已提交
1121 1122
	il->temperature = il3945_hw_reg_txpower_get_temperature(il);
	temp_diff = il->temperature - il->last_temperature;
Z
Zhu Yi 已提交
1123 1124 1125

	/* get absolute value */
	if (temp_diff < 0) {
1126
		D_POWER("Getting cooler, delta %d,\n", temp_diff);
Z
Zhu Yi 已提交
1127 1128
		temp_diff = -temp_diff;
	} else if (temp_diff == 0)
1129
		D_POWER("Same temp,\n");
Z
Zhu Yi 已提交
1130
	else
1131
		D_POWER("Getting warmer, delta %d,\n", temp_diff);
Z
Zhu Yi 已提交
1132 1133

	/* if we don't need calibration, *don't* update last_temperature */
S
Stanislaw Gruszka 已提交
1134
	if (temp_diff < IL_TEMPERATURE_LIMIT_TIMER) {
1135
		D_POWER("Timed thermal calib not needed\n");
Z
Zhu Yi 已提交
1136 1137 1138
		return 0;
	}

1139
	D_POWER("Timed thermal calib needed\n");
Z
Zhu Yi 已提交
1140 1141 1142

	/* assume that caller will actually do calib ...
	 *   update the "last temperature" value */
S
Stanislaw Gruszka 已提交
1143
	il->last_temperature = il->temperature;
Z
Zhu Yi 已提交
1144 1145 1146
	return 1;
}

S
Stanislaw Gruszka 已提交
1147 1148
#define IL_MAX_GAIN_ENTRIES 78
#define IL_CCK_FROM_OFDM_POWER_DIFF  -5
S
Stanislaw Gruszka 已提交
1149
#define IL_CCK_FROM_OFDM_IDX_DIFF (10)
Z
Zhu Yi 已提交
1150 1151 1152

/* radio and DSP power table, each step is 1/2 dB.
 * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
S
Stanislaw Gruszka 已提交
1153
static struct il3945_tx_power power_gain_table[2][IL_MAX_GAIN_ENTRIES] = {
Z
Zhu Yi 已提交
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
	{
	 {251, 127},		/* 2.4 GHz, highest power */
	 {251, 127},
	 {251, 127},
	 {251, 127},
	 {251, 125},
	 {251, 110},
	 {251, 105},
	 {251, 98},
	 {187, 125},
	 {187, 115},
	 {187, 108},
	 {187, 99},
	 {243, 119},
	 {243, 111},
	 {243, 105},
	 {243, 97},
	 {243, 92},
	 {211, 106},
	 {211, 100},
	 {179, 120},
	 {179, 113},
	 {179, 107},
	 {147, 125},
	 {147, 119},
	 {147, 112},
	 {147, 106},
	 {147, 101},
	 {147, 97},
	 {147, 91},
	 {115, 107},
	 {235, 121},
	 {235, 115},
	 {235, 109},
	 {203, 127},
	 {203, 121},
	 {203, 115},
	 {203, 108},
	 {203, 102},
	 {203, 96},
	 {203, 92},
	 {171, 110},
	 {171, 104},
	 {171, 98},
	 {139, 116},
	 {227, 125},
	 {227, 119},
	 {227, 113},
	 {227, 107},
	 {227, 101},
	 {227, 96},
	 {195, 113},
	 {195, 106},
	 {195, 102},
	 {195, 95},
	 {163, 113},
	 {163, 106},
	 {163, 102},
	 {163, 95},
	 {131, 113},
	 {131, 106},
	 {131, 102},
	 {131, 95},
	 {99, 113},
	 {99, 106},
	 {99, 102},
	 {99, 95},
	 {67, 113},
	 {67, 106},
	 {67, 102},
	 {67, 95},
	 {35, 113},
	 {35, 106},
	 {35, 102},
	 {35, 95},
	 {3, 113},
	 {3, 106},
	 {3, 102},
S
Stanislaw Gruszka 已提交
1232 1233
	 {3, 95}		/* 2.4 GHz, lowest power */
	},
Z
Zhu Yi 已提交
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
	{
	 {251, 127},		/* 5.x GHz, highest power */
	 {251, 120},
	 {251, 114},
	 {219, 119},
	 {219, 101},
	 {187, 113},
	 {187, 102},
	 {155, 114},
	 {155, 103},
	 {123, 117},
	 {123, 107},
	 {123, 99},
	 {123, 92},
	 {91, 108},
	 {59, 125},
	 {59, 118},
	 {59, 109},
	 {59, 102},
	 {59, 96},
	 {59, 90},
	 {27, 104},
	 {27, 98},
	 {27, 92},
	 {115, 118},
	 {115, 111},
	 {115, 104},
	 {83, 126},
	 {83, 121},
	 {83, 113},
	 {83, 105},
	 {83, 99},
	 {51, 118},
	 {51, 111},
	 {51, 104},
	 {51, 98},
	 {19, 116},
	 {19, 109},
	 {19, 102},
	 {19, 98},
	 {19, 93},
	 {171, 113},
	 {171, 107},
	 {171, 99},
	 {139, 120},
	 {139, 113},
	 {139, 107},
	 {139, 99},
	 {107, 120},
	 {107, 113},
	 {107, 107},
	 {107, 99},
	 {75, 120},
	 {75, 113},
	 {75, 107},
	 {75, 99},
	 {43, 120},
	 {43, 113},
	 {43, 107},
	 {43, 99},
	 {11, 120},
	 {11, 113},
	 {11, 107},
	 {11, 99},
	 {131, 107},
	 {131, 99},
	 {99, 120},
	 {99, 113},
	 {99, 107},
	 {99, 99},
	 {67, 120},
	 {67, 113},
	 {67, 107},
	 {67, 99},
	 {35, 120},
	 {35, 113},
	 {35, 107},
	 {35, 99},
S
Stanislaw Gruszka 已提交
1312 1313
	 {3, 120}		/* 5.x GHz, lowest power */
	}
Z
Zhu Yi 已提交
1314 1315
};

1316 1317
static inline u8
il3945_hw_reg_fix_power_idx(int idx)
Z
Zhu Yi 已提交
1318
{
S
Stanislaw Gruszka 已提交
1319
	if (idx < 0)
Z
Zhu Yi 已提交
1320
		return 0;
S
Stanislaw Gruszka 已提交
1321
	if (idx >= IL_MAX_GAIN_ENTRIES)
S
Stanislaw Gruszka 已提交
1322
		return IL_MAX_GAIN_ENTRIES - 1;
S
Stanislaw Gruszka 已提交
1323
	return (u8) idx;
Z
Zhu Yi 已提交
1324 1325 1326 1327 1328 1329
}

/* Kick off thermal recalibration check every 60 seconds */
#define REG_RECALIB_PERIOD (60)

/**
S
Stanislaw Gruszka 已提交
1330
 * il3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
Z
Zhu Yi 已提交
1331 1332 1333 1334
 *
 * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
 * or 6 Mbit (OFDM) rates.
 */
1335 1336
static void
il3945_hw_reg_set_scan_power(struct il_priv *il, u32 scan_tbl_idx, s32 rate_idx,
S
Stanislaw Gruszka 已提交
1337
			     const s8 *clip_pwrs,
1338
			     struct il_channel_info *ch_info, int band_idx)
Z
Zhu Yi 已提交
1339
{
S
Stanislaw Gruszka 已提交
1340
	struct il3945_scan_power_info *scan_power_info;
Z
Zhu Yi 已提交
1341
	s8 power;
S
Stanislaw Gruszka 已提交
1342
	u8 power_idx;
Z
Zhu Yi 已提交
1343

S
Stanislaw Gruszka 已提交
1344
	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_idx];
Z
Zhu Yi 已提交
1345 1346 1347 1348

	/* use this channel group's 6Mbit clipping/saturation pwr,
	 *   but cap at regulatory scan power restriction (set during init
	 *   based on eeprom channel data) for this channel.  */
S
Stanislaw Gruszka 已提交
1349
	power = min(ch_info->scan_power, clip_pwrs[RATE_6M_IDX_TBL]);
Z
Zhu Yi 已提交
1350

S
Stanislaw Gruszka 已提交
1351
	power = min(power, il->tx_power_user_lmt);
Z
Zhu Yi 已提交
1352 1353 1354 1355
	scan_power_info->requested_power = power;

	/* find difference between new scan *power* and current "normal"
	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
S
Stanislaw Gruszka 已提交
1356
	 *   current "normal" temperature-compensated Tx power *idx* for
Z
Zhu Yi 已提交
1357
	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
S
Stanislaw Gruszka 已提交
1358
	 *   *idx*. */
1359 1360 1361 1362 1363 1364 1365
	power_idx =
	    ch_info->power_info[rate_idx].power_table_idx - (power -
							     ch_info->
							     power_info
							     [RATE_6M_IDX_TBL].
							     requested_power) *
	    2;
Z
Zhu Yi 已提交
1366

S
Stanislaw Gruszka 已提交
1367
	/* store reference idx that we use when adjusting *all* scan
Z
Zhu Yi 已提交
1368 1369 1370
	 *   powers.  So we can accommodate user (all channel) or spectrum
	 *   management (single channel) power changes "between" temperature
	 *   feedback compensation procedures.
S
Stanislaw Gruszka 已提交
1371
	 * don't force fit this reference idx into gain table; it may be a
Z
Zhu Yi 已提交
1372 1373 1374 1375 1376
	 *   negative number.  This will help avoid errors when we're at
	 *   the lower bounds (highest gains, for warmest temperatures)
	 *   of the table. */

	/* don't exceed table bounds for "real" setting */
S
Stanislaw Gruszka 已提交
1377
	power_idx = il3945_hw_reg_fix_power_idx(power_idx);
Z
Zhu Yi 已提交
1378

S
Stanislaw Gruszka 已提交
1379
	scan_power_info->power_table_idx = power_idx;
Z
Zhu Yi 已提交
1380
	scan_power_info->tpc.tx_gain =
S
Stanislaw Gruszka 已提交
1381
	    power_gain_table[band_idx][power_idx].tx_gain;
Z
Zhu Yi 已提交
1382
	scan_power_info->tpc.dsp_atten =
S
Stanislaw Gruszka 已提交
1383
	    power_gain_table[band_idx][power_idx].dsp_atten;
Z
Zhu Yi 已提交
1384 1385 1386
}

/**
S
Stanislaw Gruszka 已提交
1387
 * il3945_send_tx_power - fill in Tx Power command with gain settings
Z
Zhu Yi 已提交
1388 1389 1390 1391
 *
 * Configures power settings for all rates for the current channel,
 * using values from channel info struct, and send to NIC
 */
1392 1393
static int
il3945_send_tx_power(struct il_priv *il)
Z
Zhu Yi 已提交
1394
{
1395
	int rate_idx, i;
S
Stanislaw Gruszka 已提交
1396 1397
	const struct il_channel_info *ch_info = NULL;
	struct il3945_txpowertable_cmd txpower = {
1398
		.channel = il->ctx.active.channel,
Z
Zhu Yi 已提交
1399
	};
1400 1401
	u16 chan;

1402 1403 1404
	if (WARN_ONCE
	    (test_bit(S_SCAN_HW, &il->status),
	     "TX Power requested while scanning!\n"))
1405 1406
		return -EAGAIN;

1407
	chan = le16_to_cpu(il->ctx.active.channel);
Z
Zhu Yi 已提交
1408

S
Stanislaw Gruszka 已提交
1409 1410
	txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
	ch_info = il_get_channel_info(il, il->band, chan);
Z
Zhu Yi 已提交
1411
	if (!ch_info) {
1412 1413
		IL_ERR("Failed to get channel info for channel %d [%d]\n", chan,
		       il->band);
Z
Zhu Yi 已提交
1414 1415 1416
		return -EINVAL;
	}

S
Stanislaw Gruszka 已提交
1417
	if (!il_is_channel_valid(ch_info)) {
1418
		D_POWER("Not calling TX_PWR_TBL_CMD on " "non-Tx channel.\n");
Z
Zhu Yi 已提交
1419 1420 1421 1422
		return 0;
	}

	/* fill cmd with power settings for all rates for current channel */
1423
	/* Fill OFDM rate */
S
Stanislaw Gruszka 已提交
1424
	for (rate_idx = IL_FIRST_OFDM_RATE, i = 0;
1425
	     rate_idx <= IL39_LAST_OFDM_RATE; rate_idx++, i++) {
1426 1427

		txpower.power[i].tpc = ch_info->power_info[i].tpc;
S
Stanislaw Gruszka 已提交
1428
		txpower.power[i].rate = il3945_rates[rate_idx].plcp;
Z
Zhu Yi 已提交
1429

1430
		D_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
1431 1432 1433
			le16_to_cpu(txpower.channel), txpower.band,
			txpower.power[i].tpc.tx_gain,
			txpower.power[i].tpc.dsp_atten, txpower.power[i].rate);
1434 1435
	}
	/* Fill CCK rates */
1436 1437
	for (rate_idx = IL_FIRST_CCK_RATE; rate_idx <= IL_LAST_CCK_RATE;
	     rate_idx++, i++) {
1438
		txpower.power[i].tpc = ch_info->power_info[i].tpc;
S
Stanislaw Gruszka 已提交
1439
		txpower.power[i].rate = il3945_rates[rate_idx].plcp;
1440

1441
		D_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
1442 1443 1444
			le16_to_cpu(txpower.channel), txpower.band,
			txpower.power[i].tpc.tx_gain,
			txpower.power[i].tpc.dsp_atten, txpower.power[i].rate);
Z
Zhu Yi 已提交
1445 1446
	}

1447
	return il_send_cmd_pdu(il, C_TX_PWR_TBL,
1448 1449
			       sizeof(struct il3945_txpowertable_cmd),
			       &txpower);
Z
Zhu Yi 已提交
1450 1451 1452 1453

}

/**
S
Stanislaw Gruszka 已提交
1454
 * il3945_hw_reg_set_new_power - Configures power tables at new levels
Z
Zhu Yi 已提交
1455 1456
 * @ch_info: Channel to update.  Uses power_info.requested_power.
 *
S
Stanislaw Gruszka 已提交
1457
 * Replace requested_power and base_power_idx ch_info fields for
Z
Zhu Yi 已提交
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
 * one channel.
 *
 * Called if user or spectrum management changes power preferences.
 * Takes into account h/w and modulation limitations (clip power).
 *
 * This does *not* send anything to NIC, just sets up ch_info for one channel.
 *
 * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
 *	 properly fill out the scan powers, and actual h/w gain settings,
 *	 and send changes to NIC
 */
1469 1470
static int
il3945_hw_reg_set_new_power(struct il_priv *il, struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1471
{
S
Stanislaw Gruszka 已提交
1472
	struct il3945_channel_power_info *power_info;
Z
Zhu Yi 已提交
1473 1474 1475 1476 1477 1478
	int power_changed = 0;
	int i;
	const s8 *clip_pwrs;
	int power;

	/* Get this chnlgrp's rate-to-max/clip-powers table */
S
Stanislaw Gruszka 已提交
1479
	clip_pwrs = il->_3945.clip_groups[ch_info->group_idx].clip_powers;
Z
Zhu Yi 已提交
1480 1481 1482 1483 1484

	/* Get this channel's rate-to-current-power settings table */
	power_info = ch_info->power_info;

	/* update OFDM Txpower settings */
1485
	for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++, ++power_info) {
Z
Zhu Yi 已提交
1486 1487 1488 1489 1490 1491 1492 1493
		int delta_idx;

		/* limit new power to be no more than h/w capability */
		power = min(ch_info->curr_txpow, clip_pwrs[i]);
		if (power == power_info->requested_power)
			continue;

		/* find difference between old and new requested powers,
S
Stanislaw Gruszka 已提交
1494
		 *    update base (non-temp-compensated) power idx */
Z
Zhu Yi 已提交
1495
		delta_idx = (power - power_info->requested_power) * 2;
S
Stanislaw Gruszka 已提交
1496
		power_info->base_power_idx -= delta_idx;
Z
Zhu Yi 已提交
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507

		/* save new requested power value */
		power_info->requested_power = power;

		power_changed = 1;
	}

	/* update CCK Txpower settings, based on OFDM 12M setting ...
	 *    ... all CCK power settings for a given channel are the *same*. */
	if (power_changed) {
		power =
1508 1509
		    ch_info->power_info[RATE_12M_IDX_TBL].requested_power +
		    IL_CCK_FROM_OFDM_POWER_DIFF;
Z
Zhu Yi 已提交
1510

S
Stanislaw Gruszka 已提交
1511
		/* do all CCK rates' il3945_channel_power_info structures */
S
Stanislaw Gruszka 已提交
1512
		for (i = RATE_1M_IDX_TBL; i <= RATE_11M_IDX_TBL; i++) {
Z
Zhu Yi 已提交
1513
			power_info->requested_power = power;
S
Stanislaw Gruszka 已提交
1514
			power_info->base_power_idx =
S
Stanislaw Gruszka 已提交
1515
			    ch_info->power_info[RATE_12M_IDX_TBL].
S
Stanislaw Gruszka 已提交
1516
			    base_power_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
Z
Zhu Yi 已提交
1517 1518 1519 1520 1521 1522 1523 1524
			++power_info;
		}
	}

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
1525
 * il3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
Z
Zhu Yi 已提交
1526 1527 1528 1529 1530
 *
 * NOTE: Returned power limit may be less (but not more) than requested,
 *	 based strictly on regulatory (eeprom and spectrum mgt) limitations
 *	 (no consideration for h/w clipping limitations).
 */
1531 1532
static int
il3945_hw_reg_get_ch_txpower_limit(struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1533 1534 1535 1536 1537 1538
{
	s8 max_power;

#if 0
	/* if we're using TGd limits, use lower of TGd or EEPROM */
	if (ch_info->tgd_data.max_power != 0)
1539 1540 1541
		max_power =
		    min(ch_info->tgd_data.max_power,
			ch_info->eeprom.max_power_avg);
Z
Zhu Yi 已提交
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551

	/* else just use EEPROM limits */
	else
#endif
		max_power = ch_info->eeprom.max_power_avg;

	return min(max_power, ch_info->max_power_avg);
}

/**
S
Stanislaw Gruszka 已提交
1552
 * il3945_hw_reg_comp_txpower_temp - Compensate for temperature
Z
Zhu Yi 已提交
1553 1554 1555 1556
 *
 * Compensate txpower settings of *all* channels for temperature.
 * This only accounts for the difference between current temperature
 *   and the factory calibration temperatures, and bases the new settings
S
Stanislaw Gruszka 已提交
1557
 *   on the channel's base_power_idx.
Z
Zhu Yi 已提交
1558 1559 1560
 *
 * If RxOn is "associated", this sends the new Txpower to NIC!
 */
1561 1562
static int
il3945_hw_reg_comp_txpower_temp(struct il_priv *il)
Z
Zhu Yi 已提交
1563
{
S
Stanislaw Gruszka 已提交
1564
	struct il_channel_info *ch_info = NULL;
S
Stanislaw Gruszka 已提交
1565
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1566
	int delta_idx;
1567
	const s8 *clip_pwrs;	/* array of h/w max power levels for each rate */
Z
Zhu Yi 已提交
1568
	u8 a_band;
S
Stanislaw Gruszka 已提交
1569 1570
	u8 rate_idx;
	u8 scan_tbl_idx;
Z
Zhu Yi 已提交
1571 1572
	u8 i;
	int ref_temp;
S
Stanislaw Gruszka 已提交
1573
	int temperature = il->temperature;
Z
Zhu Yi 已提交
1574

1575
	if (il->disable_tx_power_cal || test_bit(S_SCANNING, &il->status)) {
1576 1577 1578
		/* do not perform tx power calibration */
		return 0;
	}
Z
Zhu Yi 已提交
1579
	/* set up new Tx power info for each and every channel, 2.4 and 5.x */
S
Stanislaw Gruszka 已提交
1580 1581
	for (i = 0; i < il->channel_count; i++) {
		ch_info = &il->channel_info[i];
S
Stanislaw Gruszka 已提交
1582
		a_band = il_is_channel_a_band(ch_info);
Z
Zhu Yi 已提交
1583 1584

		/* Get this chnlgrp's factory calibration temperature */
1585
		ref_temp = (s16) eeprom->groups[ch_info->group_idx].temperature;
Z
Zhu Yi 已提交
1586

S
Stanislaw Gruszka 已提交
1587
		/* get power idx adjustment based on current and factory
Z
Zhu Yi 已提交
1588
		 * temps */
1589 1590
		delta_idx =
		    il3945_hw_reg_adjust_power_by_temp(temperature, ref_temp);
Z
Zhu Yi 已提交
1591 1592

		/* set tx power value for all rates, OFDM and CCK */
1593
		for (rate_idx = 0; rate_idx < RATE_COUNT_3945; rate_idx++) {
Z
Zhu Yi 已提交
1594
			int power_idx =
S
Stanislaw Gruszka 已提交
1595
			    ch_info->power_info[rate_idx].base_power_idx;
Z
Zhu Yi 已提交
1596 1597

			/* temperature compensate */
S
Stanislaw Gruszka 已提交
1598
			power_idx += delta_idx;
Z
Zhu Yi 已提交
1599 1600

			/* stay within table range */
S
Stanislaw Gruszka 已提交
1601
			power_idx = il3945_hw_reg_fix_power_idx(power_idx);
1602 1603
			ch_info->power_info[rate_idx].power_table_idx =
			    (u8) power_idx;
S
Stanislaw Gruszka 已提交
1604
			ch_info->power_info[rate_idx].tpc =
Z
Zhu Yi 已提交
1605 1606 1607 1608
			    power_gain_table[a_band][power_idx];
		}

		/* Get this chnlgrp's rate-to-max/clip-powers table */
1609 1610
		clip_pwrs =
		    il->_3945.clip_groups[ch_info->group_idx].clip_powers;
Z
Zhu Yi 已提交
1611 1612

		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
1613 1614 1615 1616 1617
		for (scan_tbl_idx = 0; scan_tbl_idx < IL_NUM_SCAN_RATES;
		     scan_tbl_idx++) {
			s32 actual_idx =
			    (scan_tbl_idx ==
			     0) ? RATE_1M_IDX_TBL : RATE_6M_IDX_TBL;
S
Stanislaw Gruszka 已提交
1618
			il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
1619 1620
						     actual_idx, clip_pwrs,
						     ch_info, a_band);
Z
Zhu Yi 已提交
1621 1622 1623 1624
		}
	}

	/* send Txpower command for current channel to ucode */
S
Stanislaw Gruszka 已提交
1625
	return il->cfg->ops->lib->send_tx_power(il);
Z
Zhu Yi 已提交
1626 1627
}

1628 1629
int
il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
Z
Zhu Yi 已提交
1630
{
S
Stanislaw Gruszka 已提交
1631
	struct il_channel_info *ch_info;
Z
Zhu Yi 已提交
1632 1633 1634 1635
	s8 max_power;
	u8 a_band;
	u8 i;

S
Stanislaw Gruszka 已提交
1636
	if (il->tx_power_user_lmt == power) {
1637 1638
		D_POWER("Requested Tx power same as current " "limit: %ddBm.\n",
			power);
Z
Zhu Yi 已提交
1639 1640 1641
		return 0;
	}

1642
	D_POWER("Setting upper limit clamp to %ddBm.\n", power);
S
Stanislaw Gruszka 已提交
1643
	il->tx_power_user_lmt = power;
Z
Zhu Yi 已提交
1644 1645 1646

	/* set up new Tx powers for each and every channel, 2.4 and 5.x */

S
Stanislaw Gruszka 已提交
1647 1648
	for (i = 0; i < il->channel_count; i++) {
		ch_info = &il->channel_info[i];
S
Stanislaw Gruszka 已提交
1649
		a_band = il_is_channel_a_band(ch_info);
Z
Zhu Yi 已提交
1650 1651 1652

		/* find minimum power of all user and regulatory constraints
		 *    (does not consider h/w clipping limitations) */
S
Stanislaw Gruszka 已提交
1653
		max_power = il3945_hw_reg_get_ch_txpower_limit(ch_info);
Z
Zhu Yi 已提交
1654 1655 1656 1657 1658
		max_power = min(power, max_power);
		if (max_power != ch_info->curr_txpow) {
			ch_info->curr_txpow = max_power;

			/* this considers the h/w clipping limitations */
S
Stanislaw Gruszka 已提交
1659
			il3945_hw_reg_set_new_power(il, ch_info);
Z
Zhu Yi 已提交
1660 1661 1662 1663 1664
		}
	}

	/* update txpower settings for all channels,
	 *   send to NIC if associated. */
S
Stanislaw Gruszka 已提交
1665 1666
	il3945_is_temp_calib_needed(il);
	il3945_hw_reg_comp_txpower_temp(il);
Z
Zhu Yi 已提交
1667 1668 1669 1670

	return 0;
}

1671 1672
static int
il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx)
1673 1674
{
	int rc = 0;
1675
	struct il_rx_pkt *pkt;
S
Stanislaw Gruszka 已提交
1676 1677
	struct il3945_rxon_assoc_cmd rxon_assoc;
	struct il_host_cmd cmd = {
1678
		.id = C_RXON_ASSOC,
1679
		.len = sizeof(rxon_assoc),
J
Johannes Berg 已提交
1680
		.flags = CMD_WANT_SKB,
1681 1682
		.data = &rxon_assoc,
	};
S
Stanislaw Gruszka 已提交
1683 1684
	const struct il_rxon_cmd *rxon1 = &ctx->staging;
	const struct il_rxon_cmd *rxon2 = &ctx->active;
1685

1686 1687 1688 1689
	if (rxon1->flags == rxon2->flags &&
	    rxon1->filter_flags == rxon2->filter_flags &&
	    rxon1->cck_basic_rates == rxon2->cck_basic_rates &&
	    rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates) {
1690
		D_INFO("Using current RXON_ASSOC.  Not resending.\n");
1691 1692 1693
		return 0;
	}

1694 1695 1696 1697
	rxon_assoc.flags = ctx->staging.flags;
	rxon_assoc.filter_flags = ctx->staging.filter_flags;
	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
1698 1699
	rxon_assoc.reserved = 0;

S
Stanislaw Gruszka 已提交
1700
	rc = il_send_cmd_sync(il, &cmd);
1701 1702 1703
	if (rc)
		return rc;

1704
	pkt = (struct il_rx_pkt *)cmd.reply_page;
S
Stanislaw Gruszka 已提交
1705
	if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
1706
		IL_ERR("Bad return from C_RXON_ASSOC command\n");
1707 1708 1709
		rc = -EIO;
	}

S
Stanislaw Gruszka 已提交
1710
	il_free_pages(il, cmd.reply_page);
1711 1712 1713 1714

	return rc;
}

A
Abhijeet Kolekar 已提交
1715
/**
S
Stanislaw Gruszka 已提交
1716
 * il3945_commit_rxon - commit staging_rxon to hardware
A
Abhijeet Kolekar 已提交
1717 1718 1719 1720 1721 1722
 *
 * The RXON command in staging_rxon is committed to the hardware and
 * 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.
 */
1723 1724
int
il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx)
A
Abhijeet Kolekar 已提交
1725 1726
{
	/* cast away the const for active_rxon in this function */
S
Stanislaw Gruszka 已提交
1727 1728
	struct il3945_rxon_cmd *active_rxon = (void *)&ctx->active;
	struct il3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
A
Abhijeet Kolekar 已提交
1729
	int rc = 0;
1730
	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
A
Abhijeet Kolekar 已提交
1731

S
Stanislaw Gruszka 已提交
1732
	if (test_bit(S_EXIT_PENDING, &il->status))
1733 1734
		return -EINVAL;

S
Stanislaw Gruszka 已提交
1735
	if (!il_is_alive(il))
A
Abhijeet Kolekar 已提交
1736 1737 1738 1739 1740 1741
		return -1;

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

	/* select antenna */
1742
	staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
S
Stanislaw Gruszka 已提交
1743
	staging_rxon->flags |= il3945_get_antenna_flags(il);
A
Abhijeet Kolekar 已提交
1744

S
Stanislaw Gruszka 已提交
1745
	rc = il_check_rxon_cmd(il, ctx);
A
Abhijeet Kolekar 已提交
1746
	if (rc) {
1747
		IL_ERR("Invalid RXON configuration.  Not committing.\n");
A
Abhijeet Kolekar 已提交
1748 1749 1750 1751
		return -EINVAL;
	}

	/* If we don't need to send a full RXON, we can use
S
Stanislaw Gruszka 已提交
1752
	 * il3945_rxon_assoc_cmd which is used to reconfigure filter
A
Abhijeet Kolekar 已提交
1753
	 * and other flags for the current radio configuration. */
1754 1755
	if (!il_full_rxon_required(il, &il->ctx)) {
		rc = il_send_rxon_assoc(il, &il->ctx);
A
Abhijeet Kolekar 已提交
1756
		if (rc) {
1757
			IL_ERR("Error setting RXON_ASSOC "
1758
			       "configuration (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1759 1760 1761 1762
			return rc;
		}

		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
1763 1764 1765 1766
		/*
		 * We do not commit tx power settings while channel changing,
		 * do it now if tx power changed.
		 */
S
Stanislaw Gruszka 已提交
1767
		il_set_tx_power(il, il->tx_power_next, false);
A
Abhijeet Kolekar 已提交
1768 1769 1770 1771 1772 1773 1774
		return 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 */
1775
	if (il_is_associated(il) && new_assoc) {
1776
		D_INFO("Toggling associated bit on current RXON\n");
A
Abhijeet Kolekar 已提交
1777 1778 1779 1780 1781 1782 1783 1784
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

		/*
		 * reserved4 and 5 could have been filled by the iwlcore code.
		 * Let's clear them before pushing to the 3945.
		 */
		active_rxon->reserved4 = 0;
		active_rxon->reserved5 = 0;
1785 1786
		rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd),
				     &il->ctx.active);
A
Abhijeet Kolekar 已提交
1787 1788 1789 1790 1791

		/* 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;
1792
			IL_ERR("Error clearing ASSOC_MSK on current "
1793
			       "configuration (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1794 1795
			return rc;
		}
1796 1797
		il_clear_ucode_stations(il, &il->ctx);
		il_restore_stations(il, &il->ctx);
A
Abhijeet Kolekar 已提交
1798 1799
	}

1800 1801 1802
	D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n"
	       "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"),
	       le16_to_cpu(staging_rxon->channel), staging_rxon->bssid_addr);
A
Abhijeet Kolekar 已提交
1803 1804 1805 1806 1807 1808 1809 1810

	/*
	 * reserved4 and 5 could have been filled by the iwlcore code.
	 * Let's clear them before pushing to the 3945.
	 */
	staging_rxon->reserved4 = 0;
	staging_rxon->reserved5 = 0;

S
Stanislaw Gruszka 已提交
1811
	il_set_rxon_hwcrypto(il, ctx, !il3945_mod_params.sw_crypto);
A
Abhijeet Kolekar 已提交
1812 1813

	/* Apply the new configuration */
1814 1815
	rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd),
			     staging_rxon);
A
Abhijeet Kolekar 已提交
1816
	if (rc) {
1817
		IL_ERR("Error setting new configuration (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1818 1819 1820 1821 1822
		return rc;
	}

	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));

1823
	if (!new_assoc) {
1824 1825
		il_clear_ucode_stations(il, &il->ctx);
		il_restore_stations(il, &il->ctx);
1826
	}
A
Abhijeet Kolekar 已提交
1827 1828 1829

	/* 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 */
S
Stanislaw Gruszka 已提交
1830
	rc = il_set_tx_power(il, il->tx_power_next, true);
A
Abhijeet Kolekar 已提交
1831
	if (rc) {
1832
		IL_ERR("Error setting Tx power (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1833 1834 1835 1836
		return rc;
	}

	/* Init the hardware's rate fallback order based on the band */
S
Stanislaw Gruszka 已提交
1837
	rc = il3945_init_hw_rate_table(il);
A
Abhijeet Kolekar 已提交
1838
	if (rc) {
1839
		IL_ERR("Error setting HW rate table: %02X\n", rc);
A
Abhijeet Kolekar 已提交
1840 1841 1842 1843 1844 1845
		return -EIO;
	}

	return 0;
}

Z
Zhu Yi 已提交
1846
/**
S
Stanislaw Gruszka 已提交
1847
 * il3945_reg_txpower_periodic -  called when time to check our temperature.
Z
Zhu Yi 已提交
1848 1849 1850 1851 1852 1853 1854 1855
 *
 * -- reset periodic timer
 * -- see if temp has changed enough to warrant re-calibration ... if so:
 *     -- correct coeffs for temp (can reset temp timer)
 *     -- save this temp as "last",
 *     -- send new set of gain settings to NIC
 * NOTE:  This should continue working, even when we're not associated,
 *   so we can keep our internal table of scan powers current. */
1856 1857
void
il3945_reg_txpower_periodic(struct il_priv *il)
Z
Zhu Yi 已提交
1858 1859
{
	/* This will kick in the "brute force"
S
Stanislaw Gruszka 已提交
1860
	 * il3945_hw_reg_comp_txpower_temp() below */
S
Stanislaw Gruszka 已提交
1861
	if (!il3945_is_temp_calib_needed(il))
Z
Zhu Yi 已提交
1862 1863 1864 1865 1866
		goto reschedule;

	/* Set up a new set of temp-adjusted TxPowers, send to NIC.
	 * This is based *only* on current temperature,
	 * ignoring any previous power measurements */
S
Stanislaw Gruszka 已提交
1867
	il3945_hw_reg_comp_txpower_temp(il);
Z
Zhu Yi 已提交
1868

1869 1870 1871
reschedule:
	queue_delayed_work(il->workqueue, &il->_3945.thermal_periodic,
			   REG_RECALIB_PERIOD * HZ);
Z
Zhu Yi 已提交
1872 1873
}

1874 1875
static void
il3945_bg_reg_txpower_periodic(struct work_struct *work)
Z
Zhu Yi 已提交
1876
{
S
Stanislaw Gruszka 已提交
1877
	struct il_priv *il = container_of(work, struct il_priv,
1878
					  _3945.thermal_periodic.work);
Z
Zhu Yi 已提交
1879

S
Stanislaw Gruszka 已提交
1880
	if (test_bit(S_EXIT_PENDING, &il->status))
Z
Zhu Yi 已提交
1881 1882
		return;

S
Stanislaw Gruszka 已提交
1883 1884 1885
	mutex_lock(&il->mutex);
	il3945_reg_txpower_periodic(il);
	mutex_unlock(&il->mutex);
Z
Zhu Yi 已提交
1886 1887 1888
}

/**
S
Stanislaw Gruszka 已提交
1889
 * il3945_hw_reg_get_ch_grp_idx - find the channel-group idx (0-4) for channel.
Z
Zhu Yi 已提交
1890 1891 1892 1893 1894 1895 1896 1897
 *
 * This function is used when initializing channel-info structs.
 *
 * NOTE: These channel groups do *NOT* match the bands above!
 *	 These channel groups are based on factory-tested channels;
 *	 on A-band, EEPROM's "group frequency" entries represent the top
 *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
 */
1898 1899 1900
static u16
il3945_hw_reg_get_ch_grp_idx(struct il_priv *il,
			     const struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1901
{
S
Stanislaw Gruszka 已提交
1902
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1903
	struct il3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
Z
Zhu Yi 已提交
1904
	u8 group;
S
Stanislaw Gruszka 已提交
1905
	u16 group_idx = 0;	/* based on factory calib frequencies */
Z
Zhu Yi 已提交
1906 1907
	u8 grp_channel;

S
Stanislaw Gruszka 已提交
1908
	/* Find the group idx for the channel ... don't use idx 1(?) */
S
Stanislaw Gruszka 已提交
1909
	if (il_is_channel_a_band(ch_info)) {
Z
Zhu Yi 已提交
1910 1911 1912
		for (group = 1; group < 5; group++) {
			grp_channel = ch_grp[group].group_channel;
			if (ch_info->channel <= grp_channel) {
S
Stanislaw Gruszka 已提交
1913
				group_idx = group;
Z
Zhu Yi 已提交
1914 1915 1916 1917 1918
				break;
			}
		}
		/* group 4 has a few channels *above* its factory cal freq */
		if (group == 5)
S
Stanislaw Gruszka 已提交
1919
			group_idx = 4;
Z
Zhu Yi 已提交
1920
	} else
S
Stanislaw Gruszka 已提交
1921
		group_idx = 0;	/* 2.4 GHz, group 0 */
Z
Zhu Yi 已提交
1922

1923
	D_POWER("Chnl %d mapped to grp %d\n", ch_info->channel, group_idx);
S
Stanislaw Gruszka 已提交
1924
	return group_idx;
Z
Zhu Yi 已提交
1925 1926 1927
}

/**
S
Stanislaw Gruszka 已提交
1928
 * il3945_hw_reg_get_matched_power_idx - Interpolate to get nominal idx
Z
Zhu Yi 已提交
1929
 *
S
Stanislaw Gruszka 已提交
1930
 * Interpolate to get nominal (i.e. at factory calibration temperature) idx
Z
Zhu Yi 已提交
1931 1932
 *   into radio/DSP gain settings table for requested power.
 */
1933 1934
static int
il3945_hw_reg_get_matched_power_idx(struct il_priv *il, s8 requested_power,
S
Stanislaw Gruszka 已提交
1935
				    s32 setting_idx, s32 *new_idx)
Z
Zhu Yi 已提交
1936
{
S
Stanislaw Gruszka 已提交
1937
	const struct il3945_eeprom_txpower_group *chnl_grp = NULL;
S
Stanislaw Gruszka 已提交
1938
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1939
	s32 idx0, idx1;
Z
Zhu Yi 已提交
1940 1941
	s32 power = 2 * requested_power;
	s32 i;
S
Stanislaw Gruszka 已提交
1942
	const struct il3945_eeprom_txpower_sample *samples;
Z
Zhu Yi 已提交
1943 1944 1945 1946
	s32 gains0, gains1;
	s32 res;
	s32 denominator;

S
Stanislaw Gruszka 已提交
1947
	chnl_grp = &eeprom->groups[setting_idx];
Z
Zhu Yi 已提交
1948 1949 1950
	samples = chnl_grp->samples;
	for (i = 0; i < 5; i++) {
		if (power == samples[i].power) {
S
Stanislaw Gruszka 已提交
1951
			*new_idx = samples[i].gain_idx;
Z
Zhu Yi 已提交
1952 1953 1954 1955 1956
			return 0;
		}
	}

	if (power > samples[1].power) {
S
Stanislaw Gruszka 已提交
1957 1958
		idx0 = 0;
		idx1 = 1;
Z
Zhu Yi 已提交
1959
	} else if (power > samples[2].power) {
S
Stanislaw Gruszka 已提交
1960 1961
		idx0 = 1;
		idx1 = 2;
Z
Zhu Yi 已提交
1962
	} else if (power > samples[3].power) {
S
Stanislaw Gruszka 已提交
1963 1964
		idx0 = 2;
		idx1 = 3;
Z
Zhu Yi 已提交
1965
	} else {
S
Stanislaw Gruszka 已提交
1966 1967
		idx0 = 3;
		idx1 = 4;
Z
Zhu Yi 已提交
1968 1969
	}

S
Stanislaw Gruszka 已提交
1970
	denominator = (s32) samples[idx1].power - (s32) samples[idx0].power;
Z
Zhu Yi 已提交
1971 1972
	if (denominator == 0)
		return -EINVAL;
S
Stanislaw Gruszka 已提交
1973 1974
	gains0 = (s32) samples[idx0].gain_idx * (1 << 19);
	gains1 = (s32) samples[idx1].gain_idx * (1 << 19);
1975 1976 1977 1978
	res =
	    gains0 + (gains1 - gains0) * ((s32) power -
					  (s32) samples[idx0].power) /
	    denominator + (1 << 18);
S
Stanislaw Gruszka 已提交
1979
	*new_idx = res >> 19;
Z
Zhu Yi 已提交
1980 1981 1982
	return 0;
}

1983 1984
static void
il3945_hw_reg_init_channel_groups(struct il_priv *il)
Z
Zhu Yi 已提交
1985 1986
{
	u32 i;
S
Stanislaw Gruszka 已提交
1987
	s32 rate_idx;
S
Stanislaw Gruszka 已提交
1988
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1989
	const struct il3945_eeprom_txpower_group *group;
Z
Zhu Yi 已提交
1990

1991
	D_POWER("Initializing factory calib info from EEPROM\n");
Z
Zhu Yi 已提交
1992

S
Stanislaw Gruszka 已提交
1993
	for (i = 0; i < IL_NUM_TX_CALIB_GROUPS; i++) {
Z
Zhu Yi 已提交
1994 1995
		s8 *clip_pwrs;	/* table of power levels for each rate */
		s8 satur_pwr;	/* saturation power for each chnl group */
1996
		group = &eeprom->groups[i];
Z
Zhu Yi 已提交
1997 1998 1999

		/* sanity check on factory saturation power value */
		if (group->saturation_power < 40) {
2000
			IL_WARN("Error: saturation power is %d, "
2001 2002
				"less than minimum expected 40\n",
				group->saturation_power);
Z
Zhu Yi 已提交
2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
			return;
		}

		/*
		 * Derive requested power levels for each rate, based on
		 *   hardware capabilities (saturation power for band).
		 * Basic value is 3dB down from saturation, with further
		 *   power reductions for highest 3 data rates.  These
		 *   backoffs provide headroom for high rate modulation
		 *   power peaks, without too much distortion (clipping).
		 */
		/* we'll fill in this array with h/w max power levels */
S
Stanislaw Gruszka 已提交
2015
		clip_pwrs = (s8 *) il->_3945.clip_groups[i].clip_powers;
Z
Zhu Yi 已提交
2016 2017 2018 2019 2020

		/* divide factory saturation power by 2 to find -3dB level */
		satur_pwr = (s8) (group->saturation_power >> 1);

		/* fill in channel group's nominal powers for each rate */
2021 2022
		for (rate_idx = 0; rate_idx < RATE_COUNT_3945;
		     rate_idx++, clip_pwrs++) {
S
Stanislaw Gruszka 已提交
2023
			switch (rate_idx) {
S
Stanislaw Gruszka 已提交
2024
			case RATE_36M_IDX_TBL:
Z
Zhu Yi 已提交
2025 2026 2027 2028 2029
				if (i == 0)	/* B/G */
					*clip_pwrs = satur_pwr;
				else	/* A */
					*clip_pwrs = satur_pwr - 5;
				break;
S
Stanislaw Gruszka 已提交
2030
			case RATE_48M_IDX_TBL:
Z
Zhu Yi 已提交
2031 2032 2033 2034 2035
				if (i == 0)
					*clip_pwrs = satur_pwr - 7;
				else
					*clip_pwrs = satur_pwr - 10;
				break;
S
Stanislaw Gruszka 已提交
2036
			case RATE_54M_IDX_TBL:
Z
Zhu Yi 已提交
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
				if (i == 0)
					*clip_pwrs = satur_pwr - 9;
				else
					*clip_pwrs = satur_pwr - 12;
				break;
			default:
				*clip_pwrs = satur_pwr;
				break;
			}
		}
	}
}

/**
S
Stanislaw Gruszka 已提交
2051
 * il3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
Z
Zhu Yi 已提交
2052
 *
S
Stanislaw Gruszka 已提交
2053
 * Second pass (during init) to set up il->channel_info
Z
Zhu Yi 已提交
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
 *
 * Set up Tx-power settings in our channel info database for each VALID
 * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
 * and current temperature.
 *
 * Since this is based on current temperature (at init time), these values may
 * not be valid for very long, but it gives us a starting/default point,
 * and allows us to active (i.e. using Tx) scan.
 *
 * This does *not* write values to NIC, just sets up our internal table.
 */
2065 2066
int
il3945_txpower_set_from_eeprom(struct il_priv *il)
Z
Zhu Yi 已提交
2067
{
S
Stanislaw Gruszka 已提交
2068 2069
	struct il_channel_info *ch_info = NULL;
	struct il3945_channel_power_info *pwr_info;
S
Stanislaw Gruszka 已提交
2070
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
2071 2072 2073
	int delta_idx;
	u8 rate_idx;
	u8 scan_tbl_idx;
Z
Zhu Yi 已提交
2074 2075 2076
	const s8 *clip_pwrs;	/* array of power levels for each rate */
	u8 gain, dsp_atten;
	s8 power;
S
Stanislaw Gruszka 已提交
2077
	u8 pwr_idx, base_pwr_idx, a_band;
Z
Zhu Yi 已提交
2078 2079 2080 2081 2082
	u8 i;
	int temperature;

	/* save temperature reference,
	 *   so we can determine next time to calibrate */
S
Stanislaw Gruszka 已提交
2083 2084
	temperature = il3945_hw_reg_txpower_get_temperature(il);
	il->last_temperature = temperature;
Z
Zhu Yi 已提交
2085

S
Stanislaw Gruszka 已提交
2086
	il3945_hw_reg_init_channel_groups(il);
Z
Zhu Yi 已提交
2087 2088

	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
S
Stanislaw Gruszka 已提交
2089
	for (i = 0, ch_info = il->channel_info; i < il->channel_count;
Z
Zhu Yi 已提交
2090
	     i++, ch_info++) {
S
Stanislaw Gruszka 已提交
2091 2092
		a_band = il_is_channel_a_band(ch_info);
		if (!il_is_channel_valid(ch_info))
Z
Zhu Yi 已提交
2093 2094
			continue;

S
Stanislaw Gruszka 已提交
2095
		/* find this channel's channel group (*not* "band") idx */
2096
		ch_info->group_idx = il3945_hw_reg_get_ch_grp_idx(il, ch_info);
Z
Zhu Yi 已提交
2097 2098

		/* Get this chnlgrp's rate->max/clip-powers table */
2099 2100
		clip_pwrs =
		    il->_3945.clip_groups[ch_info->group_idx].clip_powers;
Z
Zhu Yi 已提交
2101

S
Stanislaw Gruszka 已提交
2102
		/* calculate power idx *adjustment* value according to
Z
Zhu Yi 已提交
2103
		 *  diff between current temperature and factory temperature */
2104 2105 2106 2107 2108
		delta_idx =
		    il3945_hw_reg_adjust_power_by_temp(temperature,
						       eeprom->groups[ch_info->
								      group_idx].
						       temperature);
Z
Zhu Yi 已提交
2109

2110 2111
		D_POWER("Delta idx for channel %d: %d [%d]\n", ch_info->channel,
			delta_idx, temperature + IL_TEMP_CONVERT);
Z
Zhu Yi 已提交
2112 2113

		/* set tx power value for all OFDM rates */
2114
		for (rate_idx = 0; rate_idx < IL_OFDM_RATES; rate_idx++) {
2115
			s32 uninitialized_var(power_idx);
Z
Zhu Yi 已提交
2116 2117 2118 2119 2120
			int rc;

			/* use channel group's clip-power table,
			 *   but don't exceed channel's max power */
			s8 pwr = min(ch_info->max_power_avg,
S
Stanislaw Gruszka 已提交
2121
				     clip_pwrs[rate_idx]);
Z
Zhu Yi 已提交
2122

S
Stanislaw Gruszka 已提交
2123
			pwr_info = &ch_info->power_info[rate_idx];
Z
Zhu Yi 已提交
2124 2125

			/* get base (i.e. at factory-measured temperature)
S
Stanislaw Gruszka 已提交
2126 2127
			 *    power table idx for this rate's power */
			rc = il3945_hw_reg_get_matched_power_idx(il, pwr,
2128 2129 2130
								 ch_info->
								 group_idx,
								 &power_idx);
Z
Zhu Yi 已提交
2131
			if (rc) {
S
Stanislaw Gruszka 已提交
2132
				IL_ERR("Invalid power idx\n");
Z
Zhu Yi 已提交
2133 2134
				return rc;
			}
S
Stanislaw Gruszka 已提交
2135
			pwr_info->base_power_idx = (u8) power_idx;
Z
Zhu Yi 已提交
2136 2137

			/* temperature compensate */
S
Stanislaw Gruszka 已提交
2138
			power_idx += delta_idx;
Z
Zhu Yi 已提交
2139 2140

			/* stay within range of gain table */
S
Stanislaw Gruszka 已提交
2141
			power_idx = il3945_hw_reg_fix_power_idx(power_idx);
Z
Zhu Yi 已提交
2142

S
Stanislaw Gruszka 已提交
2143
			/* fill 1 OFDM rate's il3945_channel_power_info struct */
Z
Zhu Yi 已提交
2144
			pwr_info->requested_power = pwr;
S
Stanislaw Gruszka 已提交
2145
			pwr_info->power_table_idx = (u8) power_idx;
Z
Zhu Yi 已提交
2146 2147 2148 2149 2150 2151
			pwr_info->tpc.tx_gain =
			    power_gain_table[a_band][power_idx].tx_gain;
			pwr_info->tpc.dsp_atten =
			    power_gain_table[a_band][power_idx].dsp_atten;
		}

2152
		/* set tx power for CCK rates, based on OFDM 12 Mbit settings */
S
Stanislaw Gruszka 已提交
2153
		pwr_info = &ch_info->power_info[RATE_12M_IDX_TBL];
2154 2155 2156 2157
		power = pwr_info->requested_power + IL_CCK_FROM_OFDM_POWER_DIFF;
		pwr_idx = pwr_info->power_table_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
		base_pwr_idx =
		    pwr_info->base_power_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
Z
Zhu Yi 已提交
2158 2159

		/* stay within table range */
S
Stanislaw Gruszka 已提交
2160 2161 2162
		pwr_idx = il3945_hw_reg_fix_power_idx(pwr_idx);
		gain = power_gain_table[a_band][pwr_idx].tx_gain;
		dsp_atten = power_gain_table[a_band][pwr_idx].dsp_atten;
Z
Zhu Yi 已提交
2163

S
Stanislaw Gruszka 已提交
2164
		/* fill each CCK rate's il3945_channel_power_info structure
Z
Zhu Yi 已提交
2165 2166
		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
		 * NOTE:  CCK rates start at end of OFDM rates! */
2167 2168 2169
		for (rate_idx = 0; rate_idx < IL_CCK_RATES; rate_idx++) {
			pwr_info =
			    &ch_info->power_info[rate_idx + IL_OFDM_RATES];
Z
Zhu Yi 已提交
2170
			pwr_info->requested_power = power;
S
Stanislaw Gruszka 已提交
2171 2172
			pwr_info->power_table_idx = pwr_idx;
			pwr_info->base_power_idx = base_pwr_idx;
Z
Zhu Yi 已提交
2173 2174 2175 2176 2177
			pwr_info->tpc.tx_gain = gain;
			pwr_info->tpc.dsp_atten = dsp_atten;
		}

		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
2178 2179 2180 2181 2182
		for (scan_tbl_idx = 0; scan_tbl_idx < IL_NUM_SCAN_RATES;
		     scan_tbl_idx++) {
			s32 actual_idx =
			    (scan_tbl_idx ==
			     0) ? RATE_1M_IDX_TBL : RATE_6M_IDX_TBL;
S
Stanislaw Gruszka 已提交
2183
			il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
2184 2185
						     actual_idx, clip_pwrs,
						     ch_info, a_band);
Z
Zhu Yi 已提交
2186 2187 2188 2189 2190 2191
		}
	}

	return 0;
}

2192 2193
int
il3945_hw_rxq_stop(struct il_priv *il)
Z
Zhu Yi 已提交
2194 2195 2196
{
	int rc;

2197 2198
	il_wr(il, FH39_RCSR_CONFIG(0), 0);
	rc = il_poll_bit(il, FH39_RSSR_STATUS,
2199
			 FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
Z
Zhu Yi 已提交
2200
	if (rc < 0)
2201
		IL_ERR("Can't stop Rx DMA.\n");
Z
Zhu Yi 已提交
2202 2203 2204 2205

	return 0;
}

2206 2207
int
il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
Z
Zhu Yi 已提交
2208 2209 2210
{
	int txq_id = txq->q.id;

S
Stanislaw Gruszka 已提交
2211
	struct il3945_shared *shared_data = il->_3945.shared_virt;
Z
Zhu Yi 已提交
2212

2213
	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32) txq->q.dma_addr);
Z
Zhu Yi 已提交
2214

2215 2216
	il_wr(il, FH39_CBCC_CTRL(txq_id), 0);
	il_wr(il, FH39_CBCC_BASE(txq_id), 0);
2217

2218
	il_wr(il, FH39_TCSR_CONFIG(txq_id),
2219 2220 2221 2222 2223
	      FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
	      FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
	      FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
	      FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
	      FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
Z
Zhu Yi 已提交
2224 2225

	/* fake read to flush all prev. writes */
2226
	_il_rd(il, FH39_TSSR_CBB_BASE);
Z
Zhu Yi 已提交
2227 2228 2229 2230

	return 0;
}

K
Kolekar, Abhijeet 已提交
2231 2232 2233
/*
 * HCMD utils
 */
2234 2235
static u16
il3945_get_hcmd_size(u8 cmd_id, u16 len)
K
Kolekar, Abhijeet 已提交
2236 2237
{
	switch (cmd_id) {
2238
	case C_RXON:
S
Stanislaw Gruszka 已提交
2239
		return sizeof(struct il3945_rxon_cmd);
2240
	case C_POWER_TBL:
S
Stanislaw Gruszka 已提交
2241
		return sizeof(struct il3945_powertable_cmd);
K
Kolekar, Abhijeet 已提交
2242 2243 2244 2245 2246
	default:
		return len;
	}
}

2247 2248
static u16
il3945_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data)
2249
{
S
Stanislaw Gruszka 已提交
2250
	struct il3945_addsta_cmd *addsta = (struct il3945_addsta_cmd *)data;
2251 2252
	addsta->mode = cmd->mode;
	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
S
Stanislaw Gruszka 已提交
2253
	memcpy(&addsta->key, &cmd->key, sizeof(struct il4965_keyinfo));
2254 2255 2256 2257 2258 2259 2260 2261
	addsta->station_flags = cmd->station_flags;
	addsta->station_flags_msk = cmd->station_flags_msk;
	addsta->tid_disable_tx = cpu_to_le16(0);
	addsta->rate_n_flags = cmd->rate_n_flags;
	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;

2262
	return (u16) sizeof(struct il3945_addsta_cmd);
2263 2264
}

2265 2266
static int
il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r)
2267
{
2268
	struct il_rxon_context *ctx = &il->ctx;
2269 2270 2271 2272 2273
	int ret;
	u8 sta_id;
	unsigned long flags;

	if (sta_id_r)
S
Stanislaw Gruszka 已提交
2274
		*sta_id_r = IL_INVALID_STATION;
2275

S
Stanislaw Gruszka 已提交
2276
	ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
2277
	if (ret) {
2278
		IL_ERR("Unable to add station %pM\n", addr);
2279 2280 2281 2282 2283 2284
		return ret;
	}

	if (sta_id_r)
		*sta_id_r = sta_id;

S
Stanislaw Gruszka 已提交
2285 2286 2287
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].used |= IL_STA_LOCAL;
	spin_unlock_irqrestore(&il->sta_lock, flags);
2288 2289 2290

	return 0;
}
2291 2292 2293 2294

static int
il3945_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
			   bool add)
2295
{
S
Stanislaw Gruszka 已提交
2296
	struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
2297 2298 2299
	int ret;

	if (add) {
2300 2301 2302
		ret =
		    il3945_add_bssid_station(il, vif->bss_conf.bssid,
					     &vif_priv->ibss_bssid_sta_id);
2303 2304 2305
		if (ret)
			return ret;

S
Stanislaw Gruszka 已提交
2306
		il3945_sync_sta(il, vif_priv->ibss_bssid_sta_id,
2307 2308 2309
				(il->band ==
				 IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP :
				RATE_1M_PLCP);
S
Stanislaw Gruszka 已提交
2310
		il3945_rate_scale_init(il->hw, vif_priv->ibss_bssid_sta_id);
2311 2312 2313 2314

		return 0;
	}

S
Stanislaw Gruszka 已提交
2315
	return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
2316
				 vif->bss_conf.bssid);
2317
}
2318

Z
Zhu Yi 已提交
2319
/**
S
Stanislaw Gruszka 已提交
2320
 * il3945_init_hw_rate_table - Initialize the hardware rate fallback table
Z
Zhu Yi 已提交
2321
 */
2322 2323
int
il3945_init_hw_rate_table(struct il_priv *il)
Z
Zhu Yi 已提交
2324
{
S
Stanislaw Gruszka 已提交
2325
	int rc, i, idx, prev_idx;
S
Stanislaw Gruszka 已提交
2326
	struct il3945_rate_scaling_cmd rate_cmd = {
Z
Zhu Yi 已提交
2327 2328
		.reserved = {0, 0, 0},
	};
S
Stanislaw Gruszka 已提交
2329
	struct il3945_rate_scaling_info *table = rate_cmd.table;
Z
Zhu Yi 已提交
2330

S
Stanislaw Gruszka 已提交
2331
	for (i = 0; i < ARRAY_SIZE(il3945_rates); i++) {
S
Stanislaw Gruszka 已提交
2332
		idx = il3945_rates[i].table_rs_idx;
2333

S
Stanislaw Gruszka 已提交
2334
		table[idx].rate_n_flags =
2335
		    il3945_hw_set_rate_n_flags(il3945_rates[i].plcp, 0);
S
Stanislaw Gruszka 已提交
2336 2337
		table[idx].try_cnt = il->retry_rate;
		prev_idx = il3945_get_prev_ieee_rate(i);
2338
		table[idx].next_rate_idx = il3945_rates[prev_idx].table_rs_idx;
Z
Zhu Yi 已提交
2339 2340
	}

S
Stanislaw Gruszka 已提交
2341
	switch (il->band) {
2342
	case IEEE80211_BAND_5GHZ:
2343
		D_RATE("Select A mode rate scale\n");
Z
Zhu Yi 已提交
2344 2345
		/* If one of the following CCK rates is used,
		 * have it fall back to the 6M OFDM rate */
2346
		for (i = RATE_1M_IDX_TBL; i <= RATE_11M_IDX_TBL; i++)
S
Stanislaw Gruszka 已提交
2347
			table[i].next_rate_idx =
2348
			    il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
Z
Zhu Yi 已提交
2349 2350

		/* Don't fall back to CCK rates */
2351
		table[RATE_12M_IDX_TBL].next_rate_idx = RATE_9M_IDX_TBL;
Z
Zhu Yi 已提交
2352 2353

		/* Don't drop out of OFDM rates */
S
Stanislaw Gruszka 已提交
2354
		table[RATE_6M_IDX_TBL].next_rate_idx =
S
Stanislaw Gruszka 已提交
2355
		    il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
Z
Zhu Yi 已提交
2356 2357
		break;

2358
	case IEEE80211_BAND_2GHZ:
2359
		D_RATE("Select B/G mode rate scale\n");
Z
Zhu Yi 已提交
2360 2361 2362
		/* If an OFDM rate is used, have it fall back to the
		 * 1M CCK rates */

S
Stanislaw Gruszka 已提交
2363
		if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
2364
		    il_is_associated(il)) {
2365

S
Stanislaw Gruszka 已提交
2366
			idx = IL_FIRST_CCK_RATE;
2367
			for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++)
S
Stanislaw Gruszka 已提交
2368
				table[i].next_rate_idx =
2369
				    il3945_rates[idx].table_rs_idx;
2370

S
Stanislaw Gruszka 已提交
2371
			idx = RATE_11M_IDX_TBL;
2372
			/* CCK shouldn't fall back to OFDM... */
S
Stanislaw Gruszka 已提交
2373
			table[idx].next_rate_idx = RATE_5M_IDX_TBL;
2374
		}
Z
Zhu Yi 已提交
2375 2376 2377
		break;

	default:
2378
		WARN_ON(1);
Z
Zhu Yi 已提交
2379 2380 2381 2382 2383
		break;
	}

	/* Update the rate scaling for control frame Tx */
	rate_cmd.table_id = 0;
2384
	rc = il_send_cmd_pdu(il, C_RATE_SCALE, sizeof(rate_cmd), &rate_cmd);
Z
Zhu Yi 已提交
2385 2386 2387 2388 2389
	if (rc)
		return rc;

	/* Update the rate scaling for data frame Tx */
	rate_cmd.table_id = 1;
2390
	return il_send_cmd_pdu(il, C_RATE_SCALE, sizeof(rate_cmd), &rate_cmd);
Z
Zhu Yi 已提交
2391 2392
}

2393
/* Called when initializing driver */
2394 2395
int
il3945_hw_set_hw_params(struct il_priv *il)
Z
Zhu Yi 已提交
2396
{
2397
	memset((void *)&il->hw_params, 0, sizeof(struct il_hw_params));
Z
Zhu Yi 已提交
2398

S
Stanislaw Gruszka 已提交
2399
	il->_3945.shared_virt =
2400 2401
	    dma_alloc_coherent(&il->pci_dev->dev, sizeof(struct il3945_shared),
			       &il->_3945.shared_phys, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
2402
	if (!il->_3945.shared_virt) {
2403
		IL_ERR("failed to allocate pci memory\n");
Z
Zhu Yi 已提交
2404 2405 2406
		return -ENOMEM;
	}

2407
	/* Assign number of Usable TX queues */
S
Stanislaw Gruszka 已提交
2408
	il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues;
2409

S
Stanislaw Gruszka 已提交
2410 2411 2412 2413
	il->hw_params.tfd_size = sizeof(struct il3945_tfd);
	il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_3K);
	il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
	il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
2414
	il->hw_params.max_stations = IL3945_STATION_COUNT;
2415
	il->ctx.bcast_sta_id = IL3945_BROADCAST_ID;
2416

S
Stanislaw Gruszka 已提交
2417
	il->sta_key_max_num = STA_KEY_MAX_NUM;
2418

S
Stanislaw Gruszka 已提交
2419
	il->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
2420 2421
	il->hw_params.max_beacon_itrvl = IL39_MAX_UCODE_BEACON_INTERVAL;
	il->hw_params.beacon_time_tsf_bits = IL3945_EXT_BEACON_TIME_POS;
2422

Z
Zhu Yi 已提交
2423 2424 2425
	return 0;
}

2426 2427 2428
unsigned int
il3945_hw_get_beacon_cmd(struct il_priv *il, struct il3945_frame *frame,
			 u8 rate)
Z
Zhu Yi 已提交
2429
{
S
Stanislaw Gruszka 已提交
2430
	struct il3945_tx_beacon_cmd *tx_beacon_cmd;
Z
Zhu Yi 已提交
2431 2432
	unsigned int frame_size;

S
Stanislaw Gruszka 已提交
2433
	tx_beacon_cmd = (struct il3945_tx_beacon_cmd *)&frame->u;
Z
Zhu Yi 已提交
2434 2435
	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));

2436
	tx_beacon_cmd->tx.sta_id = il->ctx.bcast_sta_id;
Z
Zhu Yi 已提交
2437 2438
	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

2439 2440 2441
	frame_size =
	    il3945_fill_beacon_frame(il, tx_beacon_cmd->frame,
				     sizeof(frame->u) - sizeof(*tx_beacon_cmd));
Z
Zhu Yi 已提交
2442 2443

	BUG_ON(frame_size > MAX_MPDU_SIZE);
2444
	tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
Z
Zhu Yi 已提交
2445 2446

	tx_beacon_cmd->tx.rate = rate;
2447 2448
	tx_beacon_cmd->tx.tx_flags =
	    (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
Z
Zhu Yi 已提交
2449

2450
	/* supp_rates[0] == OFDM start at IL_FIRST_OFDM_RATE */
2451
	tx_beacon_cmd->tx.supp_rates[0] =
2452
	    (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
2453

2454
	tx_beacon_cmd->tx.supp_rates[1] = (IL_CCK_BASIC_RATES_MASK & 0xF);
Z
Zhu Yi 已提交
2455

S
Stanislaw Gruszka 已提交
2456
	return sizeof(struct il3945_tx_beacon_cmd) + frame_size;
Z
Zhu Yi 已提交
2457 2458
}

2459 2460
void
il3945_hw_handler_setup(struct il_priv *il)
Z
Zhu Yi 已提交
2461
{
S
Stanislaw Gruszka 已提交
2462 2463
	il->handlers[C_TX] = il3945_hdl_tx;
	il->handlers[N_3945_RX] = il3945_hdl_rx;
Z
Zhu Yi 已提交
2464 2465
}

2466 2467
void
il3945_hw_setup_deferred_work(struct il_priv *il)
Z
Zhu Yi 已提交
2468
{
S
Stanislaw Gruszka 已提交
2469
	INIT_DELAYED_WORK(&il->_3945.thermal_periodic,
S
Stanislaw Gruszka 已提交
2470
			  il3945_bg_reg_txpower_periodic);
Z
Zhu Yi 已提交
2471 2472
}

2473 2474
void
il3945_hw_cancel_deferred_work(struct il_priv *il)
Z
Zhu Yi 已提交
2475
{
S
Stanislaw Gruszka 已提交
2476
	cancel_delayed_work(&il->_3945.thermal_periodic);
Z
Zhu Yi 已提交
2477 2478
}

K
Kolekar, Abhijeet 已提交
2479
/* check contents of special bootstrap uCode SRAM */
2480 2481 2482
static int
il3945_verify_bsm(struct il_priv *il)
{
S
Stanislaw Gruszka 已提交
2483 2484
	__le32 *image = il->ucode_boot.v_addr;
	u32 len = il->ucode_boot.len;
K
Kolekar, Abhijeet 已提交
2485 2486 2487
	u32 reg;
	u32 val;

2488
	D_INFO("Begin verify bsm\n");
K
Kolekar, Abhijeet 已提交
2489 2490

	/* verify BSM SRAM contents */
2491
	val = il_rd_prph(il, BSM_WR_DWCOUNT_REG);
2492
	for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len;
K
Kolekar, Abhijeet 已提交
2493
	     reg += sizeof(u32), image++) {
2494
		val = il_rd_prph(il, reg);
K
Kolekar, Abhijeet 已提交
2495
		if (val != le32_to_cpu(*image)) {
2496
			IL_ERR("BSM uCode verification failed at "
2497 2498 2499
			       "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
			       BSM_SRAM_LOWER_BOUND, reg - BSM_SRAM_LOWER_BOUND,
			       len, val, le32_to_cpu(*image));
K
Kolekar, Abhijeet 已提交
2500 2501 2502 2503
			return -EIO;
		}
	}

2504
	D_INFO("BSM bootstrap uCode image OK\n");
K
Kolekar, Abhijeet 已提交
2505 2506 2507 2508

	return 0;
}

2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522
/******************************************************************************
 *
 * EEPROM related functions
 *
 ******************************************************************************/

/*
 * Clear the OWNER_MSK, to establish driver (instead of uCode running on
 * embedded controller) as EEPROM reader; each read is a series of pulses
 * to/from the EEPROM chip, not a single event, so even reads could conflict
 * if they weren't arbitrated by some ownership mechanism.  Here, the driver
 * simply claims ownership, which should be safe when this function is called
 * (i.e. before loading uCode!).
 */
2523 2524
static int
il3945_eeprom_acquire_semaphore(struct il_priv *il)
2525
{
S
Stanislaw Gruszka 已提交
2526
	_il_clear_bit(il, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
2527 2528 2529
	return 0;
}

2530 2531
static void
il3945_eeprom_release_semaphore(struct il_priv *il)
2532 2533 2534 2535
{
	return;
}

K
Kolekar, Abhijeet 已提交
2536
 /**
S
Stanislaw Gruszka 已提交
2537
  * il3945_load_bsm - Load bootstrap instructions
K
Kolekar, Abhijeet 已提交
2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
  *
  * BSM operation:
  *
  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
  * in special SRAM that does not power down during RFKILL.  When powering back
  * up after power-saving sleeps (or during initial uCode load), the BSM loads
  * the bootstrap program into the on-board processor, and starts it.
  *
  * The bootstrap program loads (via DMA) instructions and data for a new
  * program from host DRAM locations indicated by the host driver in the
  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
  * automatically.
  *
  * When initializing the NIC, the host driver points the BSM to the
  * "initialize" uCode image.  This uCode sets up some internal data, then
  * notifies host via "initialize alive" that it is complete.
  *
  * The host then replaces the BSM_DRAM_* pointer values to point to the
  * normal runtime uCode instructions and a backup uCode data cache buffer
  * (filled initially with starting data values for the on-board processor),
  * then triggers the "initialize" uCode to load and launch the runtime uCode,
  * which begins normal operation.
  *
  * When doing a power-save shutdown, runtime uCode saves data SRAM into
  * the backup data cache in DRAM before SRAM is powered down.
  *
  * When powering back up, the BSM loads the bootstrap program.  This reloads
  * the runtime uCode instructions and the backup data cache into SRAM,
  * and re-launches the runtime uCode from where it left off.
  */
2568 2569
static int
il3945_load_bsm(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
2570
{
S
Stanislaw Gruszka 已提交
2571 2572
	__le32 *image = il->ucode_boot.v_addr;
	u32 len = il->ucode_boot.len;
K
Kolekar, Abhijeet 已提交
2573 2574 2575 2576 2577 2578 2579 2580 2581
	dma_addr_t pinst;
	dma_addr_t pdata;
	u32 inst_len;
	u32 data_len;
	int rc;
	int i;
	u32 done;
	u32 reg_offset;

2582
	D_INFO("Begin load bsm\n");
K
Kolekar, Abhijeet 已提交
2583 2584

	/* make sure bootstrap program is no larger than BSM's SRAM size */
2585
	if (len > IL39_MAX_BSM_SIZE)
K
Kolekar, Abhijeet 已提交
2586 2587 2588
		return -EINVAL;

	/* Tell bootstrap uCode where to find the "Initialize" uCode
2589 2590 2591 2592
	 *   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
	 * NOTE:  il3945_initialize_alive_start() will replace these values,
	 *        after the "initialize" uCode has run, to point to
	 *        runtime/protocol instructions and backup data cache. */
S
Stanislaw Gruszka 已提交
2593 2594 2595 2596
	pinst = il->ucode_init.p_addr;
	pdata = il->ucode_init_data.p_addr;
	inst_len = il->ucode_init.len;
	data_len = il->ucode_init_data.len;
K
Kolekar, Abhijeet 已提交
2597

2598 2599 2600 2601
	il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
	il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
	il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
	il_wr_prph(il, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
K
Kolekar, Abhijeet 已提交
2602 2603 2604 2605 2606

	/* Fill BSM memory with bootstrap instructions */
	for (reg_offset = BSM_SRAM_LOWER_BOUND;
	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
	     reg_offset += sizeof(u32), image++)
2607
		_il_wr_prph(il, reg_offset, le32_to_cpu(*image));
K
Kolekar, Abhijeet 已提交
2608

S
Stanislaw Gruszka 已提交
2609
	rc = il3945_verify_bsm(il);
M
Mohamed Abbas 已提交
2610
	if (rc)
K
Kolekar, Abhijeet 已提交
2611 2612 2613
		return rc;

	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
2614
	il_wr_prph(il, BSM_WR_MEM_SRC_REG, 0x0);
2615
	il_wr_prph(il, BSM_WR_MEM_DST_REG, IL39_RTC_INST_LOWER_BOUND);
2616
	il_wr_prph(il, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
K
Kolekar, Abhijeet 已提交
2617 2618 2619

	/* Load bootstrap code into instruction SRAM now,
	 *   to prepare to load "initialize" uCode */
2620
	il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
K
Kolekar, Abhijeet 已提交
2621 2622 2623

	/* Wait for load of bootstrap uCode to finish */
	for (i = 0; i < 100; i++) {
2624
		done = il_rd_prph(il, BSM_WR_CTRL_REG);
K
Kolekar, Abhijeet 已提交
2625 2626 2627 2628 2629
		if (!(done & BSM_WR_CTRL_REG_BIT_START))
			break;
		udelay(10);
	}
	if (i < 100)
2630
		D_INFO("BSM write complete, poll %d iterations\n", i);
K
Kolekar, Abhijeet 已提交
2631
	else {
2632
		IL_ERR("BSM write did not complete!\n");
K
Kolekar, Abhijeet 已提交
2633 2634 2635 2636 2637
		return -EIO;
	}

	/* Enable future boot loads whenever power management unit triggers it
	 *   (e.g. when powering back up after power-save shutdown) */
2638
	il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
K
Kolekar, Abhijeet 已提交
2639 2640 2641 2642

	return 0;
}

S
Stanislaw Gruszka 已提交
2643 2644 2645
static struct il_hcmd_ops il3945_hcmd = {
	.rxon_assoc = il3945_send_rxon_assoc,
	.commit_rxon = il3945_commit_rxon,
2646 2647
};

S
Stanislaw Gruszka 已提交
2648 2649 2650 2651 2652 2653
static struct il_lib_ops il3945_lib = {
	.txq_attach_buf_to_tfd = il3945_hw_txq_attach_buf_to_tfd,
	.txq_free_tfd = il3945_hw_txq_free_tfd,
	.txq_init = il3945_hw_tx_queue_init,
	.load_ucode = il3945_load_bsm,
	.dump_nic_error_log = il3945_dump_nic_error_log,
K
Kolekar, Abhijeet 已提交
2654
	.apm_ops = {
2655 2656 2657
		    .init = il3945_apm_init,
		    .config = il3945_nic_config,
		    },
2658
	.eeprom_ops = {
2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671
		       .regulatory_bands = {
					    EEPROM_REGULATORY_BAND_1_CHANNELS,
					    EEPROM_REGULATORY_BAND_2_CHANNELS,
					    EEPROM_REGULATORY_BAND_3_CHANNELS,
					    EEPROM_REGULATORY_BAND_4_CHANNELS,
					    EEPROM_REGULATORY_BAND_5_CHANNELS,
					    EEPROM_REGULATORY_BAND_NO_HT40,
					    EEPROM_REGULATORY_BAND_NO_HT40,
					    },
		       .acquire_semaphore = il3945_eeprom_acquire_semaphore,
		       .release_semaphore = il3945_eeprom_release_semaphore,
		       },
	.send_tx_power = il3945_send_tx_power,
S
Stanislaw Gruszka 已提交
2672
	.is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr,
A
Abhijeet Kolekar 已提交
2673 2674

	.debugfs_ops = {
2675 2676 2677 2678
			.rx_stats_read = il3945_ucode_rx_stats_read,
			.tx_stats_read = il3945_ucode_tx_stats_read,
			.general_stats_read = il3945_ucode_general_stats_read,
			},
K
Kolekar, Abhijeet 已提交
2679 2680
};

S
Stanislaw Gruszka 已提交
2681 2682 2683 2684
static const struct il_legacy_ops il3945_legacy_ops = {
	.post_associate = il3945_post_associate,
	.config_ap = il3945_config_ap,
	.manage_ibss_station = il3945_manage_ibss_station,
2685 2686
};

S
Stanislaw Gruszka 已提交
2687 2688 2689 2690 2691
static struct il_hcmd_utils_ops il3945_hcmd_utils = {
	.get_hcmd_size = il3945_get_hcmd_size,
	.build_addsta_hcmd = il3945_build_addsta_hcmd,
	.request_scan = il3945_request_scan,
	.post_scan = il3945_post_scan,
K
Kolekar, Abhijeet 已提交
2692 2693
};

S
Stanislaw Gruszka 已提交
2694 2695 2696 2697 2698 2699 2700
static const struct il_ops il3945_ops = {
	.lib = &il3945_lib,
	.hcmd = &il3945_hcmd,
	.utils = &il3945_hcmd_utils,
	.led = &il3945_led_ops,
	.legacy = &il3945_legacy_ops,
	.ieee80211_ops = &il3945_hw_ops,
K
Kolekar, Abhijeet 已提交
2701 2702
};

S
Stanislaw Gruszka 已提交
2703
static struct il_base_params il3945_base_params = {
2704 2705
	.eeprom_size = IL3945_EEPROM_IMG_SIZE,
	.num_of_queues = IL39_NUM_QUEUES,
2706 2707 2708
	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
	.set_l0s = false,
	.use_bsm = true,
2709
	.led_compensation = 64,
S
Stanislaw Gruszka 已提交
2710
	.wd_timeout = IL_DEF_WD_TIMEOUT,
T
Tomas Winkler 已提交
2711 2712
};

S
Stanislaw Gruszka 已提交
2713
static struct il_cfg il3945_bg_cfg = {
2714
	.name = "3945BG",
2715 2716 2717
	.fw_name_pre = IL3945_FW_PRE,
	.ucode_api_max = IL3945_UCODE_API_MAX,
	.ucode_api_min = IL3945_UCODE_API_MIN,
S
Stanislaw Gruszka 已提交
2718
	.sku = IL_SKU_G,
2719
	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
S
Stanislaw Gruszka 已提交
2720 2721 2722 2723
	.ops = &il3945_ops,
	.mod_params = &il3945_mod_params,
	.base_params = &il3945_base_params,
	.led_mode = IL_LED_BLINK,
2724 2725
};

S
Stanislaw Gruszka 已提交
2726
static struct il_cfg il3945_abg_cfg = {
T
Tomas Winkler 已提交
2727
	.name = "3945ABG",
2728 2729 2730
	.fw_name_pre = IL3945_FW_PRE,
	.ucode_api_max = IL3945_UCODE_API_MAX,
	.ucode_api_min = IL3945_UCODE_API_MIN,
2731
	.sku = IL_SKU_A | IL_SKU_G,
2732
	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
S
Stanislaw Gruszka 已提交
2733 2734 2735 2736
	.ops = &il3945_ops,
	.mod_params = &il3945_mod_params,
	.base_params = &il3945_base_params,
	.led_mode = IL_LED_BLINK,
T
Tomas Winkler 已提交
2737 2738
};

S
Stanislaw Gruszka 已提交
2739
DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = {
S
Stanislaw Gruszka 已提交
2740 2741 2742 2743 2744 2745 2746
	{IL_PCI_DEVICE(0x4222, 0x1005, il3945_bg_cfg)},
	{IL_PCI_DEVICE(0x4222, 0x1034, il3945_bg_cfg)},
	{IL_PCI_DEVICE(0x4222, 0x1044, il3945_bg_cfg)},
	{IL_PCI_DEVICE(0x4227, 0x1014, il3945_bg_cfg)},
	{IL_PCI_DEVICE(0x4222, PCI_ANY_ID, il3945_abg_cfg)},
	{IL_PCI_DEVICE(0x4227, PCI_ANY_ID, il3945_abg_cfg)},
	{0}
Z
Zhu Yi 已提交
2747 2748
};

S
Stanislaw Gruszka 已提交
2749
MODULE_DEVICE_TABLE(pci, il3945_hw_card_ids);