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
void
il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
			    struct ieee80211_tx_info *info,
683
			    struct ieee80211_hdr *hdr, int sta_id)
Z
Zhu Yi 已提交
684
{
S
Stanislaw Gruszka 已提交
685
	u16 hw_value = ieee80211_get_tx_rate(il->hw, info)->hw_value;
686
	u16 rate_idx = min(hw_value & 0xffff, RATE_COUNT_3945 - 1);
Z
Zhu Yi 已提交
687 688
	u16 rate_mask;
	int rate;
689
	const u8 rts_retry_limit = 7;
Z
Zhu Yi 已提交
690 691
	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
	tx_cmd->data_retry_limit = data_retry_limit;
708 709
	/* Set retry limit on RTS packets */
	tx_cmd->rts_retry_limit = min(data_retry_limit, rts_retry_limit);
Z
Zhu Yi 已提交
710

A
Abhijeet Kolekar 已提交
711 712
	tx_cmd->rate = rate;
	tx_cmd->tx_flags = tx_flags;
Z
Zhu Yi 已提交
713 714

	/* OFDM */
A
Abhijeet Kolekar 已提交
715
	tx_cmd->supp_rates[0] =
716
	    ((rate_mask & IL_OFDM_RATES_MASK) >> IL_FIRST_OFDM_RATE) & 0xFF;
Z
Zhu Yi 已提交
717 718

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

721
	D_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
722 723 724
	       "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 已提交
725 726
}

727 728
static u8
il3945_sync_sta(struct il_priv *il, int sta_id, u16 tx_rate)
Z
Zhu Yi 已提交
729 730
{
	unsigned long flags_spin;
S
Stanislaw Gruszka 已提交
731
	struct il_station_entry *station;
Z
Zhu Yi 已提交
732

S
Stanislaw Gruszka 已提交
733 734
	if (sta_id == IL_INVALID_STATION)
		return IL_INVALID_STATION;
Z
Zhu Yi 已提交
735

S
Stanislaw Gruszka 已提交
736 737
	spin_lock_irqsave(&il->sta_lock, flags_spin);
	station = &il->stations[sta_id];
Z
Zhu Yi 已提交
738 739 740 741

	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 已提交
742 743
	il_send_add_sta(il, &station->sta, CMD_ASYNC);
	spin_unlock_irqrestore(&il->sta_lock, flags_spin);
Z
Zhu Yi 已提交
744

745
	D_RATE("SCALE sync station %d to rate %d\n", sta_id, tx_rate);
Z
Zhu Yi 已提交
746 747 748
	return sta_id;
}

749 750
static void
il3945_set_pwr_vmain(struct il_priv *il)
Z
Zhu Yi 已提交
751
{
752 753 754 755
/*
 * (for documentation purposes)
 * to set power to V_AUX, do

S
Stanislaw Gruszka 已提交
756 757
		if (pci_pme_capable(il->pci_dev, PCI_D3cold)) {
			il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
Z
Zhu Yi 已提交
758 759 760
					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
					~APMG_PS_CTRL_MSK_PWR_SRC);

761
			_il_poll_bit(il, CSR_GPIO_IN,
Z
Zhu Yi 已提交
762 763
				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
764
		}
765
 */
Z
Zhu Yi 已提交
766

S
Stanislaw Gruszka 已提交
767
	il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
768 769
			      APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
			      ~APMG_PS_CTRL_MSK_PWR_SRC);
Z
Zhu Yi 已提交
770

S
Stanislaw Gruszka 已提交
771 772
	_il_poll_bit(il, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
Z
Zhu Yi 已提交
773 774
}

775 776
static int
il3945_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
Z
Zhu Yi 已提交
777
{
778
	il_wr(il, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
779
	il_wr(il, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
780 781
	il_wr(il, FH39_RCSR_WPTR(0), 0);
	il_wr(il, FH39_RCSR_CONFIG(0),
782 783 784 785 786 787 788 789 790
	      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 已提交
791 792

	/* fake read to flush all prev I/O */
793
	il_rd(il, FH39_RSSR_CTRL);
Z
Zhu Yi 已提交
794 795 796 797

	return 0;
}

798 799
static int
il3945_tx_reset(struct il_priv *il)
Z
Zhu Yi 已提交
800 801 802
{

	/* bypass mode */
803
	il_wr_prph(il, ALM_SCD_MODE_REG, 0x2);
Z
Zhu Yi 已提交
804 805

	/* RA 0 is active */
806
	il_wr_prph(il, ALM_SCD_ARASTAT_REG, 0x01);
Z
Zhu Yi 已提交
807 808

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

811 812 813 814
	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 已提交
815

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

818
	il_wr(il, FH39_TSSR_MSG_CONFIG,
819 820 821 822 823 824 825
	      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 已提交
826 827 828 829 830

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
831
 * il3945_txq_ctx_reset - Reset TX queue context
Z
Zhu Yi 已提交
832 833 834
 *
 * Destroys all DMA structures and initialize them again
 */
835 836
static int
il3945_txq_ctx_reset(struct il_priv *il)
Z
Zhu Yi 已提交
837 838 839 840
{
	int rc;
	int txq_id, slots_num;

S
Stanislaw Gruszka 已提交
841
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
842

843
	/* allocate tx queue structure */
S
Stanislaw Gruszka 已提交
844
	rc = il_alloc_txq_mem(il);
845 846 847
	if (rc)
		return rc;

Z
Zhu Yi 已提交
848
	/* Tx CMD queue */
S
Stanislaw Gruszka 已提交
849
	rc = il3945_tx_reset(il);
Z
Zhu Yi 已提交
850 851 852 853
	if (rc)
		goto error;

	/* Tx queue(s) */
S
Stanislaw Gruszka 已提交
854
	for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
855 856 857 858
		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 已提交
859
		if (rc) {
860
			IL_ERR("Tx %d queue init failed\n", txq_id);
Z
Zhu Yi 已提交
861 862 863 864 865 866
			goto error;
		}
	}

	return rc;

867
error:
S
Stanislaw Gruszka 已提交
868
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
869 870 871
	return rc;
}

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

B
Ben Cahill 已提交
882
	/* Clear APMG (NIC's internal power management) interrupts */
883 884
	il_wr_prph(il, APMG_RTC_INT_MSK_REG, 0x0);
	il_wr_prph(il, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
B
Ben Cahill 已提交
885 886

	/* Reset radio chip */
887
	il_set_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
B
Ben Cahill 已提交
888
	udelay(5);
889
	il_clear_bits_prph(il, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
B
Ben Cahill 已提交
890

K
Kolekar, Abhijeet 已提交
891 892
	return ret;
}
Z
Zhu Yi 已提交
893

894 895
static void
il3945_nic_config(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
896
{
S
Stanislaw Gruszka 已提交
897
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
K
Kolekar, Abhijeet 已提交
898
	unsigned long flags;
S
Stanislaw Gruszka 已提交
899
	u8 rev_id = il->pci_dev->revision;
Z
Zhu Yi 已提交
900

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

903
	/* Determine HW type */
904
	D_INFO("HW Revision ID = 0x%X\n", rev_id);
905

Z
Zhu Yi 已提交
906
	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
907
		D_INFO("RTP type\n");
Z
Zhu Yi 已提交
908
	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
909
		D_INFO("3945 RADIO-MB type\n");
S
Stanislaw Gruszka 已提交
910
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
911
			   CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
Z
Zhu Yi 已提交
912
	} else {
913
		D_INFO("3945 RADIO-MM type\n");
S
Stanislaw Gruszka 已提交
914
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
915
			   CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
Z
Zhu Yi 已提交
916 917
	}

918
	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
919
		D_INFO("SKU OP mode is mrc\n");
S
Stanislaw Gruszka 已提交
920
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
921
			   CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
Z
Zhu Yi 已提交
922
	} else
923
		D_INFO("SKU OP mode is basic\n");
Z
Zhu Yi 已提交
924

925
	if ((eeprom->board_revision & 0xF0) == 0xD0) {
926
		D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
S
Stanislaw Gruszka 已提交
927
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
928
			   CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
Z
Zhu Yi 已提交
929
	} else {
930
		D_INFO("3945ABG revision is 0x%X\n", eeprom->board_revision);
S
Stanislaw Gruszka 已提交
931
		il_clear_bit(il, CSR_HW_IF_CONFIG_REG,
932
			     CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
Z
Zhu Yi 已提交
933 934
	}

935
	if (eeprom->almgor_m_version <= 1) {
S
Stanislaw Gruszka 已提交
936
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
937
			   CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
938
		D_INFO("Card M type A version is 0x%X\n",
939
		       eeprom->almgor_m_version);
Z
Zhu Yi 已提交
940
	} else {
941
		D_INFO("Card M type B version is 0x%X\n",
942
		       eeprom->almgor_m_version);
S
Stanislaw Gruszka 已提交
943
		il_set_bit(il, CSR_HW_IF_CONFIG_REG,
944
			   CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
Z
Zhu Yi 已提交
945
	}
S
Stanislaw Gruszka 已提交
946
	spin_unlock_irqrestore(&il->lock, flags);
Z
Zhu Yi 已提交
947

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

951
	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
952
		D_RF_KILL("HW RF KILL supported in EEPROM.\n");
K
Kolekar, Abhijeet 已提交
953 954
}

955 956
int
il3945_hw_nic_init(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
957 958 959
{
	int rc;
	unsigned long flags;
S
Stanislaw Gruszka 已提交
960
	struct il_rx_queue *rxq = &il->rxq;
K
Kolekar, Abhijeet 已提交
961

S
Stanislaw Gruszka 已提交
962 963 964
	spin_lock_irqsave(&il->lock, flags);
	il->cfg->ops->lib->apm_ops.init(il);
	spin_unlock_irqrestore(&il->lock, flags);
K
Kolekar, Abhijeet 已提交
965

S
Stanislaw Gruszka 已提交
966
	il3945_set_pwr_vmain(il);
K
Kolekar, Abhijeet 已提交
967

S
Stanislaw Gruszka 已提交
968
	il->cfg->ops->lib->apm_ops.config(il);
Z
Zhu Yi 已提交
969 970 971

	/* Allocate the RX queue, or reset if it is already allocated */
	if (!rxq->bd) {
S
Stanislaw Gruszka 已提交
972
		rc = il_rx_queue_alloc(il);
Z
Zhu Yi 已提交
973
		if (rc) {
974
			IL_ERR("Unable to initialize Rx queue\n");
Z
Zhu Yi 已提交
975 976 977
			return -ENOMEM;
		}
	} else
S
Stanislaw Gruszka 已提交
978
		il3945_rx_queue_reset(il, rxq);
Z
Zhu Yi 已提交
979

S
Stanislaw Gruszka 已提交
980
	il3945_rx_replenish(il);
Z
Zhu Yi 已提交
981

S
Stanislaw Gruszka 已提交
982
	il3945_rx_init(il, rxq);
Z
Zhu Yi 已提交
983 984

	/* Look at using this instead:
985 986 987
	   rxq->need_update = 1;
	   il_rx_queue_update_write_ptr(il, rxq);
	 */
Z
Zhu Yi 已提交
988

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

S
Stanislaw Gruszka 已提交
991
	rc = il3945_txq_ctx_reset(il);
Z
Zhu Yi 已提交
992 993 994
	if (rc)
		return rc;

S
Stanislaw Gruszka 已提交
995
	set_bit(S_INIT, &il->status);
Z
Zhu Yi 已提交
996 997 998 999 1000

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
1001
 * il3945_hw_txq_ctx_free - Free TXQ Context
Z
Zhu Yi 已提交
1002 1003 1004
 *
 * Destroy all TX DMA queues and structures
 */
1005 1006
void
il3945_hw_txq_ctx_free(struct il_priv *il)
Z
Zhu Yi 已提交
1007 1008 1009 1010
{
	int txq_id;

	/* Tx queues */
S
Stanislaw Gruszka 已提交
1011
	if (il->txq)
1012
		for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
1013
			if (txq_id == IL39_CMD_QUEUE_NUM)
S
Stanislaw Gruszka 已提交
1014
				il_cmd_queue_free(il);
1015
			else
S
Stanislaw Gruszka 已提交
1016
				il_tx_queue_free(il, txq_id);
1017

1018
	/* free tx queue structure */
S
Stanislaw Gruszka 已提交
1019
	il_txq_mem(il);
Z
Zhu Yi 已提交
1020 1021
}

1022 1023
void
il3945_hw_txq_ctx_stop(struct il_priv *il)
Z
Zhu Yi 已提交
1024
{
1025
	int txq_id;
Z
Zhu Yi 已提交
1026 1027

	/* stop SCD */
1028 1029
	il_wr_prph(il, ALM_SCD_MODE_REG, 0);
	il_wr_prph(il, ALM_SCD_TXFACT_REG, 0);
Z
Zhu Yi 已提交
1030 1031

	/* reset TFD queues */
S
Stanislaw Gruszka 已提交
1032
	for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
1033 1034
		il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0);
		il_poll_bit(il, FH39_TSSR_TX_STATUS,
1035 1036
			    FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
			    1000);
Z
Zhu Yi 已提交
1037 1038
	}

S
Stanislaw Gruszka 已提交
1039
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
1040 1041 1042
}

/**
S
Stanislaw Gruszka 已提交
1043
 * il3945_hw_reg_adjust_power_by_temp
S
Stanislaw Gruszka 已提交
1044
 * return idx delta into power gain settings table
1045
*/
1046 1047
static int
il3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
Z
Zhu Yi 已提交
1048 1049 1050 1051 1052
{
	return (new_reading - old_reading) * (-11) / 100;
}

/**
S
Stanislaw Gruszka 已提交
1053
 * il3945_hw_reg_temp_out_of_range - Keep temperature in sane range
Z
Zhu Yi 已提交
1054
 */
1055 1056
static inline int
il3945_hw_reg_temp_out_of_range(int temperature)
Z
Zhu Yi 已提交
1057
{
1058
	return (temperature < -260 || temperature > 25) ? 1 : 0;
Z
Zhu Yi 已提交
1059 1060
}

1061 1062
int
il3945_hw_get_temperature(struct il_priv *il)
Z
Zhu Yi 已提交
1063
{
1064
	return _il_rd(il, CSR_UCODE_DRV_GP2);
Z
Zhu Yi 已提交
1065 1066 1067
}

/**
S
Stanislaw Gruszka 已提交
1068
 * il3945_hw_reg_txpower_get_temperature
1069 1070
 * get the current temperature by reading from NIC
*/
1071 1072
static int
il3945_hw_reg_txpower_get_temperature(struct il_priv *il)
Z
Zhu Yi 已提交
1073
{
S
Stanislaw Gruszka 已提交
1074
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Z
Zhu Yi 已提交
1075 1076
	int temperature;

S
Stanislaw Gruszka 已提交
1077
	temperature = il3945_hw_get_temperature(il);
Z
Zhu Yi 已提交
1078 1079 1080

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

	/* handle insane temp reading */
S
Stanislaw Gruszka 已提交
1084
	if (il3945_hw_reg_temp_out_of_range(temperature)) {
1085
		IL_ERR("Error bad temperature value  %d\n", temperature);
Z
Zhu Yi 已提交
1086 1087 1088

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

	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 已提交
1101
#define IL_TEMPERATURE_LIMIT_TIMER   6
Z
Zhu Yi 已提交
1102 1103

/**
S
Stanislaw Gruszka 已提交
1104
 * il3945_is_temp_calib_needed - determines if new calibration is needed
Z
Zhu Yi 已提交
1105 1106 1107 1108
 *
 * records new temperature in tx_mgr->temperature.
 * replaces tx_mgr->last_temperature *only* if calib needed
 *    (assumes caller will actually do the calibration!). */
1109 1110
static int
il3945_is_temp_calib_needed(struct il_priv *il)
Z
Zhu Yi 已提交
1111 1112 1113
{
	int temp_diff;

S
Stanislaw Gruszka 已提交
1114 1115
	il->temperature = il3945_hw_reg_txpower_get_temperature(il);
	temp_diff = il->temperature - il->last_temperature;
Z
Zhu Yi 已提交
1116 1117 1118

	/* get absolute value */
	if (temp_diff < 0) {
1119
		D_POWER("Getting cooler, delta %d,\n", temp_diff);
Z
Zhu Yi 已提交
1120 1121
		temp_diff = -temp_diff;
	} else if (temp_diff == 0)
1122
		D_POWER("Same temp,\n");
Z
Zhu Yi 已提交
1123
	else
1124
		D_POWER("Getting warmer, delta %d,\n", temp_diff);
Z
Zhu Yi 已提交
1125 1126

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

1132
	D_POWER("Timed thermal calib needed\n");
Z
Zhu Yi 已提交
1133 1134 1135

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

S
Stanislaw Gruszka 已提交
1140 1141
#define IL_MAX_GAIN_ENTRIES 78
#define IL_CCK_FROM_OFDM_POWER_DIFF  -5
S
Stanislaw Gruszka 已提交
1142
#define IL_CCK_FROM_OFDM_IDX_DIFF (10)
Z
Zhu Yi 已提交
1143 1144 1145

/* 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 已提交
1146
static struct il3945_tx_power power_gain_table[2][IL_MAX_GAIN_ENTRIES] = {
Z
Zhu Yi 已提交
1147 1148 1149 1150 1151 1152 1153 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
	{
	 {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 已提交
1225 1226
	 {3, 95}		/* 2.4 GHz, lowest power */
	},
Z
Zhu Yi 已提交
1227 1228 1229 1230 1231 1232 1233 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
	{
	 {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 已提交
1305 1306
	 {3, 120}		/* 5.x GHz, lowest power */
	}
Z
Zhu Yi 已提交
1307 1308
};

1309 1310
static inline u8
il3945_hw_reg_fix_power_idx(int idx)
Z
Zhu Yi 已提交
1311
{
S
Stanislaw Gruszka 已提交
1312
	if (idx < 0)
Z
Zhu Yi 已提交
1313
		return 0;
S
Stanislaw Gruszka 已提交
1314
	if (idx >= IL_MAX_GAIN_ENTRIES)
S
Stanislaw Gruszka 已提交
1315
		return IL_MAX_GAIN_ENTRIES - 1;
S
Stanislaw Gruszka 已提交
1316
	return (u8) idx;
Z
Zhu Yi 已提交
1317 1318 1319 1320 1321 1322
}

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

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

S
Stanislaw Gruszka 已提交
1337
	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_idx];
Z
Zhu Yi 已提交
1338 1339 1340 1341

	/* 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 已提交
1342
	power = min(ch_info->scan_power, clip_pwrs[RATE_6M_IDX_TBL]);
Z
Zhu Yi 已提交
1343

S
Stanislaw Gruszka 已提交
1344
	power = min(power, il->tx_power_user_lmt);
Z
Zhu Yi 已提交
1345 1346 1347 1348
	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 已提交
1349
	 *   current "normal" temperature-compensated Tx power *idx* for
Z
Zhu Yi 已提交
1350
	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
S
Stanislaw Gruszka 已提交
1351
	 *   *idx*. */
1352 1353 1354 1355 1356 1357 1358
	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 已提交
1359

S
Stanislaw Gruszka 已提交
1360
	/* store reference idx that we use when adjusting *all* scan
Z
Zhu Yi 已提交
1361 1362 1363
	 *   powers.  So we can accommodate user (all channel) or spectrum
	 *   management (single channel) power changes "between" temperature
	 *   feedback compensation procedures.
S
Stanislaw Gruszka 已提交
1364
	 * don't force fit this reference idx into gain table; it may be a
Z
Zhu Yi 已提交
1365 1366 1367 1368 1369
	 *   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 已提交
1370
	power_idx = il3945_hw_reg_fix_power_idx(power_idx);
Z
Zhu Yi 已提交
1371

S
Stanislaw Gruszka 已提交
1372
	scan_power_info->power_table_idx = power_idx;
Z
Zhu Yi 已提交
1373
	scan_power_info->tpc.tx_gain =
S
Stanislaw Gruszka 已提交
1374
	    power_gain_table[band_idx][power_idx].tx_gain;
Z
Zhu Yi 已提交
1375
	scan_power_info->tpc.dsp_atten =
S
Stanislaw Gruszka 已提交
1376
	    power_gain_table[band_idx][power_idx].dsp_atten;
Z
Zhu Yi 已提交
1377 1378 1379
}

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

1395 1396 1397
	if (WARN_ONCE
	    (test_bit(S_SCAN_HW, &il->status),
	     "TX Power requested while scanning!\n"))
1398 1399
		return -EAGAIN;

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

S
Stanislaw Gruszka 已提交
1402 1403
	txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
	ch_info = il_get_channel_info(il, il->band, chan);
Z
Zhu Yi 已提交
1404
	if (!ch_info) {
1405 1406
		IL_ERR("Failed to get channel info for channel %d [%d]\n", chan,
		       il->band);
Z
Zhu Yi 已提交
1407 1408 1409
		return -EINVAL;
	}

S
Stanislaw Gruszka 已提交
1410
	if (!il_is_channel_valid(ch_info)) {
1411
		D_POWER("Not calling TX_PWR_TBL_CMD on " "non-Tx channel.\n");
Z
Zhu Yi 已提交
1412 1413 1414 1415
		return 0;
	}

	/* fill cmd with power settings for all rates for current channel */
1416
	/* Fill OFDM rate */
S
Stanislaw Gruszka 已提交
1417
	for (rate_idx = IL_FIRST_OFDM_RATE, i = 0;
1418
	     rate_idx <= IL39_LAST_OFDM_RATE; rate_idx++, i++) {
1419 1420

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

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

1434
		D_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
1435 1436 1437
			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 已提交
1438 1439
	}

1440
	return il_send_cmd_pdu(il, C_TX_PWR_TBL,
1441 1442
			       sizeof(struct il3945_txpowertable_cmd),
			       &txpower);
Z
Zhu Yi 已提交
1443 1444 1445 1446

}

/**
S
Stanislaw Gruszka 已提交
1447
 * il3945_hw_reg_set_new_power - Configures power tables at new levels
Z
Zhu Yi 已提交
1448 1449
 * @ch_info: Channel to update.  Uses power_info.requested_power.
 *
S
Stanislaw Gruszka 已提交
1450
 * Replace requested_power and base_power_idx ch_info fields for
Z
Zhu Yi 已提交
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461
 * 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
 */
1462 1463
static int
il3945_hw_reg_set_new_power(struct il_priv *il, struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1464
{
S
Stanislaw Gruszka 已提交
1465
	struct il3945_channel_power_info *power_info;
Z
Zhu Yi 已提交
1466 1467 1468 1469 1470 1471
	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 已提交
1472
	clip_pwrs = il->_3945.clip_groups[ch_info->group_idx].clip_powers;
Z
Zhu Yi 已提交
1473 1474 1475 1476 1477

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

	/* update OFDM Txpower settings */
1478
	for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++, ++power_info) {
Z
Zhu Yi 已提交
1479 1480 1481 1482 1483 1484 1485 1486
		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 已提交
1487
		 *    update base (non-temp-compensated) power idx */
Z
Zhu Yi 已提交
1488
		delta_idx = (power - power_info->requested_power) * 2;
S
Stanislaw Gruszka 已提交
1489
		power_info->base_power_idx -= delta_idx;
Z
Zhu Yi 已提交
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500

		/* 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 =
1501 1502
		    ch_info->power_info[RATE_12M_IDX_TBL].requested_power +
		    IL_CCK_FROM_OFDM_POWER_DIFF;
Z
Zhu Yi 已提交
1503

S
Stanislaw Gruszka 已提交
1504
		/* do all CCK rates' il3945_channel_power_info structures */
S
Stanislaw Gruszka 已提交
1505
		for (i = RATE_1M_IDX_TBL; i <= RATE_11M_IDX_TBL; i++) {
Z
Zhu Yi 已提交
1506
			power_info->requested_power = power;
S
Stanislaw Gruszka 已提交
1507
			power_info->base_power_idx =
S
Stanislaw Gruszka 已提交
1508
			    ch_info->power_info[RATE_12M_IDX_TBL].
S
Stanislaw Gruszka 已提交
1509
			    base_power_idx + IL_CCK_FROM_OFDM_IDX_DIFF;
Z
Zhu Yi 已提交
1510 1511 1512 1513 1514 1515 1516 1517
			++power_info;
		}
	}

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
1518
 * il3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
Z
Zhu Yi 已提交
1519 1520 1521 1522 1523
 *
 * 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).
 */
1524 1525
static int
il3945_hw_reg_get_ch_txpower_limit(struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1526 1527 1528 1529 1530 1531
{
	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)
1532 1533 1534
		max_power =
		    min(ch_info->tgd_data.max_power,
			ch_info->eeprom.max_power_avg);
Z
Zhu Yi 已提交
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544

	/* 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 已提交
1545
 * il3945_hw_reg_comp_txpower_temp - Compensate for temperature
Z
Zhu Yi 已提交
1546 1547 1548 1549
 *
 * 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 已提交
1550
 *   on the channel's base_power_idx.
Z
Zhu Yi 已提交
1551 1552 1553
 *
 * If RxOn is "associated", this sends the new Txpower to NIC!
 */
1554 1555
static int
il3945_hw_reg_comp_txpower_temp(struct il_priv *il)
Z
Zhu Yi 已提交
1556
{
S
Stanislaw Gruszka 已提交
1557
	struct il_channel_info *ch_info = NULL;
S
Stanislaw Gruszka 已提交
1558
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1559
	int delta_idx;
1560
	const s8 *clip_pwrs;	/* array of h/w max power levels for each rate */
Z
Zhu Yi 已提交
1561
	u8 a_band;
S
Stanislaw Gruszka 已提交
1562 1563
	u8 rate_idx;
	u8 scan_tbl_idx;
Z
Zhu Yi 已提交
1564 1565
	u8 i;
	int ref_temp;
S
Stanislaw Gruszka 已提交
1566
	int temperature = il->temperature;
Z
Zhu Yi 已提交
1567

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

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

S
Stanislaw Gruszka 已提交
1580
		/* get power idx adjustment based on current and factory
Z
Zhu Yi 已提交
1581
		 * temps */
1582 1583
		delta_idx =
		    il3945_hw_reg_adjust_power_by_temp(temperature, ref_temp);
Z
Zhu Yi 已提交
1584 1585

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

			/* temperature compensate */
S
Stanislaw Gruszka 已提交
1591
			power_idx += delta_idx;
Z
Zhu Yi 已提交
1592 1593

			/* stay within table range */
S
Stanislaw Gruszka 已提交
1594
			power_idx = il3945_hw_reg_fix_power_idx(power_idx);
1595 1596
			ch_info->power_info[rate_idx].power_table_idx =
			    (u8) power_idx;
S
Stanislaw Gruszka 已提交
1597
			ch_info->power_info[rate_idx].tpc =
Z
Zhu Yi 已提交
1598 1599 1600 1601
			    power_gain_table[a_band][power_idx];
		}

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

		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
1606 1607 1608 1609 1610
		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 已提交
1611
			il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
1612 1613
						     actual_idx, clip_pwrs,
						     ch_info, a_band);
Z
Zhu Yi 已提交
1614 1615 1616 1617
		}
	}

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

1621 1622
int
il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
Z
Zhu Yi 已提交
1623
{
S
Stanislaw Gruszka 已提交
1624
	struct il_channel_info *ch_info;
Z
Zhu Yi 已提交
1625 1626 1627 1628
	s8 max_power;
	u8 a_band;
	u8 i;

S
Stanislaw Gruszka 已提交
1629
	if (il->tx_power_user_lmt == power) {
1630 1631
		D_POWER("Requested Tx power same as current " "limit: %ddBm.\n",
			power);
Z
Zhu Yi 已提交
1632 1633 1634
		return 0;
	}

1635
	D_POWER("Setting upper limit clamp to %ddBm.\n", power);
S
Stanislaw Gruszka 已提交
1636
	il->tx_power_user_lmt = power;
Z
Zhu Yi 已提交
1637 1638 1639

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

S
Stanislaw Gruszka 已提交
1640 1641
	for (i = 0; i < il->channel_count; i++) {
		ch_info = &il->channel_info[i];
S
Stanislaw Gruszka 已提交
1642
		a_band = il_is_channel_a_band(ch_info);
Z
Zhu Yi 已提交
1643 1644 1645

		/* find minimum power of all user and regulatory constraints
		 *    (does not consider h/w clipping limitations) */
S
Stanislaw Gruszka 已提交
1646
		max_power = il3945_hw_reg_get_ch_txpower_limit(ch_info);
Z
Zhu Yi 已提交
1647 1648 1649 1650 1651
		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 已提交
1652
			il3945_hw_reg_set_new_power(il, ch_info);
Z
Zhu Yi 已提交
1653 1654 1655 1656 1657
		}
	}

	/* update txpower settings for all channels,
	 *   send to NIC if associated. */
S
Stanislaw Gruszka 已提交
1658 1659
	il3945_is_temp_calib_needed(il);
	il3945_hw_reg_comp_txpower_temp(il);
Z
Zhu Yi 已提交
1660 1661 1662 1663

	return 0;
}

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

1679 1680 1681 1682
	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) {
1683
		D_INFO("Using current RXON_ASSOC.  Not resending.\n");
1684 1685 1686
		return 0;
	}

1687 1688 1689 1690
	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;
1691 1692
	rxon_assoc.reserved = 0;

S
Stanislaw Gruszka 已提交
1693
	rc = il_send_cmd_sync(il, &cmd);
1694 1695 1696
	if (rc)
		return rc;

1697
	pkt = (struct il_rx_pkt *)cmd.reply_page;
S
Stanislaw Gruszka 已提交
1698
	if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
1699
		IL_ERR("Bad return from C_RXON_ASSOC command\n");
1700 1701 1702
		rc = -EIO;
	}

S
Stanislaw Gruszka 已提交
1703
	il_free_pages(il, cmd.reply_page);
1704 1705 1706 1707

	return rc;
}

A
Abhijeet Kolekar 已提交
1708
/**
S
Stanislaw Gruszka 已提交
1709
 * il3945_commit_rxon - commit staging_rxon to hardware
A
Abhijeet Kolekar 已提交
1710 1711 1712 1713 1714 1715
 *
 * 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.
 */
1716 1717
int
il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx)
A
Abhijeet Kolekar 已提交
1718 1719
{
	/* cast away the const for active_rxon in this function */
S
Stanislaw Gruszka 已提交
1720 1721
	struct il3945_rxon_cmd *active_rxon = (void *)&ctx->active;
	struct il3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
A
Abhijeet Kolekar 已提交
1722
	int rc = 0;
1723
	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
A
Abhijeet Kolekar 已提交
1724

S
Stanislaw Gruszka 已提交
1725
	if (test_bit(S_EXIT_PENDING, &il->status))
1726 1727
		return -EINVAL;

S
Stanislaw Gruszka 已提交
1728
	if (!il_is_alive(il))
A
Abhijeet Kolekar 已提交
1729 1730 1731 1732 1733 1734
		return -1;

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

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

S
Stanislaw Gruszka 已提交
1738
	rc = il_check_rxon_cmd(il, ctx);
A
Abhijeet Kolekar 已提交
1739
	if (rc) {
1740
		IL_ERR("Invalid RXON configuration.  Not committing.\n");
A
Abhijeet Kolekar 已提交
1741 1742 1743 1744
		return -EINVAL;
	}

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

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

		/* 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;
1785
			IL_ERR("Error clearing ASSOC_MSK on current "
1786
			       "configuration (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1787 1788
			return rc;
		}
1789 1790
		il_clear_ucode_stations(il, &il->ctx);
		il_restore_stations(il, &il->ctx);
A
Abhijeet Kolekar 已提交
1791 1792
	}

1793 1794 1795
	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 已提交
1796 1797 1798 1799 1800 1801 1802 1803

	/*
	 * 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 已提交
1804
	il_set_rxon_hwcrypto(il, ctx, !il3945_mod_params.sw_crypto);
A
Abhijeet Kolekar 已提交
1805 1806

	/* Apply the new configuration */
1807 1808
	rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd),
			     staging_rxon);
A
Abhijeet Kolekar 已提交
1809
	if (rc) {
1810
		IL_ERR("Error setting new configuration (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1811 1812 1813 1814 1815
		return rc;
	}

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

1816
	if (!new_assoc) {
1817 1818
		il_clear_ucode_stations(il, &il->ctx);
		il_restore_stations(il, &il->ctx);
1819
	}
A
Abhijeet Kolekar 已提交
1820 1821 1822

	/* 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 已提交
1823
	rc = il_set_tx_power(il, il->tx_power_next, true);
A
Abhijeet Kolekar 已提交
1824
	if (rc) {
1825
		IL_ERR("Error setting Tx power (%d).\n", rc);
A
Abhijeet Kolekar 已提交
1826 1827 1828 1829
		return rc;
	}

	/* Init the hardware's rate fallback order based on the band */
S
Stanislaw Gruszka 已提交
1830
	rc = il3945_init_hw_rate_table(il);
A
Abhijeet Kolekar 已提交
1831
	if (rc) {
1832
		IL_ERR("Error setting HW rate table: %02X\n", rc);
A
Abhijeet Kolekar 已提交
1833 1834 1835 1836 1837 1838
		return -EIO;
	}

	return 0;
}

Z
Zhu Yi 已提交
1839
/**
S
Stanislaw Gruszka 已提交
1840
 * il3945_reg_txpower_periodic -  called when time to check our temperature.
Z
Zhu Yi 已提交
1841 1842 1843 1844 1845 1846 1847 1848
 *
 * -- 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. */
1849 1850
void
il3945_reg_txpower_periodic(struct il_priv *il)
Z
Zhu Yi 已提交
1851 1852
{
	/* This will kick in the "brute force"
S
Stanislaw Gruszka 已提交
1853
	 * il3945_hw_reg_comp_txpower_temp() below */
S
Stanislaw Gruszka 已提交
1854
	if (!il3945_is_temp_calib_needed(il))
Z
Zhu Yi 已提交
1855 1856 1857 1858 1859
		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 已提交
1860
	il3945_hw_reg_comp_txpower_temp(il);
Z
Zhu Yi 已提交
1861

1862 1863 1864
reschedule:
	queue_delayed_work(il->workqueue, &il->_3945.thermal_periodic,
			   REG_RECALIB_PERIOD * HZ);
Z
Zhu Yi 已提交
1865 1866
}

1867 1868
static void
il3945_bg_reg_txpower_periodic(struct work_struct *work)
Z
Zhu Yi 已提交
1869
{
S
Stanislaw Gruszka 已提交
1870
	struct il_priv *il = container_of(work, struct il_priv,
1871
					  _3945.thermal_periodic.work);
Z
Zhu Yi 已提交
1872

S
Stanislaw Gruszka 已提交
1873
	mutex_lock(&il->mutex);
1874 1875 1876
	if (test_bit(S_EXIT_PENDING, &il->status) || il->txq == NULL)
		goto out;

S
Stanislaw Gruszka 已提交
1877
	il3945_reg_txpower_periodic(il);
1878
out:
S
Stanislaw Gruszka 已提交
1879
	mutex_unlock(&il->mutex);
Z
Zhu Yi 已提交
1880 1881 1882
}

/**
S
Stanislaw Gruszka 已提交
1883
 * il3945_hw_reg_get_ch_grp_idx - find the channel-group idx (0-4) for channel.
Z
Zhu Yi 已提交
1884 1885 1886 1887 1888 1889 1890 1891
 *
 * 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.
 */
1892 1893 1894
static u16
il3945_hw_reg_get_ch_grp_idx(struct il_priv *il,
			     const struct il_channel_info *ch_info)
Z
Zhu Yi 已提交
1895
{
S
Stanislaw Gruszka 已提交
1896
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1897
	struct il3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
Z
Zhu Yi 已提交
1898
	u8 group;
S
Stanislaw Gruszka 已提交
1899
	u16 group_idx = 0;	/* based on factory calib frequencies */
Z
Zhu Yi 已提交
1900 1901
	u8 grp_channel;

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

1917
	D_POWER("Chnl %d mapped to grp %d\n", ch_info->channel, group_idx);
S
Stanislaw Gruszka 已提交
1918
	return group_idx;
Z
Zhu Yi 已提交
1919 1920 1921
}

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

S
Stanislaw Gruszka 已提交
1941
	chnl_grp = &eeprom->groups[setting_idx];
Z
Zhu Yi 已提交
1942 1943 1944
	samples = chnl_grp->samples;
	for (i = 0; i < 5; i++) {
		if (power == samples[i].power) {
S
Stanislaw Gruszka 已提交
1945
			*new_idx = samples[i].gain_idx;
Z
Zhu Yi 已提交
1946 1947 1948 1949 1950
			return 0;
		}
	}

	if (power > samples[1].power) {
S
Stanislaw Gruszka 已提交
1951 1952
		idx0 = 0;
		idx1 = 1;
Z
Zhu Yi 已提交
1953
	} else if (power > samples[2].power) {
S
Stanislaw Gruszka 已提交
1954 1955
		idx0 = 1;
		idx1 = 2;
Z
Zhu Yi 已提交
1956
	} else if (power > samples[3].power) {
S
Stanislaw Gruszka 已提交
1957 1958
		idx0 = 2;
		idx1 = 3;
Z
Zhu Yi 已提交
1959
	} else {
S
Stanislaw Gruszka 已提交
1960 1961
		idx0 = 3;
		idx1 = 4;
Z
Zhu Yi 已提交
1962 1963
	}

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

1977 1978
static void
il3945_hw_reg_init_channel_groups(struct il_priv *il)
Z
Zhu Yi 已提交
1979 1980
{
	u32 i;
S
Stanislaw Gruszka 已提交
1981
	s32 rate_idx;
S
Stanislaw Gruszka 已提交
1982
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
1983
	const struct il3945_eeprom_txpower_group *group;
Z
Zhu Yi 已提交
1984

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

S
Stanislaw Gruszka 已提交
1987
	for (i = 0; i < IL_NUM_TX_CALIB_GROUPS; i++) {
Z
Zhu Yi 已提交
1988 1989
		s8 *clip_pwrs;	/* table of power levels for each rate */
		s8 satur_pwr;	/* saturation power for each chnl group */
1990
		group = &eeprom->groups[i];
Z
Zhu Yi 已提交
1991 1992 1993

		/* sanity check on factory saturation power value */
		if (group->saturation_power < 40) {
1994
			IL_WARN("Error: saturation power is %d, "
1995 1996
				"less than minimum expected 40\n",
				group->saturation_power);
Z
Zhu Yi 已提交
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
			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 已提交
2009
		clip_pwrs = (s8 *) il->_3945.clip_groups[i].clip_powers;
Z
Zhu Yi 已提交
2010 2011 2012 2013 2014

		/* 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 */
2015 2016
		for (rate_idx = 0; rate_idx < RATE_COUNT_3945;
		     rate_idx++, clip_pwrs++) {
S
Stanislaw Gruszka 已提交
2017
			switch (rate_idx) {
S
Stanislaw Gruszka 已提交
2018
			case RATE_36M_IDX_TBL:
Z
Zhu Yi 已提交
2019 2020 2021 2022 2023
				if (i == 0)	/* B/G */
					*clip_pwrs = satur_pwr;
				else	/* A */
					*clip_pwrs = satur_pwr - 5;
				break;
S
Stanislaw Gruszka 已提交
2024
			case RATE_48M_IDX_TBL:
Z
Zhu Yi 已提交
2025 2026 2027 2028 2029
				if (i == 0)
					*clip_pwrs = satur_pwr - 7;
				else
					*clip_pwrs = satur_pwr - 10;
				break;
S
Stanislaw Gruszka 已提交
2030
			case RATE_54M_IDX_TBL:
Z
Zhu Yi 已提交
2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044
				if (i == 0)
					*clip_pwrs = satur_pwr - 9;
				else
					*clip_pwrs = satur_pwr - 12;
				break;
			default:
				*clip_pwrs = satur_pwr;
				break;
			}
		}
	}
}

/**
S
Stanislaw Gruszka 已提交
2045
 * il3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
Z
Zhu Yi 已提交
2046
 *
S
Stanislaw Gruszka 已提交
2047
 * Second pass (during init) to set up il->channel_info
Z
Zhu Yi 已提交
2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
 *
 * 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.
 */
2059 2060
int
il3945_txpower_set_from_eeprom(struct il_priv *il)
Z
Zhu Yi 已提交
2061
{
S
Stanislaw Gruszka 已提交
2062 2063
	struct il_channel_info *ch_info = NULL;
	struct il3945_channel_power_info *pwr_info;
S
Stanislaw Gruszka 已提交
2064
	struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
S
Stanislaw Gruszka 已提交
2065 2066 2067
	int delta_idx;
	u8 rate_idx;
	u8 scan_tbl_idx;
Z
Zhu Yi 已提交
2068 2069 2070
	const s8 *clip_pwrs;	/* array of power levels for each rate */
	u8 gain, dsp_atten;
	s8 power;
S
Stanislaw Gruszka 已提交
2071
	u8 pwr_idx, base_pwr_idx, a_band;
Z
Zhu Yi 已提交
2072 2073 2074 2075 2076
	u8 i;
	int temperature;

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

S
Stanislaw Gruszka 已提交
2080
	il3945_hw_reg_init_channel_groups(il);
Z
Zhu Yi 已提交
2081 2082

	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
S
Stanislaw Gruszka 已提交
2083
	for (i = 0, ch_info = il->channel_info; i < il->channel_count;
Z
Zhu Yi 已提交
2084
	     i++, ch_info++) {
S
Stanislaw Gruszka 已提交
2085 2086
		a_band = il_is_channel_a_band(ch_info);
		if (!il_is_channel_valid(ch_info))
Z
Zhu Yi 已提交
2087 2088
			continue;

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

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

S
Stanislaw Gruszka 已提交
2096
		/* calculate power idx *adjustment* value according to
Z
Zhu Yi 已提交
2097
		 *  diff between current temperature and factory temperature */
2098 2099 2100 2101 2102
		delta_idx =
		    il3945_hw_reg_adjust_power_by_temp(temperature,
						       eeprom->groups[ch_info->
								      group_idx].
						       temperature);
Z
Zhu Yi 已提交
2103

2104 2105
		D_POWER("Delta idx for channel %d: %d [%d]\n", ch_info->channel,
			delta_idx, temperature + IL_TEMP_CONVERT);
Z
Zhu Yi 已提交
2106 2107

		/* set tx power value for all OFDM rates */
2108
		for (rate_idx = 0; rate_idx < IL_OFDM_RATES; rate_idx++) {
2109
			s32 uninitialized_var(power_idx);
Z
Zhu Yi 已提交
2110 2111 2112 2113 2114
			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 已提交
2115
				     clip_pwrs[rate_idx]);
Z
Zhu Yi 已提交
2116

S
Stanislaw Gruszka 已提交
2117
			pwr_info = &ch_info->power_info[rate_idx];
Z
Zhu Yi 已提交
2118 2119

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

			/* temperature compensate */
S
Stanislaw Gruszka 已提交
2132
			power_idx += delta_idx;
Z
Zhu Yi 已提交
2133 2134

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

S
Stanislaw Gruszka 已提交
2137
			/* fill 1 OFDM rate's il3945_channel_power_info struct */
Z
Zhu Yi 已提交
2138
			pwr_info->requested_power = pwr;
S
Stanislaw Gruszka 已提交
2139
			pwr_info->power_table_idx = (u8) power_idx;
Z
Zhu Yi 已提交
2140 2141 2142 2143 2144 2145
			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;
		}

2146
		/* set tx power for CCK rates, based on OFDM 12 Mbit settings */
S
Stanislaw Gruszka 已提交
2147
		pwr_info = &ch_info->power_info[RATE_12M_IDX_TBL];
2148 2149 2150 2151
		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 已提交
2152 2153

		/* stay within table range */
S
Stanislaw Gruszka 已提交
2154 2155 2156
		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 已提交
2157

S
Stanislaw Gruszka 已提交
2158
		/* fill each CCK rate's il3945_channel_power_info structure
Z
Zhu Yi 已提交
2159 2160
		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
		 * NOTE:  CCK rates start at end of OFDM rates! */
2161 2162 2163
		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 已提交
2164
			pwr_info->requested_power = power;
S
Stanislaw Gruszka 已提交
2165 2166
			pwr_info->power_table_idx = pwr_idx;
			pwr_info->base_power_idx = base_pwr_idx;
Z
Zhu Yi 已提交
2167 2168 2169 2170 2171
			pwr_info->tpc.tx_gain = gain;
			pwr_info->tpc.dsp_atten = dsp_atten;
		}

		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
2172 2173 2174 2175 2176
		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 已提交
2177
			il3945_hw_reg_set_scan_power(il, scan_tbl_idx,
2178 2179
						     actual_idx, clip_pwrs,
						     ch_info, a_band);
Z
Zhu Yi 已提交
2180 2181 2182 2183 2184 2185
		}
	}

	return 0;
}

2186 2187
int
il3945_hw_rxq_stop(struct il_priv *il)
Z
Zhu Yi 已提交
2188 2189 2190
{
	int rc;

2191 2192
	il_wr(il, FH39_RCSR_CONFIG(0), 0);
	rc = il_poll_bit(il, FH39_RSSR_STATUS,
2193
			 FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
Z
Zhu Yi 已提交
2194
	if (rc < 0)
2195
		IL_ERR("Can't stop Rx DMA.\n");
Z
Zhu Yi 已提交
2196 2197 2198 2199

	return 0;
}

2200 2201
int
il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
Z
Zhu Yi 已提交
2202 2203 2204
{
	int txq_id = txq->q.id;

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

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

2209 2210
	il_wr(il, FH39_CBCC_CTRL(txq_id), 0);
	il_wr(il, FH39_CBCC_BASE(txq_id), 0);
2211

2212
	il_wr(il, FH39_TCSR_CONFIG(txq_id),
2213 2214 2215 2216 2217
	      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 已提交
2218 2219

	/* fake read to flush all prev. writes */
2220
	_il_rd(il, FH39_TSSR_CBB_BASE);
Z
Zhu Yi 已提交
2221 2222 2223 2224

	return 0;
}

K
Kolekar, Abhijeet 已提交
2225 2226 2227
/*
 * HCMD utils
 */
2228 2229
static u16
il3945_get_hcmd_size(u8 cmd_id, u16 len)
K
Kolekar, Abhijeet 已提交
2230 2231
{
	switch (cmd_id) {
2232
	case C_RXON:
S
Stanislaw Gruszka 已提交
2233
		return sizeof(struct il3945_rxon_cmd);
2234
	case C_POWER_TBL:
S
Stanislaw Gruszka 已提交
2235
		return sizeof(struct il3945_powertable_cmd);
K
Kolekar, Abhijeet 已提交
2236 2237 2238 2239 2240
	default:
		return len;
	}
}

2241 2242
static u16
il3945_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data)
2243
{
S
Stanislaw Gruszka 已提交
2244
	struct il3945_addsta_cmd *addsta = (struct il3945_addsta_cmd *)data;
2245 2246
	addsta->mode = cmd->mode;
	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
S
Stanislaw Gruszka 已提交
2247
	memcpy(&addsta->key, &cmd->key, sizeof(struct il4965_keyinfo));
2248 2249 2250 2251 2252 2253 2254 2255
	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;

2256
	return (u16) sizeof(struct il3945_addsta_cmd);
2257 2258
}

2259 2260
static int
il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r)
2261
{
2262
	struct il_rxon_context *ctx = &il->ctx;
2263 2264 2265 2266 2267
	int ret;
	u8 sta_id;
	unsigned long flags;

	if (sta_id_r)
S
Stanislaw Gruszka 已提交
2268
		*sta_id_r = IL_INVALID_STATION;
2269

S
Stanislaw Gruszka 已提交
2270
	ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
2271
	if (ret) {
2272
		IL_ERR("Unable to add station %pM\n", addr);
2273 2274 2275 2276 2277 2278
		return ret;
	}

	if (sta_id_r)
		*sta_id_r = sta_id;

S
Stanislaw Gruszka 已提交
2279 2280 2281
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].used |= IL_STA_LOCAL;
	spin_unlock_irqrestore(&il->sta_lock, flags);
2282 2283 2284

	return 0;
}
2285 2286 2287 2288

static int
il3945_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
			   bool add)
2289
{
S
Stanislaw Gruszka 已提交
2290
	struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
2291 2292 2293
	int ret;

	if (add) {
2294 2295 2296
		ret =
		    il3945_add_bssid_station(il, vif->bss_conf.bssid,
					     &vif_priv->ibss_bssid_sta_id);
2297 2298 2299
		if (ret)
			return ret;

S
Stanislaw Gruszka 已提交
2300
		il3945_sync_sta(il, vif_priv->ibss_bssid_sta_id,
2301 2302 2303
				(il->band ==
				 IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP :
				RATE_1M_PLCP);
S
Stanislaw Gruszka 已提交
2304
		il3945_rate_scale_init(il->hw, vif_priv->ibss_bssid_sta_id);
2305 2306 2307 2308

		return 0;
	}

S
Stanislaw Gruszka 已提交
2309
	return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
2310
				 vif->bss_conf.bssid);
2311
}
2312

Z
Zhu Yi 已提交
2313
/**
S
Stanislaw Gruszka 已提交
2314
 * il3945_init_hw_rate_table - Initialize the hardware rate fallback table
Z
Zhu Yi 已提交
2315
 */
2316 2317
int
il3945_init_hw_rate_table(struct il_priv *il)
Z
Zhu Yi 已提交
2318
{
S
Stanislaw Gruszka 已提交
2319
	int rc, i, idx, prev_idx;
S
Stanislaw Gruszka 已提交
2320
	struct il3945_rate_scaling_cmd rate_cmd = {
Z
Zhu Yi 已提交
2321 2322
		.reserved = {0, 0, 0},
	};
S
Stanislaw Gruszka 已提交
2323
	struct il3945_rate_scaling_info *table = rate_cmd.table;
Z
Zhu Yi 已提交
2324

S
Stanislaw Gruszka 已提交
2325
	for (i = 0; i < ARRAY_SIZE(il3945_rates); i++) {
S
Stanislaw Gruszka 已提交
2326
		idx = il3945_rates[i].table_rs_idx;
2327

2328
		table[idx].rate_n_flags = cpu_to_le16(il3945_rates[i].plcp);
S
Stanislaw Gruszka 已提交
2329 2330
		table[idx].try_cnt = il->retry_rate;
		prev_idx = il3945_get_prev_ieee_rate(i);
2331
		table[idx].next_rate_idx = il3945_rates[prev_idx].table_rs_idx;
Z
Zhu Yi 已提交
2332 2333
	}

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

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

		/* Don't drop out of OFDM rates */
S
Stanislaw Gruszka 已提交
2347
		table[RATE_6M_IDX_TBL].next_rate_idx =
S
Stanislaw Gruszka 已提交
2348
		    il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
Z
Zhu Yi 已提交
2349 2350
		break;

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

S
Stanislaw Gruszka 已提交
2356
		if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
2357
		    il_is_associated(il)) {
2358

S
Stanislaw Gruszka 已提交
2359
			idx = IL_FIRST_CCK_RATE;
2360
			for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++)
S
Stanislaw Gruszka 已提交
2361
				table[i].next_rate_idx =
2362
				    il3945_rates[idx].table_rs_idx;
2363

S
Stanislaw Gruszka 已提交
2364
			idx = RATE_11M_IDX_TBL;
2365
			/* CCK shouldn't fall back to OFDM... */
S
Stanislaw Gruszka 已提交
2366
			table[idx].next_rate_idx = RATE_5M_IDX_TBL;
2367
		}
Z
Zhu Yi 已提交
2368 2369 2370
		break;

	default:
2371
		WARN_ON(1);
Z
Zhu Yi 已提交
2372 2373 2374 2375 2376
		break;
	}

	/* Update the rate scaling for control frame Tx */
	rate_cmd.table_id = 0;
2377
	rc = il_send_cmd_pdu(il, C_RATE_SCALE, sizeof(rate_cmd), &rate_cmd);
Z
Zhu Yi 已提交
2378 2379 2380 2381 2382
	if (rc)
		return rc;

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

2386
/* Called when initializing driver */
2387 2388
int
il3945_hw_set_hw_params(struct il_priv *il)
Z
Zhu Yi 已提交
2389
{
2390
	memset((void *)&il->hw_params, 0, sizeof(struct il_hw_params));
Z
Zhu Yi 已提交
2391

S
Stanislaw Gruszka 已提交
2392
	il->_3945.shared_virt =
2393 2394
	    dma_alloc_coherent(&il->pci_dev->dev, sizeof(struct il3945_shared),
			       &il->_3945.shared_phys, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
2395
	if (!il->_3945.shared_virt) {
2396
		IL_ERR("failed to allocate pci memory\n");
Z
Zhu Yi 已提交
2397 2398 2399
		return -ENOMEM;
	}

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

S
Stanislaw Gruszka 已提交
2403 2404 2405 2406
	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;
2407
	il->hw_params.max_stations = IL3945_STATION_COUNT;
2408
	il->ctx.bcast_sta_id = IL3945_BROADCAST_ID;
2409

S
Stanislaw Gruszka 已提交
2410
	il->sta_key_max_num = STA_KEY_MAX_NUM;
2411

S
Stanislaw Gruszka 已提交
2412
	il->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
2413 2414
	il->hw_params.max_beacon_itrvl = IL39_MAX_UCODE_BEACON_INTERVAL;
	il->hw_params.beacon_time_tsf_bits = IL3945_EXT_BEACON_TIME_POS;
2415

Z
Zhu Yi 已提交
2416 2417 2418
	return 0;
}

2419 2420 2421
unsigned int
il3945_hw_get_beacon_cmd(struct il_priv *il, struct il3945_frame *frame,
			 u8 rate)
Z
Zhu Yi 已提交
2422
{
S
Stanislaw Gruszka 已提交
2423
	struct il3945_tx_beacon_cmd *tx_beacon_cmd;
Z
Zhu Yi 已提交
2424 2425
	unsigned int frame_size;

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

2429
	tx_beacon_cmd->tx.sta_id = il->ctx.bcast_sta_id;
Z
Zhu Yi 已提交
2430 2431
	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

2432 2433 2434
	frame_size =
	    il3945_fill_beacon_frame(il, tx_beacon_cmd->frame,
				     sizeof(frame->u) - sizeof(*tx_beacon_cmd));
Z
Zhu Yi 已提交
2435 2436

	BUG_ON(frame_size > MAX_MPDU_SIZE);
2437
	tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
Z
Zhu Yi 已提交
2438 2439

	tx_beacon_cmd->tx.rate = rate;
2440 2441
	tx_beacon_cmd->tx.tx_flags =
	    (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
Z
Zhu Yi 已提交
2442

2443
	/* supp_rates[0] == OFDM start at IL_FIRST_OFDM_RATE */
2444
	tx_beacon_cmd->tx.supp_rates[0] =
2445
	    (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
2446

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

S
Stanislaw Gruszka 已提交
2449
	return sizeof(struct il3945_tx_beacon_cmd) + frame_size;
Z
Zhu Yi 已提交
2450 2451
}

2452 2453
void
il3945_hw_handler_setup(struct il_priv *il)
Z
Zhu Yi 已提交
2454
{
S
Stanislaw Gruszka 已提交
2455 2456
	il->handlers[C_TX] = il3945_hdl_tx;
	il->handlers[N_3945_RX] = il3945_hdl_rx;
Z
Zhu Yi 已提交
2457 2458
}

2459 2460
void
il3945_hw_setup_deferred_work(struct il_priv *il)
Z
Zhu Yi 已提交
2461
{
S
Stanislaw Gruszka 已提交
2462
	INIT_DELAYED_WORK(&il->_3945.thermal_periodic,
S
Stanislaw Gruszka 已提交
2463
			  il3945_bg_reg_txpower_periodic);
Z
Zhu Yi 已提交
2464 2465
}

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

K
Kolekar, Abhijeet 已提交
2472
/* check contents of special bootstrap uCode SRAM */
2473 2474 2475
static int
il3945_verify_bsm(struct il_priv *il)
{
S
Stanislaw Gruszka 已提交
2476 2477
	__le32 *image = il->ucode_boot.v_addr;
	u32 len = il->ucode_boot.len;
K
Kolekar, Abhijeet 已提交
2478 2479 2480
	u32 reg;
	u32 val;

2481
	D_INFO("Begin verify bsm\n");
K
Kolekar, Abhijeet 已提交
2482 2483

	/* verify BSM SRAM contents */
2484
	val = il_rd_prph(il, BSM_WR_DWCOUNT_REG);
2485
	for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len;
K
Kolekar, Abhijeet 已提交
2486
	     reg += sizeof(u32), image++) {
2487
		val = il_rd_prph(il, reg);
K
Kolekar, Abhijeet 已提交
2488
		if (val != le32_to_cpu(*image)) {
2489
			IL_ERR("BSM uCode verification failed at "
2490 2491 2492
			       "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 已提交
2493 2494 2495 2496
			return -EIO;
		}
	}

2497
	D_INFO("BSM bootstrap uCode image OK\n");
K
Kolekar, Abhijeet 已提交
2498 2499 2500 2501

	return 0;
}

2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515
/******************************************************************************
 *
 * 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!).
 */
2516 2517
static int
il3945_eeprom_acquire_semaphore(struct il_priv *il)
2518
{
S
Stanislaw Gruszka 已提交
2519
	_il_clear_bit(il, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
2520 2521 2522
	return 0;
}

2523 2524
static void
il3945_eeprom_release_semaphore(struct il_priv *il)
2525 2526 2527 2528
{
	return;
}

K
Kolekar, Abhijeet 已提交
2529
 /**
S
Stanislaw Gruszka 已提交
2530
  * il3945_load_bsm - Load bootstrap instructions
K
Kolekar, Abhijeet 已提交
2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560
  *
  * 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.
  */
2561 2562
static int
il3945_load_bsm(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
2563
{
S
Stanislaw Gruszka 已提交
2564 2565
	__le32 *image = il->ucode_boot.v_addr;
	u32 len = il->ucode_boot.len;
K
Kolekar, Abhijeet 已提交
2566 2567 2568 2569 2570 2571 2572 2573 2574
	dma_addr_t pinst;
	dma_addr_t pdata;
	u32 inst_len;
	u32 data_len;
	int rc;
	int i;
	u32 done;
	u32 reg_offset;

2575
	D_INFO("Begin load bsm\n");
K
Kolekar, Abhijeet 已提交
2576 2577

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

	/* Tell bootstrap uCode where to find the "Initialize" uCode
2582 2583 2584 2585
	 *   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 已提交
2586 2587 2588 2589
	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 已提交
2590

2591 2592 2593 2594
	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 已提交
2595 2596 2597 2598 2599

	/* 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++)
2600
		_il_wr_prph(il, reg_offset, le32_to_cpu(*image));
K
Kolekar, Abhijeet 已提交
2601

S
Stanislaw Gruszka 已提交
2602
	rc = il3945_verify_bsm(il);
M
Mohamed Abbas 已提交
2603
	if (rc)
K
Kolekar, Abhijeet 已提交
2604 2605 2606
		return rc;

	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
2607
	il_wr_prph(il, BSM_WR_MEM_SRC_REG, 0x0);
2608
	il_wr_prph(il, BSM_WR_MEM_DST_REG, IL39_RTC_INST_LOWER_BOUND);
2609
	il_wr_prph(il, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
K
Kolekar, Abhijeet 已提交
2610 2611 2612

	/* Load bootstrap code into instruction SRAM now,
	 *   to prepare to load "initialize" uCode */
2613
	il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
K
Kolekar, Abhijeet 已提交
2614 2615 2616

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

	/* Enable future boot loads whenever power management unit triggers it
	 *   (e.g. when powering back up after power-save shutdown) */
2631
	il_wr_prph(il, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
K
Kolekar, Abhijeet 已提交
2632 2633 2634 2635

	return 0;
}

S
Stanislaw Gruszka 已提交
2636 2637 2638
static struct il_hcmd_ops il3945_hcmd = {
	.rxon_assoc = il3945_send_rxon_assoc,
	.commit_rxon = il3945_commit_rxon,
2639 2640
};

S
Stanislaw Gruszka 已提交
2641 2642 2643 2644 2645 2646
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 已提交
2647
	.apm_ops = {
2648 2649 2650
		    .init = il3945_apm_init,
		    .config = il3945_nic_config,
		    },
2651
	.eeprom_ops = {
2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664
		       .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 已提交
2665
	.is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr,
A
Abhijeet Kolekar 已提交
2666

2667
#ifdef CONFIG_IWLEGACY_DEBUGFS
A
Abhijeet Kolekar 已提交
2668
	.debugfs_ops = {
2669 2670 2671 2672
			.rx_stats_read = il3945_ucode_rx_stats_read,
			.tx_stats_read = il3945_ucode_tx_stats_read,
			.general_stats_read = il3945_ucode_general_stats_read,
			},
2673
#endif
K
Kolekar, Abhijeet 已提交
2674 2675
};

S
Stanislaw Gruszka 已提交
2676 2677 2678 2679
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,
2680 2681
};

S
Stanislaw Gruszka 已提交
2682 2683 2684 2685 2686
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 已提交
2687 2688
};

S
Stanislaw Gruszka 已提交
2689 2690 2691 2692 2693 2694 2695
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 已提交
2696 2697
};

S
Stanislaw Gruszka 已提交
2698
static struct il_base_params il3945_base_params = {
2699 2700
	.eeprom_size = IL3945_EEPROM_IMG_SIZE,
	.num_of_queues = IL39_NUM_QUEUES,
2701 2702 2703
	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
	.set_l0s = false,
	.use_bsm = true,
2704
	.led_compensation = 64,
S
Stanislaw Gruszka 已提交
2705
	.wd_timeout = IL_DEF_WD_TIMEOUT,
T
Tomas Winkler 已提交
2706 2707
};

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

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

S
Stanislaw Gruszka 已提交
2734
DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = {
S
Stanislaw Gruszka 已提交
2735 2736 2737 2738 2739 2740 2741
	{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 已提交
2742 2743
};

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