3945.c 75.4 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
	struct il_queue *q = &txq->q;
296
	struct sk_buff *skb;
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 304 305
		skb = txq->skbs[txq->q.read_ptr];
		ieee80211_tx_status_irqsafe(il->hw, skb);
		txq->skbs[txq->q.read_ptr] = NULL;
306
		il->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->skbs[txq->q.read_ptr]);
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
	/* free SKB */
663 664
	if (txq->skbs) {
		struct sk_buff *skb = txq->skbs[txq->q.read_ptr];
665 666 667 668

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return 0;
}

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

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

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

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

809 810 811 812
	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 已提交
813

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

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

	return 0;
}

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

S
Stanislaw Gruszka 已提交
839
	il3945_hw_txq_ctx_free(il);
Z
Zhu Yi 已提交
840

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

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

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

	return rc;

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

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

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

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

K
Kolekar, Abhijeet 已提交
889 890
	return ret;
}
Z
Zhu Yi 已提交
891

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

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

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

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

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

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

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

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

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

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

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

S
Stanislaw Gruszka 已提交
964
	il3945_set_pwr_vmain(il);
K
Kolekar, Abhijeet 已提交
965

966
	il->ops->lib->apm_ops.config(il);
Z
Zhu Yi 已提交
967 968 969

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

S
Stanislaw Gruszka 已提交
978
	il3945_rx_replenish(il);
Z
Zhu Yi 已提交
979

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

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

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

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

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

	return 0;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* 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 已提交
1144
static struct il3945_tx_power power_gain_table[2][IL_MAX_GAIN_ENTRIES] = {
Z
Zhu Yi 已提交
1145 1146 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
	{
	 {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 已提交
1223 1224
	 {3, 95}		/* 2.4 GHz, lowest power */
	},
Z
Zhu Yi 已提交
1225 1226 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
	{
	 {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 已提交
1303 1304
	 {3, 120}		/* 5.x GHz, lowest power */
	}
Z
Zhu Yi 已提交
1305 1306
};

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

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

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

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

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

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

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

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

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

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

1398
	chan = le16_to_cpu(il->active.channel);
Z
Zhu Yi 已提交
1399

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

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

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

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

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

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

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

}

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

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

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

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

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

	return 0;
}

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

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

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

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

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

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

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

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

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

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

	/* send Txpower command for current channel to ucode */
1616
	return il->ops->lib->send_tx_power(il);
Z
Zhu Yi 已提交
1617 1618
}

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

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

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

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

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

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

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

	return 0;
}

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

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

1685 1686 1687 1688
	rxon_assoc.flags = il->staging.flags;
	rxon_assoc.filter_flags = il->staging.filter_flags;
	rxon_assoc.ofdm_basic_rates = il->staging.ofdm_basic_rates;
	rxon_assoc.cck_basic_rates = il->staging.cck_basic_rates;
1689 1690
	rxon_assoc.reserved = 0;

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

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

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

	return rc;
}

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

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

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

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

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

1736
	rc = il_check_rxon_cmd(il);
A
Abhijeet Kolekar 已提交
1737
	if (rc) {
1738
		IL_ERR("Invalid RXON configuration.  Not committing.\n");
A
Abhijeet Kolekar 已提交
1739 1740 1741 1742
		return -EINVAL;
	}

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

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

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

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

	/*
	 * 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;

1802
	il_set_rxon_hwcrypto(il, !il3945_mod_params.sw_crypto);
A
Abhijeet Kolekar 已提交
1803 1804

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

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

1814
	if (!new_assoc) {
1815 1816
		il_clear_ucode_stations(il);
		il_restore_stations(il);
1817
	}
A
Abhijeet Kolekar 已提交
1818 1819 1820

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

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

	return 0;
}

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

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

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

S
Stanislaw Gruszka 已提交
1871
	if (test_bit(S_EXIT_PENDING, &il->status))
Z
Zhu Yi 已提交
1872 1873
		return;

S
Stanislaw Gruszka 已提交
1874 1875 1876
	mutex_lock(&il->mutex);
	il3945_reg_txpower_periodic(il);
	mutex_unlock(&il->mutex);
Z
Zhu Yi 已提交
1877 1878 1879
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

S
Stanislaw Gruszka 已提交
2077
	il3945_hw_reg_init_channel_groups(il);
Z
Zhu Yi 已提交
2078 2079

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

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

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

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

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

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

S
Stanislaw Gruszka 已提交
2114
			pwr_info = &ch_info->power_info[rate_idx];
Z
Zhu Yi 已提交
2115 2116

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

			/* temperature compensate */
S
Stanislaw Gruszka 已提交
2129
			power_idx += delta_idx;
Z
Zhu Yi 已提交
2130 2131

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

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

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

		/* stay within table range */
S
Stanislaw Gruszka 已提交
2151 2152 2153
		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 已提交
2154

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

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

	return 0;
}

2183 2184
int
il3945_hw_rxq_stop(struct il_priv *il)
Z
Zhu Yi 已提交
2185 2186 2187
{
	int rc;

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

	return 0;
}

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

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

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

2206 2207
	il_wr(il, FH39_CBCC_CTRL(txq_id), 0);
	il_wr(il, FH39_CBCC_BASE(txq_id), 0);
2208

2209
	il_wr(il, FH39_TCSR_CONFIG(txq_id),
2210 2211 2212 2213 2214
	      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 已提交
2215 2216

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

	return 0;
}

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

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

2253
	return (u16) sizeof(struct il3945_addsta_cmd);
2254 2255
}

2256 2257
static int
il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r)
2258 2259 2260 2261 2262 2263
{
	int ret;
	u8 sta_id;
	unsigned long flags;

	if (sta_id_r)
S
Stanislaw Gruszka 已提交
2264
		*sta_id_r = IL_INVALID_STATION;
2265

2266
	ret = il_add_station_common(il, addr, 0, NULL, &sta_id);
2267
	if (ret) {
2268
		IL_ERR("Unable to add station %pM\n", addr);
2269 2270 2271 2272 2273 2274
		return ret;
	}

	if (sta_id_r)
		*sta_id_r = sta_id;

S
Stanislaw Gruszka 已提交
2275 2276 2277
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].used |= IL_STA_LOCAL;
	spin_unlock_irqrestore(&il->sta_lock, flags);
2278 2279 2280

	return 0;
}
2281 2282 2283 2284

static int
il3945_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
			   bool add)
2285
{
S
Stanislaw Gruszka 已提交
2286
	struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
2287 2288 2289
	int ret;

	if (add) {
2290 2291 2292
		ret =
		    il3945_add_bssid_station(il, vif->bss_conf.bssid,
					     &vif_priv->ibss_bssid_sta_id);
2293 2294 2295
		if (ret)
			return ret;

S
Stanislaw Gruszka 已提交
2296
		il3945_sync_sta(il, vif_priv->ibss_bssid_sta_id,
2297 2298 2299
				(il->band ==
				 IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP :
				RATE_1M_PLCP);
S
Stanislaw Gruszka 已提交
2300
		il3945_rate_scale_init(il->hw, vif_priv->ibss_bssid_sta_id);
2301 2302 2303 2304

		return 0;
	}

S
Stanislaw Gruszka 已提交
2305
	return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
2306
				 vif->bss_conf.bssid);
2307
}
2308

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

S
Stanislaw Gruszka 已提交
2321
	for (i = 0; i < ARRAY_SIZE(il3945_rates); i++) {
S
Stanislaw Gruszka 已提交
2322
		idx = il3945_rates[i].table_rs_idx;
2323

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

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

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

		/* Don't drop out of OFDM rates */
S
Stanislaw Gruszka 已提交
2343
		table[RATE_6M_IDX_TBL].next_rate_idx =
S
Stanislaw Gruszka 已提交
2344
		    il3945_rates[IL_FIRST_OFDM_RATE].table_rs_idx;
Z
Zhu Yi 已提交
2345 2346
		break;

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

S
Stanislaw Gruszka 已提交
2352
		if (!(il->_3945.sta_supp_rates & IL_OFDM_RATES_MASK) &&
2353
		    il_is_associated(il)) {
2354

S
Stanislaw Gruszka 已提交
2355
			idx = IL_FIRST_CCK_RATE;
2356
			for (i = RATE_6M_IDX_TBL; i <= RATE_54M_IDX_TBL; i++)
S
Stanislaw Gruszka 已提交
2357
				table[i].next_rate_idx =
2358
				    il3945_rates[idx].table_rs_idx;
2359

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

	default:
2367
		WARN_ON(1);
Z
Zhu Yi 已提交
2368 2369 2370 2371 2372
		break;
	}

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

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

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

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

2396 2397
	il->hw_params.bcast_id = IL3945_BROADCAST_ID;

2398
	/* Assign number of Usable TX queues */
2399
	il->hw_params.max_txq_num = il->cfg->num_of_queues;
2400

S
Stanislaw Gruszka 已提交
2401 2402 2403 2404
	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;
2405
	il->hw_params.max_stations = IL3945_STATION_COUNT;
2406

S
Stanislaw Gruszka 已提交
2407
	il->sta_key_max_num = STA_KEY_MAX_NUM;
2408

S
Stanislaw Gruszka 已提交
2409
	il->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
2410 2411
	il->hw_params.max_beacon_itrvl = IL39_MAX_UCODE_BEACON_INTERVAL;
	il->hw_params.beacon_time_tsf_bits = IL3945_EXT_BEACON_TIME_POS;
2412

Z
Zhu Yi 已提交
2413 2414 2415
	return 0;
}

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

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

2426
	tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id;
Z
Zhu Yi 已提交
2427 2428
	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

2429 2430 2431
	frame_size =
	    il3945_fill_beacon_frame(il, tx_beacon_cmd->frame,
				     sizeof(frame->u) - sizeof(*tx_beacon_cmd));
Z
Zhu Yi 已提交
2432 2433

	BUG_ON(frame_size > MAX_MPDU_SIZE);
2434
	tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
Z
Zhu Yi 已提交
2435 2436

	tx_beacon_cmd->tx.rate = rate;
2437 2438
	tx_beacon_cmd->tx.tx_flags =
	    (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
Z
Zhu Yi 已提交
2439

2440
	/* supp_rates[0] == OFDM start at IL_FIRST_OFDM_RATE */
2441
	tx_beacon_cmd->tx.supp_rates[0] =
2442
	    (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF;
2443

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

S
Stanislaw Gruszka 已提交
2446
	return sizeof(struct il3945_tx_beacon_cmd) + frame_size;
Z
Zhu Yi 已提交
2447 2448
}

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

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

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

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

2478
	D_INFO("Begin verify bsm\n");
K
Kolekar, Abhijeet 已提交
2479 2480

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

2494
	D_INFO("BSM bootstrap uCode image OK\n");
K
Kolekar, Abhijeet 已提交
2495 2496 2497 2498

	return 0;
}

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

2520 2521
static void
il3945_eeprom_release_semaphore(struct il_priv *il)
2522 2523 2524 2525
{
	return;
}

K
Kolekar, Abhijeet 已提交
2526
 /**
S
Stanislaw Gruszka 已提交
2527
  * il3945_load_bsm - Load bootstrap instructions
K
Kolekar, Abhijeet 已提交
2528 2529 2530 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
  *
  * 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.
  */
2558 2559
static int
il3945_load_bsm(struct il_priv *il)
K
Kolekar, Abhijeet 已提交
2560
{
S
Stanislaw Gruszka 已提交
2561 2562
	__le32 *image = il->ucode_boot.v_addr;
	u32 len = il->ucode_boot.len;
K
Kolekar, Abhijeet 已提交
2563 2564 2565 2566 2567 2568 2569 2570 2571
	dma_addr_t pinst;
	dma_addr_t pdata;
	u32 inst_len;
	u32 data_len;
	int rc;
	int i;
	u32 done;
	u32 reg_offset;

2572
	D_INFO("Begin load bsm\n");
K
Kolekar, Abhijeet 已提交
2573 2574

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

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

2588 2589 2590 2591
	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 已提交
2592 2593 2594 2595 2596

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

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

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

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

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

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

	return 0;
}

S
Stanislaw Gruszka 已提交
2633 2634 2635
static struct il_hcmd_ops il3945_hcmd = {
	.rxon_assoc = il3945_send_rxon_assoc,
	.commit_rxon = il3945_commit_rxon,
2636 2637
};

S
Stanislaw Gruszka 已提交
2638 2639 2640 2641 2642 2643
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 已提交
2644
	.apm_ops = {
2645 2646 2647 2648
		    .init = il3945_apm_init,
		    .config = il3945_nic_config,
		    },
	.send_tx_power = il3945_send_tx_power,
S
Stanislaw Gruszka 已提交
2649
	.is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr,
2650 2651
	.eeprom_acquire_semaphore = il3945_eeprom_acquire_semaphore,
	.eeprom_release_semaphore = il3945_eeprom_release_semaphore,
K
Kolekar, Abhijeet 已提交
2652 2653
};

S
Stanislaw Gruszka 已提交
2654 2655 2656 2657
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,
2658 2659
};

S
Stanislaw Gruszka 已提交
2660 2661 2662 2663 2664
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 已提交
2665 2666
};

2667
const struct il_ops il3945_ops = {
S
Stanislaw Gruszka 已提交
2668 2669 2670 2671 2672
	.lib = &il3945_lib,
	.hcmd = &il3945_hcmd,
	.utils = &il3945_hcmd_utils,
	.led = &il3945_led_ops,
	.legacy = &il3945_legacy_ops,
K
Kolekar, Abhijeet 已提交
2673 2674
};

S
Stanislaw Gruszka 已提交
2675
static struct il_cfg il3945_bg_cfg = {
2676
	.name = "3945BG",
2677 2678 2679
	.fw_name_pre = IL3945_FW_PRE,
	.ucode_api_max = IL3945_UCODE_API_MAX,
	.ucode_api_min = IL3945_UCODE_API_MIN,
S
Stanislaw Gruszka 已提交
2680
	.sku = IL_SKU_G,
2681
	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
S
Stanislaw Gruszka 已提交
2682 2683
	.mod_params = &il3945_mod_params,
	.led_mode = IL_LED_BLINK,
2684 2685 2686 2687 2688 2689 2690

	.eeprom_size = IL3945_EEPROM_IMG_SIZE,
	.num_of_queues = IL39_NUM_QUEUES,
	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
	.set_l0s = false,
	.use_bsm = true,
	.led_compensation = 64,
2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701
	.wd_timeout = IL_DEF_WD_TIMEOUT,

	.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,
	},
2702 2703
};

S
Stanislaw Gruszka 已提交
2704
static struct il_cfg il3945_abg_cfg = {
T
Tomas Winkler 已提交
2705
	.name = "3945ABG",
2706 2707 2708
	.fw_name_pre = IL3945_FW_PRE,
	.ucode_api_max = IL3945_UCODE_API_MAX,
	.ucode_api_min = IL3945_UCODE_API_MIN,
2709
	.sku = IL_SKU_A | IL_SKU_G,
2710
	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
S
Stanislaw Gruszka 已提交
2711 2712
	.mod_params = &il3945_mod_params,
	.led_mode = IL_LED_BLINK,
2713 2714 2715 2716 2717 2718 2719

	.eeprom_size = IL3945_EEPROM_IMG_SIZE,
	.num_of_queues = IL39_NUM_QUEUES,
	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
	.set_l0s = false,
	.use_bsm = true,
	.led_compensation = 64,
2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730
	.wd_timeout = IL_DEF_WD_TIMEOUT,

	.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,
	},
T
Tomas Winkler 已提交
2731 2732
};

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

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