iwl-5000.c 50.0 KB
Newer Older
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 *
 * 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:
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>

#include "iwl-eeprom.h"
40
#include "iwl-dev.h"
41 42
#include "iwl-core.h"
#include "iwl-io.h"
43
#include "iwl-sta.h"
44
#include "iwl-helpers.h"
J
Johannes Berg 已提交
45
#include "iwl-agn-led.h"
46
#include "iwl-5000-hw.h"
47
#include "iwl-6000-hw.h"
48

49
/* Highest firmware API version supported */
50
#define IWL5000_UCODE_API_MAX 2
51
#define IWL5150_UCODE_API_MAX 2
52

53 54 55 56 57 58 59 60 61 62 63
/* Lowest firmware API version supported */
#define IWL5000_UCODE_API_MIN 1
#define IWL5150_UCODE_API_MIN 1

#define IWL5000_FW_PRE "iwlwifi-5000-"
#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)

#define IWL5150_FW_PRE "iwlwifi-5150-"
#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
64

65 66 67 68 69 70 71 72 73 74
static const u16 iwl5000_default_queue_to_tx_fifo[] = {
	IWL_TX_FIFO_AC3,
	IWL_TX_FIFO_AC2,
	IWL_TX_FIFO_AC1,
	IWL_TX_FIFO_AC0,
	IWL50_CMD_FIFO_NUM,
	IWL_TX_FIFO_HCCA_1,
	IWL_TX_FIFO_HCCA_2
};

75
/* NIC configuration for 5000 series */
76
void iwl5000_nic_config(struct iwl_priv *priv)
77 78 79 80 81 82 83 84 85
{
	unsigned long flags;
	u16 radio_cfg;

	spin_lock_irqsave(&priv->lock, flags);

	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);

	/* write radio config values to register */
86
	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
87 88 89 90 91 92 93 94 95 96
		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));

	/* set CSR_HW_CONFIG_REG for uCode use */
	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);

T
Tomas Winkler 已提交
97 98 99 100
	/* W/A : NIC is stuck in a reset state after Early PCIe power off
	 * (PCIe power is lost before PERST# is asserted),
	 * causing ME FW to lose ownership and not being able to obtain it back.
	 */
101
	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
T
Tomas Winkler 已提交
102 103 104
				APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
				~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);

W
Wey-Yi Guy 已提交
105

106 107 108 109
	spin_unlock_irqrestore(&priv->lock, flags);
}


110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/*
 * EEPROM
 */
static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
{
	u16 offset = 0;

	if ((address & INDIRECT_ADDRESS) == 0)
		return address;

	switch (address & INDIRECT_TYPE_MSK) {
	case INDIRECT_HOST:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST);
		break;
	case INDIRECT_GENERAL:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL);
		break;
	case INDIRECT_REGULATORY:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY);
		break;
	case INDIRECT_CALIBRATION:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION);
		break;
	case INDIRECT_PROCESS_ADJST:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST);
		break;
	case INDIRECT_OTHERS:
		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
		break;
	default:
140
		IWL_ERR(priv, "illegal indirect type: 0x%X\n",
141 142 143 144 145 146 147 148
		address & INDIRECT_TYPE_MSK);
		break;
	}

	/* translate the offset from words to byte */
	return (address & ADDRESS_MSK) + (offset << 1);
}

149
u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
150 151 152 153 154 155 156 157 158
{
	struct iwl_eeprom_calib_hdr {
		u8 version;
		u8 pa_type;
		u16 voltage;
	} *hdr;

	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
							EEPROM_5000_CALIB_ALL);
159
	return hdr->version;
160 161 162

}

163 164 165
static void iwl5000_gain_computation(struct iwl_priv *priv,
		u32 average_noise[NUM_RX_CHAINS],
		u16 min_average_noise_antenna_i,
166 167
		u32 min_average_noise,
		u8 default_chain)
168 169 170 171 172
{
	int i;
	s32 delta_g;
	struct iwl_chain_noise_data *data = &priv->chain_noise_data;

173 174 175 176
	/*
	 * Find Gain Code for the chains based on "default chain"
	 */
	for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
177 178 179 180
		if ((data->disconn_array[i])) {
			data->delta_gain_code[i] = 0;
			continue;
		}
181
		delta_g = (1000 * ((s32)average_noise[default_chain] -
182 183 184
			(s32)average_noise[i])) / 1500;
		/* bound gain by 2 bits value max, 3rd bit is sign */
		data->delta_gain_code[i] =
185
			min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
186 187 188 189 190 191

		if (delta_g < 0)
			/* set negative sign */
			data->delta_gain_code[i] |= (1 << 2);
	}

192
	IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d  ANT_C = %d\n",
193 194 195
			data->delta_gain_code[1], data->delta_gain_code[2]);

	if (!data->radio_write) {
196
		struct iwl_calib_chain_noise_gain_cmd cmd;
197

198 199
		memset(&cmd, 0, sizeof(cmd));

200 201 202 203
		cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
		cmd.hdr.first_group = 0;
		cmd.hdr.groups_num = 1;
		cmd.hdr.data_valid = 1;
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
		cmd.delta_gain_1 = data->delta_gain_code[1];
		cmd.delta_gain_2 = data->delta_gain_code[2];
		iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
			sizeof(cmd), &cmd, NULL);

		data->radio_write = 1;
		data->state = IWL_CHAIN_NOISE_CALIBRATED;
	}

	data->chain_noise_a = 0;
	data->chain_noise_b = 0;
	data->chain_noise_c = 0;
	data->chain_signal_a = 0;
	data->chain_signal_b = 0;
	data->chain_signal_c = 0;
	data->beacon_count = 0;
}

static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
{
	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
225
	int ret;
226 227

	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
228
		struct iwl_calib_chain_noise_reset_cmd cmd;
229
		memset(&cmd, 0, sizeof(cmd));
230 231 232 233 234 235 236 237

		cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
		cmd.hdr.first_group = 0;
		cmd.hdr.groups_num = 1;
		cmd.hdr.data_valid = 1;
		ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
					sizeof(cmd), &cmd);
		if (ret)
238 239
			IWL_ERR(priv,
				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
240
		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
241
		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
242 243 244
	}
}

245
void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
246 247
			__le32 *tx_flags)
{
248 249
	if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
	    (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
250 251 252 253 254
		*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
	else
		*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
}

255 256
static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
	.min_nrg_cck = 95,
257
	.max_nrg_cck = 0, /* not used, set to 0 */
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
	.auto_corr_min_ofdm = 90,
	.auto_corr_min_ofdm_mrc = 170,
	.auto_corr_min_ofdm_x1 = 120,
	.auto_corr_min_ofdm_mrc_x1 = 240,

	.auto_corr_max_ofdm = 120,
	.auto_corr_max_ofdm_mrc = 210,
	.auto_corr_max_ofdm_x1 = 155,
	.auto_corr_max_ofdm_mrc_x1 = 290,

	.auto_corr_min_cck = 125,
	.auto_corr_max_cck = 200,
	.auto_corr_min_cck_mrc = 170,
	.auto_corr_max_cck_mrc = 400,
	.nrg_th_cck = 95,
	.nrg_th_ofdm = 95,
274 275 276 277

	.barker_corr_th_min = 190,
	.barker_corr_th_min_mrc = 390,
	.nrg_th_cca = 62,
278 279
};

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
	.min_nrg_cck = 95,
	.max_nrg_cck = 0, /* not used, set to 0 */
	.auto_corr_min_ofdm = 90,
	.auto_corr_min_ofdm_mrc = 170,
	.auto_corr_min_ofdm_x1 = 105,
	.auto_corr_min_ofdm_mrc_x1 = 220,

	.auto_corr_max_ofdm = 120,
	.auto_corr_max_ofdm_mrc = 210,
	/* max = min for performance bug in 5150 DSP */
	.auto_corr_max_ofdm_x1 = 105,
	.auto_corr_max_ofdm_mrc_x1 = 220,

	.auto_corr_min_cck = 125,
	.auto_corr_max_cck = 200,
	.auto_corr_min_cck_mrc = 170,
	.auto_corr_max_cck_mrc = 400,
	.nrg_th_cck = 95,
	.nrg_th_ofdm = 95,
300 301 302 303

	.barker_corr_th_min = 190,
	.barker_corr_th_min_mrc = 390,
	.nrg_th_cca = 62,
304 305
};

306
const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
307 308 309 310 311 312 313
					   size_t offset)
{
	u32 address = eeprom_indirect_address(priv, offset);
	BUG_ON(address >= priv->cfg->eeprom_size);
	return &priv->eeprom[address];
}

314
static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
315
{
316
	const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
317
	s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
318 319 320 321 322 323 324 325
			iwl_temp_calib_to_offset(priv);

	priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
}

static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{
	/* want Celsius */
326
	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
327 328
}

329 330 331
/*
 *  Calibration
 */
332
static int iwl5000_set_Xtal_calib(struct iwl_priv *priv)
333
{
334
	struct iwl_calib_xtal_freq_cmd cmd;
335 336
	u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);

337 338 339 340 341 342
	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
	cmd.hdr.first_group = 0;
	cmd.hdr.groups_num = 1;
	cmd.hdr.data_valid = 1;
	cmd.cap_pin1 = (u8)xtal_calib[0];
	cmd.cap_pin2 = (u8)xtal_calib[1];
343
	return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
344
			     (u8 *)&cmd, sizeof(cmd));
345 346 347 348
}

static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
{
349
	struct iwl_calib_cfg_cmd calib_cfg_cmd;
350 351
	struct iwl_host_cmd cmd = {
		.id = CALIBRATION_CFG_CMD,
352
		.len = sizeof(struct iwl_calib_cfg_cmd),
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
		.data = &calib_cfg_cmd,
	};

	memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
	calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
	calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
	calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;

	return iwl_send_cmd(priv, &cmd);
}

static void iwl5000_rx_calib_result(struct iwl_priv *priv,
			     struct iwl_rx_mem_buffer *rxb)
{
Z
Zhu Yi 已提交
368
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
369
	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
370
	int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
371
	int index;
372 373 374 375

	/* reduce the size of the length field itself */
	len -= 4;

376 377 378
	/* Define the order in which the results will be sent to the runtime
	 * uCode. iwl_send_calib_results sends them in a row according to their
	 * index. We sort them here */
379
	switch (hdr->op_code) {
380 381 382
	case IWL_PHY_CALIBRATE_DC_CMD:
		index = IWL_CALIB_DC;
		break;
383 384
	case IWL_PHY_CALIBRATE_LO_CMD:
		index = IWL_CALIB_LO;
385
		break;
386 387
	case IWL_PHY_CALIBRATE_TX_IQ_CMD:
		index = IWL_CALIB_TX_IQ;
388
		break;
389 390
	case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD:
		index = IWL_CALIB_TX_IQ_PERD;
391
		break;
392 393 394
	case IWL_PHY_CALIBRATE_BASE_BAND_CMD:
		index = IWL_CALIB_BASE_BAND;
		break;
395
	default:
396
		IWL_ERR(priv, "Unknown calibration notification %d\n",
397 398 399
			  hdr->op_code);
		return;
	}
400
	iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
401 402 403 404 405
}

static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
			       struct iwl_rx_mem_buffer *rxb)
{
406
	IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n");
407 408 409
	queue_work(priv->workqueue, &priv->restart);
}

410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
/*
 * ucode
 */
static int iwl5000_load_section(struct iwl_priv *priv,
				struct fw_desc *image,
				u32 dst_addr)
{
	dma_addr_t phy_addr = image->p_addr;
	u32 byte_cnt = image->len;

	iwl_write_direct32(priv,
		FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);

	iwl_write_direct32(priv,
		FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);

	iwl_write_direct32(priv,
		FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
		phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);

	iwl_write_direct32(priv,
432
		FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
T
Tomas Winkler 已提交
433
		(iwl_get_dma_hi_addr(phy_addr)
434 435
			<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);

436 437 438 439 440 441 442 443 444
	iwl_write_direct32(priv,
		FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
		1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
		1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
		FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);

	iwl_write_direct32(priv,
		FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE	|
445
		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|
446 447 448 449 450 451 452 453 454 455 456
		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);

	return 0;
}

static int iwl5000_load_given_ucode(struct iwl_priv *priv,
		struct fw_desc *inst_image,
		struct fw_desc *data_image)
{
	int ret = 0;

457 458
	ret = iwl5000_load_section(priv, inst_image,
				   IWL50_RTC_INST_LOWER_BOUND);
459 460 461
	if (ret)
		return ret;

462
	IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n");
463
	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
464
					priv->ucode_write_complete, 5 * HZ);
465
	if (ret == -ERESTARTSYS) {
466
		IWL_ERR(priv, "Could not load the INST uCode section due "
467 468 469 470
			"to interrupt\n");
		return ret;
	}
	if (!ret) {
471
		IWL_ERR(priv, "Could not load the INST uCode section\n");
472 473 474 475 476 477
		return -ETIMEDOUT;
	}

	priv->ucode_write_complete = 0;

	ret = iwl5000_load_section(
478
		priv, data_image, IWL50_RTC_DATA_LOWER_BOUND);
479 480 481
	if (ret)
		return ret;

482
	IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n");
483 484 485 486

	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
				priv->ucode_write_complete, 5 * HZ);
	if (ret == -ERESTARTSYS) {
487
		IWL_ERR(priv, "Could not load the INST uCode section due "
488 489 490
			"to interrupt\n");
		return ret;
	} else if (!ret) {
491
		IWL_ERR(priv, "Could not load the DATA uCode section\n");
492 493 494 495 496 497 498 499 500
		return -ETIMEDOUT;
	} else
		ret = 0;

	priv->ucode_write_complete = 0;

	return ret;
}

501
int iwl5000_load_ucode(struct iwl_priv *priv)
502 503 504 505 506
{
	int ret = 0;

	/* check whether init ucode should be loaded, or rather runtime ucode */
	if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) {
507
		IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n");
508 509 510
		ret = iwl5000_load_given_ucode(priv,
			&priv->ucode_init, &priv->ucode_init_data);
		if (!ret) {
511
			IWL_DEBUG_INFO(priv, "Init ucode load complete.\n");
512 513 514
			priv->ucode_type = UCODE_INIT;
		}
	} else {
515
		IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. "
516 517 518 519
			"Loading runtime ucode...\n");
		ret = iwl5000_load_given_ucode(priv,
			&priv->ucode_code, &priv->ucode_data);
		if (!ret) {
520
			IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n");
521 522 523 524 525 526 527
			priv->ucode_type = UCODE_RT;
		}
	}

	return ret;
}

528
void iwl5000_init_alive_start(struct iwl_priv *priv)
529 530 531 532 533 534 535
{
	int ret = 0;

	/* Check alive response for "valid" sign from uCode */
	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
		/* We had an error bringing up the hardware, so take it
		 * all the way back down so we can try again */
536
		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
537 538 539 540 541 542 543 544 545
		goto restart;
	}

	/* initialize uCode was loaded... verify inst image.
	 * This is a paranoid check, because we would not have gotten the
	 * "initialize" alive if code weren't properly loaded.  */
	if (iwl_verify_ucode(priv)) {
		/* Runtime instruction load was bad;
		 * take it all the way back down so we can try again */
546
		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
547 548 549
		goto restart;
	}

550
	iwl_clear_stations_table(priv);
551 552
	ret = priv->cfg->ops->lib->alive_notify(priv);
	if (ret) {
553 554
		IWL_WARN(priv,
			"Could not complete ALIVE transition: %d\n", ret);
555 556 557
		goto restart;
	}

558
	iwl5000_send_calib_cfg(priv);
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
	return;

restart:
	/* real restart (first load init_ucode) */
	queue_work(priv->workqueue, &priv->restart);
}

static void iwl5000_set_wr_ptrs(struct iwl_priv *priv,
				int txq_id, u32 index)
{
	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
			(index & 0xff) | (txq_id << 8));
	iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index);
}

static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
					struct iwl_tx_queue *txq,
					int tx_fifo_id, int scd_retry)
{
	int txq_id = txq->q.id;
T
Tomas Winkler 已提交
579
	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
580 581 582 583 584 585 586 587 588

	iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
			(active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
			(tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) |
			(1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) |
			IWL50_SCD_QUEUE_STTS_REG_MSK);

	txq->sched_retry = scd_retry;

589
	IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
590 591 592 593
		       active ? "Activate" : "Deactivate",
		       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}

594 595 596 597 598 599 600 601 602 603
static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
{
	struct iwl_wimax_coex_cmd coex_cmd;

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

	return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
				sizeof(coex_cmd), &coex_cmd);
}

604
int iwl5000_alive_notify(struct iwl_priv *priv)
605 606 607
{
	u32 a;
	unsigned long flags;
608
	int i, chan;
W
Winkler, Tomas 已提交
609
	u32 reg_val;
610 611 612 613 614 615 616 617 618 619 620

	spin_lock_irqsave(&priv->lock, flags);

	priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
	a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
	for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
		a += 4)
		iwl_write_targ_mem(priv, a, 0);
	for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET;
		a += 4)
		iwl_write_targ_mem(priv, a, 0);
621 622
	for (; a < priv->scd_base_addr +
	       IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
623 624 625
		iwl_write_targ_mem(priv, a, 0);

	iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
626
		       priv->scd_bc_tbls.dma >> 10);
627 628 629 630 631 632 633

	/* Enable DMA channel */
	for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++)
		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);

W
Winkler, Tomas 已提交
634 635 636 637 638
	/* Update FH chicken bits */
	reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);

639
	iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
640
		IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
	iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);

	/* initiate the queues */
	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
		iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0);
		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
		iwl_write_targ_mem(priv, priv->scd_base_addr +
				IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
		iwl_write_targ_mem(priv, priv->scd_base_addr +
				IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) +
				sizeof(u32),
				((SCD_WIN_SIZE <<
				IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
				IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
				((SCD_FRAME_LIMIT <<
				IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
				IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
	}

	iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
661
			IWL_MASK(0, priv->hw_params.max_txq_num));
662

663 664
	/* Activate all Tx DMA/FIFO channels */
	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
665 666

	iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
667

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
	/* map qos queues to fifos one-to-one */
	for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
		int ac = iwl5000_default_queue_to_tx_fifo[i];
		iwl_txq_ctx_activate(priv, i);
		iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
	}
	/* TODO - need to initialize those FIFOs inside the loop above,
	 * not only mark them as active */
	iwl_txq_ctx_activate(priv, 4);
	iwl_txq_ctx_activate(priv, 7);
	iwl_txq_ctx_activate(priv, 8);
	iwl_txq_ctx_activate(priv, 9);

	spin_unlock_irqrestore(&priv->lock, flags);

683

684 685
	iwl5000_send_wimax_coex(priv);

686 687
	iwl5000_set_Xtal_calib(priv);
	iwl_send_calib_results(priv);
688

689 690 691
	return 0;
}

692
int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
693
{
694 695 696 697
	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
	    priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES)
		priv->cfg->num_of_queues =
			priv->cfg->mod_params->num_of_queues;
698

699
	priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
700
	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
701
	priv->hw_params.scd_bc_tbls_size =
702 703
			priv->cfg->num_of_queues *
			sizeof(struct iwl5000_scd_bc_tbl);
704
	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
705 706
	priv->hw_params.max_stations = IWL5000_STATION_COUNT;
	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
707

708 709
	priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
	priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE;
710

711
	priv->hw_params.max_bsm_size = 0;
712
	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
713
					BIT(IEEE80211_BAND_5GHZ);
714 715
	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;

716 717 718 719
	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
720

721 722
	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
723

724
	/* Set initial sensitivity parameters */
725 726
	/* Set initial calibration set */
	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
727
	case CSR_HW_REV_TYPE_5150:
728
		priv->hw_params.sens = &iwl5150_sensitivity;
729
		priv->hw_params.calib_init_cfg =
730
			BIT(IWL_CALIB_DC)		|
731
			BIT(IWL_CALIB_LO)		|
732 733
			BIT(IWL_CALIB_TX_IQ) 		|
			BIT(IWL_CALIB_BASE_BAND);
734

735
		break;
736
	default:
737
		priv->hw_params.sens = &iwl5000_sensitivity;
738
		priv->hw_params.calib_init_cfg =
739
			BIT(IWL_CALIB_XTAL)		|
740 741
			BIT(IWL_CALIB_LO)		|
			BIT(IWL_CALIB_TX_IQ) 		|
742
			BIT(IWL_CALIB_TX_IQ_PERD)	|
743
			BIT(IWL_CALIB_BASE_BAND);
744 745 746
		break;
	}

747 748
	return 0;
}
749

750 751 752
/**
 * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
 */
753
void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
754
					    struct iwl_tx_queue *txq,
755 756
					    u16 byte_cnt)
{
757
	struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
758
	int write_ptr = txq->q.write_ptr;
759 760
	int txq_id = txq->q.id;
	u8 sec_ctl = 0;
761 762 763
	u8 sta_id = 0;
	u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
	__le16 bc_ent;
764

765
	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
766 767

	if (txq_id != IWL_CMD_QUEUE_NUM) {
768
		sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
769
		sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
770 771 772 773 774 775 776 777 778 779 780 781 782 783

		switch (sec_ctl & TX_CMD_SEC_MSK) {
		case TX_CMD_SEC_CCM:
			len += CCMP_MIC_LEN;
			break;
		case TX_CMD_SEC_TKIP:
			len += TKIP_ICV_LEN;
			break;
		case TX_CMD_SEC_WEP:
			len += WEP_IV_LEN + WEP_ICV_LEN;
			break;
		}
	}

784
	bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
785

786
	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
787

788
	if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
789
		scd_bc_tbl[txq_id].
790
			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
791 792
}

793
void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
794 795
					   struct iwl_tx_queue *txq)
{
796
	struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
797 798 799 800 801 802
	int txq_id = txq->q.id;
	int read_ptr = txq->q.read_ptr;
	u8 sta_id = 0;
	__le16 bc_ent;

	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
803 804

	if (txq_id != IWL_CMD_QUEUE_NUM)
805
		sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
806

807
	bc_ent =  cpu_to_le16(1 | (sta_id << 12));
808
	scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
809

810
	if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
811
		scd_bc_tbl[txq_id].
812
			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =  bc_ent;
813 814
}

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
					u16 txq_id)
{
	u32 tbl_dw_addr;
	u32 tbl_dw;
	u16 scd_q2ratid;

	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;

	tbl_dw_addr = priv->scd_base_addr +
			IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);

	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);

	if (txq_id & 0x1)
		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
	else
		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);

	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);

	return 0;
}
static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
{
	/* Simply stop the queue, but don't change any configuration;
	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
	iwl_write_prph(priv,
		IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
		(0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
		(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}

848
int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
849 850 851 852 853
				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
{
	unsigned long flags;
	u16 ra_tid;

854
	if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
855 856
	    (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
	     <= txq_id)) {
857 858
		IWL_WARN(priv,
			"queue number out of range: %d, must be %d to %d\n",
859
			txq_id, IWL50_FIRST_AMPDU_QUEUE,
860 861
			IWL50_FIRST_AMPDU_QUEUE +
			priv->cfg->num_of_ampdu_queues - 1);
862 863
		return -EINVAL;
	}
864 865 866 867

	ra_tid = BUILD_RAxTID(sta_id, tid);

	/* Modify device's station table to Tx this TID */
868
	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910

	spin_lock_irqsave(&priv->lock, flags);

	/* Stop this Tx queue before configuring it */
	iwl5000_tx_queue_stop_scheduler(priv, txq_id);

	/* Map receiver-address / traffic-ID to this queue */
	iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id);

	/* Set this queue as a chain-building queue */
	iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id));

	/* enable aggregations for the queue */
	iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id));

	/* Place first TFD at index corresponding to start sequence number.
	 * Assumes that ssn_idx is valid (!= 0xFFF) */
	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
	iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx);

	/* Set up Tx window size and frame limit for this queue */
	iwl_write_targ_mem(priv, priv->scd_base_addr +
			IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
			sizeof(u32),
			((SCD_WIN_SIZE <<
			IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
			IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
			((SCD_FRAME_LIMIT <<
			IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
			IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));

	iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id));

	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
	iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);

	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

911
int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
912 913
				   u16 ssn_idx, u8 tx_fifo)
{
914
	if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
915 916
	    (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
	     <= txq_id)) {
917
		IWL_ERR(priv,
918
			"queue number out of range: %d, must be %d to %d\n",
919
			txq_id, IWL50_FIRST_AMPDU_QUEUE,
920 921
			IWL50_FIRST_AMPDU_QUEUE +
			priv->cfg->num_of_ampdu_queues - 1);
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
		return -EINVAL;
	}

	iwl5000_tx_queue_stop_scheduler(priv, txq_id);

	iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id));

	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
	/* supposes that ssn_idx is valid (!= 0xFFF) */
	iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx);

	iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id));
	iwl_txq_ctx_deactivate(priv, txq_id);
	iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);

	return 0;
}

941
u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
942 943
{
	u16 size = (u16)sizeof(struct iwl_addsta_cmd);
944 945 946 947
	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
	memcpy(addsta, cmd, size);
	/* resrved in 5000 */
	addsta->rate_n_flags = cpu_to_le16(0);
948 949 950 951
	return size;
}


952
/*
T
Tomas Winkler 已提交
953
 * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
954 955
 * must be called under priv->lock and mac access
 */
956
void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
957
{
958
	iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
959 960
}

961 962 963

static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
{
964
	return le32_to_cpup((__le32 *)&tx_resp->status +
965
			    tx_resp->frame_count) & MAX_SN;
966 967 968 969 970
}

static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
				      struct iwl_ht_agg *agg,
				      struct iwl5000_tx_resp *tx_resp,
971
				      int txq_id, u16 start_idx)
972 973 974 975 976
{
	u16 status;
	struct agg_tx_status *frame_status = &tx_resp->status;
	struct ieee80211_tx_info *info = NULL;
	struct ieee80211_hdr *hdr = NULL;
977
	u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
978
	int i, sh, idx;
979 980 981
	u16 seq;

	if (agg->wait_for_ba)
982
		IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
983 984 985

	agg->frame_count = tx_resp->frame_count;
	agg->start_idx = start_idx;
986
	agg->rate_n_flags = rate_n_flags;
987 988 989 990 991 992
	agg->bitmap = 0;

	/* # frames attempted by Tx command */
	if (agg->frame_count == 1) {
		/* Only one frame was attempted; no block-ack will arrive */
		status = le16_to_cpu(frame_status[0].status);
993
		idx = start_idx;
994 995

		/* FIXME: code repetition */
996
		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
997 998 999
				   agg->frame_count, agg->start_idx, idx);

		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
1000
		info->status.rates[0].count = tx_resp->failure_frame + 1;
1001
		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
1002
		info->flags |= iwl_is_tx_success(status) ?
T
Tomas Winkler 已提交
1003
					IEEE80211_TX_STAT_ACK : 0;
1004 1005
		iwl_hwrate_to_tx_control(priv, rate_n_flags, info);

1006 1007
		/* FIXME: code repetition end */

1008
		IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
1009
				    status & 0xff, tx_resp->failure_frame);
1010
		IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029

		agg->wait_for_ba = 0;
	} else {
		/* Two or more frames were attempted; expect block-ack */
		u64 bitmap = 0;
		int start = agg->start_idx;

		/* Construct bit-map of pending frames within Tx window */
		for (i = 0; i < agg->frame_count; i++) {
			u16 sc;
			status = le16_to_cpu(frame_status[i].status);
			seq  = le16_to_cpu(frame_status[i].sequence);
			idx = SEQ_TO_INDEX(seq);
			txq_id = SEQ_TO_QUEUE(seq);

			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
				      AGG_TX_STATE_ABORT_MSK))
				continue;

1030
			IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
1031 1032 1033
					   agg->frame_count, txq_id, idx);

			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
1034 1035 1036 1037 1038 1039
			if (!hdr) {
				IWL_ERR(priv,
					"BUG_ON idx doesn't point to valid skb"
					" idx=%d, txq_id=%d\n", idx, txq_id);
				return -1;
			}
1040 1041 1042

			sc = le16_to_cpu(hdr->seq_ctrl);
			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
1043 1044 1045
				IWL_ERR(priv,
					"BUG_ON idx doesn't match seq control"
					" idx=%d, seq_idx=%d, seq=%d\n",
1046 1047 1048 1049 1050
					  idx, SEQ_TO_SN(sc),
					  hdr->seq_ctrl);
				return -1;
			}

1051
			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
					   i, idx, SEQ_TO_SN(sc));

			sh = idx - start;
			if (sh > 64) {
				sh = (start - idx) + 0xff;
				bitmap = bitmap << sh;
				sh = 0;
				start = idx;
			} else if (sh < -64)
				sh  = 0xff - (start - idx);
			else if (sh < 0) {
				sh = start - idx;
				start = idx;
				bitmap = bitmap << sh;
				sh = 0;
			}
1068
			bitmap |= 1ULL << sh;
1069
			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
1070
					   start, (unsigned long long)bitmap);
1071 1072 1073 1074
		}

		agg->bitmap = bitmap;
		agg->start_idx = start;
1075
		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
				   agg->frame_count, agg->start_idx,
				   (unsigned long long)agg->bitmap);

		if (bitmap)
			agg->wait_for_ba = 1;
	}
	return 0;
}

static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
				struct iwl_rx_mem_buffer *rxb)
{
Z
Zhu Yi 已提交
1088
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1089 1090 1091 1092 1093 1094 1095
	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
	int txq_id = SEQ_TO_QUEUE(sequence);
	int index = SEQ_TO_INDEX(sequence);
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
	struct ieee80211_tx_info *info;
	struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
	u32  status = le16_to_cpu(tx_resp->status.status);
T
Tomas Winkler 已提交
1096 1097 1098
	int tid;
	int sta_id;
	int freed;
1099 1100

	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
1101
		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
1102 1103 1104 1105 1106 1107 1108 1109 1110
			  "is out of range [0-%d] %d %d\n", txq_id,
			  index, txq->q.n_bd, txq->q.write_ptr,
			  txq->q.read_ptr);
		return;
	}

	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
	memset(&info->status, 0, sizeof(info->status));

T
Tomas Winkler 已提交
1111 1112
	tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
	sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
1113 1114 1115 1116 1117 1118 1119

	if (txq->sched_retry) {
		const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
		struct iwl_ht_agg *agg = NULL;

		agg = &priv->stations[sta_id].tid[tid].agg;

1120
		iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
1121

1122 1123 1124
		/* check if BAR is needed */
		if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
1125 1126 1127

		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
1128
			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim "
T
Tomas Winkler 已提交
1129 1130 1131
					"scd_ssn=%d idx=%d txq=%d swq=%d\n",
					scd_ssn , index, txq_id, txq->swq_id);

1132
			freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1133 1134
			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;

T
Tomas Winkler 已提交
1135 1136 1137
			if (priv->mac80211_registered &&
			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
1138
				if (agg->state == IWL_AGG_OFF)
1139
					iwl_wake_queue(priv, txq_id);
1140
				else
1141
					iwl_wake_queue(priv, txq->swq_id);
1142 1143 1144
			}
		}
	} else {
T
Tomas Winkler 已提交
1145 1146
		BUG_ON(txq_id != txq->swq_id);

1147
		info->status.rates[0].count = tx_resp->failure_frame + 1;
T
Tomas Winkler 已提交
1148 1149
		info->flags |= iwl_is_tx_success(status) ?
					IEEE80211_TX_STAT_ACK : 0;
1150
		iwl_hwrate_to_tx_control(priv,
1151 1152 1153
					le32_to_cpu(tx_resp->rate_n_flags),
					info);

1154
		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
T
Tomas Winkler 已提交
1155 1156 1157 1158 1159
				   "0x%x retries %d\n",
				   txq_id,
				   iwl_get_tx_fail_reason(status), status,
				   le32_to_cpu(tx_resp->rate_n_flags),
				   tx_resp->failure_frame);
1160

T
Tomas Winkler 已提交
1161 1162
		freed = iwl_tx_queue_reclaim(priv, txq_id, index);
		if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
1163
			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
T
Tomas Winkler 已提交
1164 1165 1166

		if (priv->mac80211_registered &&
		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
1167
			iwl_wake_queue(priv, txq_id);
1168 1169
	}

T
Tomas Winkler 已提交
1170 1171 1172
	if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
		iwl_txq_check_empty(priv, sta_id, tid, txq_id);

1173
	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
1174
		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
1175 1176
}

T
Tomas Winkler 已提交
1177
/* Currently 5000 is the superset of everything */
1178
u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
G
Gregory Greenman 已提交
1179 1180 1181 1182
{
	return len;
}

1183
void iwl5000_setup_deferred_work(struct iwl_priv *priv)
1184 1185 1186 1187 1188
{
	/* in 5000 the tx power calibration is done in uCode */
	priv->disable_tx_power_cal = 1;
}

1189
void iwl5000_rx_handler_setup(struct iwl_priv *priv)
1190
{
1191 1192 1193 1194 1195
	/* init calibration handlers */
	priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
					iwl5000_rx_calib_result;
	priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
					iwl5000_rx_calib_complete;
1196
	priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx;
1197 1198
}

1199

1200
int iwl5000_hw_valid_rtc_data_addr(u32 addr)
1201
{
1202
	return (addr >= IWL50_RTC_DATA_LOWER_BOUND) &&
1203 1204 1205
		(addr < IWL50_RTC_DATA_UPPER_BOUND);
}

1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
static int iwl5000_send_rxon_assoc(struct iwl_priv *priv)
{
	int ret = 0;
	struct iwl5000_rxon_assoc_cmd rxon_assoc;
	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;

	if ((rxon1->flags == rxon2->flags) &&
	    (rxon1->filter_flags == rxon2->filter_flags) &&
	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
	    (rxon1->ofdm_ht_single_stream_basic_rates ==
	     rxon2->ofdm_ht_single_stream_basic_rates) &&
	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
	    (rxon1->ofdm_ht_triple_stream_basic_rates ==
	     rxon2->ofdm_ht_triple_stream_basic_rates) &&
	    (rxon1->acquisition_data == rxon2->acquisition_data) &&
	    (rxon1->rx_chain == rxon2->rx_chain) &&
	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
1225
		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
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
		return 0;
	}

	rxon_assoc.flags = priv->staging_rxon.flags;
	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
	rxon_assoc.reserved1 = 0;
	rxon_assoc.reserved2 = 0;
	rxon_assoc.reserved3 = 0;
	rxon_assoc.ofdm_ht_single_stream_basic_rates =
	    priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
	    priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
	rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
	rxon_assoc.ofdm_ht_triple_stream_basic_rates =
		 priv->staging_rxon.ofdm_ht_triple_stream_basic_rates;
	rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data;

	ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
				     sizeof(rxon_assoc), &rxon_assoc, NULL);
	if (ret)
		return ret;

	return ret;
}
1252
int  iwl5000_send_tx_power(struct iwl_priv *priv)
1253 1254
{
	struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
1255
	u8 tx_ant_cfg_cmd;
1256 1257 1258

	/* half dBm need to multiply */
	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
1259
	tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
1260
	tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
1261 1262 1263 1264 1265 1266 1267

	if (IWL_UCODE_API(priv->ucode_ver) == 1)
		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
	else
		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;

	return  iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
1268 1269 1270 1271
				       sizeof(tx_power_cmd), &tx_power_cmd,
				       NULL);
}

1272
void iwl5000_temperature(struct iwl_priv *priv)
1273 1274
{
	/* store temperature from statistics (in Celsius) */
1275
	priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
1276
	iwl_tt_handler(priv);
1277
}
1278

1279 1280 1281 1282 1283 1284 1285 1286 1287
static void iwl5150_temperature(struct iwl_priv *priv)
{
	u32 vt = 0;
	s32 offset =  iwl_temp_calib_to_offset(priv);

	vt = le32_to_cpu(priv->statistics.general.temperature);
	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
	/* now vt hold the temperature in Kelvin */
	priv->temperature = KELVIN_TO_CELSIUS(vt);
1288
	iwl_tt_handler(priv);
1289 1290
}

1291
/* Calc max signal level (dBm) among 3 possible receivers */
1292
int iwl5000_calc_rssi(struct iwl_priv *priv,
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
			     struct iwl_rx_phy_res *rx_resp)
{
	/* data from PHY/DSP regarding signal strength, etc.,
	 *   contents are always there, not configurable by host
	 */
	struct iwl5000_non_cfg_phy *ncphy =
		(struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
	u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
	u8 agc;

	val  = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]);
	agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS;

	/* Find max rssi among 3 possible receivers.
	 * These values are measured by the digital signal processor (DSP).
	 * They should stay fairly constant even as the signal strength varies,
	 *   if the radio's automatic gain control (AGC) is working right.
	 * AGC value (see below) will provide the "interesting" info.
	 */
	val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]);
	rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS;
	rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS;
	val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]);
	rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS;

	max_rssi = max_t(u32, rssi_a, rssi_b);
	max_rssi = max_t(u32, max_rssi, rssi_c);

1321
	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
1322 1323 1324 1325
		rssi_a, rssi_b, rssi_c, max_rssi, agc);

	/* dBm = max_rssi dB - agc dB - constant.
	 * Higher AGC (higher radio gain) means lower signal. */
1326
	return max_rssi - agc - IWL49_RSSI_OFFSET;
1327 1328
}

1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
{
	struct iwl_tx_ant_config_cmd tx_ant_cmd = {
	  .valid = cpu_to_le32(valid_tx_ant),
	};

	if (IWL_UCODE_API(priv->ucode_ver) > 1) {
		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
		return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD,
					sizeof(struct iwl_tx_ant_config_cmd),
					&tx_ant_cmd);
	} else {
		IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
		return -EOPNOTSUPP;
	}
}


1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
#define IWL5000_UCODE_GET(item)						\
static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
				    u32 api_ver)			\
{									\
	if (api_ver <= 2)						\
		return le32_to_cpu(ucode->u.v1.item);			\
	return le32_to_cpu(ucode->u.v2.item);				\
}

static u32 iwl5000_ucode_get_header_size(u32 api_ver)
{
	if (api_ver <= 2)
		return UCODE_HEADER_SIZE(1);
	return UCODE_HEADER_SIZE(2);
}

static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode,
				   u32 api_ver)
{
	if (api_ver <= 2)
		return 0;
	return le32_to_cpu(ucode->u.v2.build);
}

static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode,
				  u32 api_ver)
{
	if (api_ver <= 2)
		return (u8 *) ucode->u.v1.data;
	return (u8 *) ucode->u.v2.data;
}

IWL5000_UCODE_GET(inst_size);
IWL5000_UCODE_GET(data_size);
IWL5000_UCODE_GET(init_size);
IWL5000_UCODE_GET(init_data_size);
IWL5000_UCODE_GET(boot_size);

1385
struct iwl_hcmd_ops iwl5000_hcmd = {
1386
	.rxon_assoc = iwl5000_send_rxon_assoc,
A
Abhijeet Kolekar 已提交
1387
	.commit_rxon = iwl_commit_rxon,
1388
	.set_rxon_chain = iwl_set_rxon_chain,
1389
	.set_tx_ant = iwl5000_send_tx_ant_config,
1390 1391
};

1392
struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
G
Gregory Greenman 已提交
1393
	.get_hcmd_size = iwl5000_get_hcmd_size,
1394
	.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
1395 1396
	.gain_computation = iwl5000_gain_computation,
	.chain_noise_reset = iwl5000_chain_noise_reset,
1397
	.rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
1398
	.calc_rssi = iwl5000_calc_rssi,
1399 1400
};

1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
struct iwl_ucode_ops iwl5000_ucode = {
	.get_header_size = iwl5000_ucode_get_header_size,
	.get_build = iwl5000_ucode_get_build,
	.get_inst_size = iwl5000_ucode_get_inst_size,
	.get_data_size = iwl5000_ucode_get_data_size,
	.get_init_size = iwl5000_ucode_get_init_size,
	.get_init_data_size = iwl5000_ucode_get_init_data_size,
	.get_boot_size = iwl5000_ucode_get_boot_size,
	.get_data = iwl5000_ucode_get_data,
};

1412
struct iwl_lib_ops iwl5000_lib = {
1413
	.set_hw_params = iwl5000_hw_set_hw_params,
1414
	.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
1415
	.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
1416
	.txq_set_sched = iwl5000_txq_set_sched,
1417 1418
	.txq_agg_enable = iwl5000_txq_agg_enable,
	.txq_agg_disable = iwl5000_txq_agg_disable,
1419 1420
	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
	.txq_free_tfd = iwl_hw_txq_free_tfd,
1421
	.txq_init = iwl_hw_tx_queue_init,
1422
	.rx_handler_setup = iwl5000_rx_handler_setup,
1423
	.setup_deferred_work = iwl5000_setup_deferred_work,
1424
	.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
1425 1426
	.dump_nic_event_log = iwl_dump_nic_event_log,
	.dump_nic_error_log = iwl_dump_nic_error_log,
1427
	.load_ucode = iwl5000_load_ucode,
1428 1429
	.init_alive_start = iwl5000_init_alive_start,
	.alive_notify = iwl5000_alive_notify,
1430
	.send_tx_power = iwl5000_send_tx_power,
1431
	.update_chain_flags = iwl_update_chain_flags,
1432
	.apm_ops = {
1433
		.init = iwl_apm_init,
1434
		.stop = iwl_apm_stop,
1435
		.config = iwl5000_nic_config,
1436
		.set_pwr_src = iwl_set_pwr_src,
1437
	},
1438
	.eeprom_ops = {
1439 1440 1441 1442 1443 1444
		.regulatory_bands = {
			EEPROM_5000_REG_BAND_1_CHANNELS,
			EEPROM_5000_REG_BAND_2_CHANNELS,
			EEPROM_5000_REG_BAND_3_CHANNELS,
			EEPROM_5000_REG_BAND_4_CHANNELS,
			EEPROM_5000_REG_BAND_5_CHANNELS,
1445 1446
			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
1447
		},
1448 1449 1450
		.verify_signature  = iwlcore_eeprom_verify_signature,
		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
		.release_semaphore = iwlcore_eeprom_release_semaphore,
1451
		.calib_version	= iwl5000_eeprom_calib_version,
1452
		.query_addr = iwl5000_eeprom_query_addr,
1453
	},
1454
	.post_associate = iwl_post_associate,
M
Mohamed Abbas 已提交
1455
	.isr = iwl_isr_ict,
A
Abhijeet Kolekar 已提交
1456
	.config_ap = iwl_config_ap,
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
	.temp_ops = {
		.temperature = iwl5000_temperature,
		.set_ct_kill = iwl5000_set_ct_threshold,
	 },
};

static struct iwl_lib_ops iwl5150_lib = {
	.set_hw_params = iwl5000_hw_set_hw_params,
	.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
	.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
	.txq_set_sched = iwl5000_txq_set_sched,
	.txq_agg_enable = iwl5000_txq_agg_enable,
	.txq_agg_disable = iwl5000_txq_agg_disable,
	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
	.txq_free_tfd = iwl_hw_txq_free_tfd,
	.txq_init = iwl_hw_tx_queue_init,
	.rx_handler_setup = iwl5000_rx_handler_setup,
	.setup_deferred_work = iwl5000_setup_deferred_work,
	.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
1476 1477
	.dump_nic_event_log = iwl_dump_nic_event_log,
	.dump_nic_error_log = iwl_dump_nic_error_log,
1478 1479 1480 1481 1482 1483
	.load_ucode = iwl5000_load_ucode,
	.init_alive_start = iwl5000_init_alive_start,
	.alive_notify = iwl5000_alive_notify,
	.send_tx_power = iwl5000_send_tx_power,
	.update_chain_flags = iwl_update_chain_flags,
	.apm_ops = {
1484
		.init = iwl_apm_init,
1485
		.stop = iwl_apm_stop,
1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
		.config = iwl5000_nic_config,
		.set_pwr_src = iwl_set_pwr_src,
	},
	.eeprom_ops = {
		.regulatory_bands = {
			EEPROM_5000_REG_BAND_1_CHANNELS,
			EEPROM_5000_REG_BAND_2_CHANNELS,
			EEPROM_5000_REG_BAND_3_CHANNELS,
			EEPROM_5000_REG_BAND_4_CHANNELS,
			EEPROM_5000_REG_BAND_5_CHANNELS,
1496 1497
			EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
			EEPROM_5000_REG_BAND_52_HT40_CHANNELS
1498 1499 1500 1501 1502 1503 1504 1505
		},
		.verify_signature  = iwlcore_eeprom_verify_signature,
		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
		.release_semaphore = iwlcore_eeprom_release_semaphore,
		.calib_version	= iwl5000_eeprom_calib_version,
		.query_addr = iwl5000_eeprom_query_addr,
	},
	.post_associate = iwl_post_associate,
M
Mohamed Abbas 已提交
1506
	.isr = iwl_isr_ict,
1507 1508 1509 1510 1511
	.config_ap = iwl_config_ap,
	.temp_ops = {
		.temperature = iwl5150_temperature,
		.set_ct_kill = iwl5150_set_ct_threshold,
	 },
1512 1513
};

J
Johannes Berg 已提交
1514
static struct iwl_ops iwl5000_ops = {
1515
	.ucode = &iwl5000_ucode,
1516 1517 1518
	.lib = &iwl5000_lib,
	.hcmd = &iwl5000_hcmd,
	.utils = &iwl5000_hcmd_utils,
J
Johannes Berg 已提交
1519
	.led = &iwlagn_led_ops,
1520 1521
};

1522
static struct iwl_ops iwl5150_ops = {
1523
	.ucode = &iwl5000_ucode,
1524 1525 1526
	.lib = &iwl5150_lib,
	.hcmd = &iwl5000_hcmd,
	.utils = &iwl5000_hcmd_utils,
J
Johannes Berg 已提交
1527
	.led = &iwlagn_led_ops,
1528 1529
};

1530
struct iwl_mod_params iwl50_mod_params = {
1531
	.amsdu_size_8K = 1,
1532
	.restart_fw = 1,
1533 1534 1535 1536 1537 1538
	/* the rest are 0 by default */
};


struct iwl_cfg iwl5300_agn_cfg = {
	.name = "5300AGN",
1539 1540 1541
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
1542
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1543
	.ops = &iwl5000_ops,
1544
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1545 1546
	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
1547 1548
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
1549
	.mod_params = &iwl50_mod_params,
1550 1551
	.valid_tx_ant = ANT_ABC,
	.valid_rx_ant = ANT_ABC,
1552 1553 1554
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1555
	.ht_greenfield_support = true,
1556
	.led_compensation = 51,
1557
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1558 1559
};

1560 1561
struct iwl_cfg iwl5100_bg_cfg = {
	.name = "5100BG",
1562 1563 1564
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
1565 1566 1567
	.sku = IWL_SKU_G,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1568 1569
	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
1570 1571
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
1572
	.mod_params = &iwl50_mod_params,
1573 1574
	.valid_tx_ant = ANT_B,
	.valid_rx_ant = ANT_AB,
1575 1576 1577
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1578
	.ht_greenfield_support = true,
1579
	.led_compensation = 51,
1580
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1581 1582 1583 1584
};

struct iwl_cfg iwl5100_abg_cfg = {
	.name = "5100ABG",
1585 1586 1587
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
1588 1589 1590
	.sku = IWL_SKU_A|IWL_SKU_G,
	.ops = &iwl5000_ops,
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1591 1592
	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
1593 1594
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
1595
	.mod_params = &iwl50_mod_params,
1596 1597
	.valid_tx_ant = ANT_B,
	.valid_rx_ant = ANT_AB,
1598 1599 1600
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1601
	.ht_greenfield_support = true,
1602
	.led_compensation = 51,
1603
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1604 1605
};

1606 1607
struct iwl_cfg iwl5100_agn_cfg = {
	.name = "5100AGN",
1608 1609 1610
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
1611
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1612
	.ops = &iwl5000_ops,
1613
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1614 1615
	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
1616 1617
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
1618
	.mod_params = &iwl50_mod_params,
1619 1620
	.valid_tx_ant = ANT_B,
	.valid_rx_ant = ANT_AB,
1621 1622 1623
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1624
	.ht_greenfield_support = true,
1625
	.led_compensation = 51,
1626
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1627 1628 1629 1630
};

struct iwl_cfg iwl5350_agn_cfg = {
	.name = "5350AGN",
1631 1632 1633
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
1634
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1635
	.ops = &iwl5000_ops,
1636
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1637 1638
	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
1639 1640
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
1641
	.mod_params = &iwl50_mod_params,
1642 1643
	.valid_tx_ant = ANT_ABC,
	.valid_rx_ant = ANT_ABC,
1644 1645 1646
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1647
	.ht_greenfield_support = true,
1648
	.led_compensation = 51,
1649
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
1650 1651
};

T
Tomas Winkler 已提交
1652 1653
struct iwl_cfg iwl5150_agn_cfg = {
	.name = "5150AGN",
1654 1655 1656
	.fw_name_pre = IWL5150_FW_PRE,
	.ucode_api_max = IWL5150_UCODE_API_MAX,
	.ucode_api_min = IWL5150_UCODE_API_MIN,
T
Tomas Winkler 已提交
1657
	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1658
	.ops = &iwl5150_ops,
T
Tomas Winkler 已提交
1659
	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1660 1661
	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
1662 1663
	.num_of_queues = IWL50_NUM_QUEUES,
	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
T
Tomas Winkler 已提交
1664
	.mod_params = &iwl50_mod_params,
1665 1666
	.valid_tx_ant = ANT_A,
	.valid_rx_ant = ANT_AB,
1667 1668 1669
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
	.set_l0s = true,
	.use_bsm = false,
1670
	.ht_greenfield_support = true,
1671
	.led_compensation = 51,
1672
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
T
Tomas Winkler 已提交
1673 1674
};

1675 1676
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
1677

1678
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO);
1679 1680
MODULE_PARM_DESC(swcrypto50,
		  "using software crypto engine (default 0 [hardware])\n");
1681
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO);
1682
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
1683
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO);
1684
MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality");
1685 1686
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K,
		   int, S_IRUGO);
1687
MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series");
1688
module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO);
1689
MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error");