iwl3945-base.c 159.1 KB
Newer Older
Z
Zhu Yi 已提交
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2009 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 22 23 24
 *
 * Portions of this file are derived from the ipw3945 project, as well
 * as portions of the ieee80211 subsystem header files.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
Z
Zhu Yi 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 * 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 <linux/firmware.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>

#include <net/ieee80211_radiotap.h>
44
#include <net/lib80211.h>
Z
Zhu Yi 已提交
45 46 47 48
#include <net/mac80211.h>

#include <asm/div64.h>

49 50
#define DRV_NAME	"iwl3945"

W
Winkler, Tomas 已提交
51 52
#include "iwl-fh.h"
#include "iwl-3945-fh.h"
53
#include "iwl-commands.h"
54
#include "iwl-sta.h"
Z
Zhu Yi 已提交
55 56
#include "iwl-3945.h"
#include "iwl-helpers.h"
K
Kolekar, Abhijeet 已提交
57
#include "iwl-core.h"
58
#include "iwl-dev.h"
Z
Zhu Yi 已提交
59 60 61 62 63 64 65 66

/*
 * module name, copyright, version, etc.
 */

#define DRV_DESCRIPTION	\
"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"

S
Samuel Ortiz 已提交
67
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
68 69 70 71 72
#define VD "d"
#else
#define VD
#endif

73
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
74 75 76 77 78
#define VS "s"
#else
#define VS
#endif

79
#define IWL39_VERSION "1.2.26k" VD VS
80
#define DRV_COPYRIGHT	"Copyright(c) 2003-2009 Intel Corporation"
81
#define DRV_AUTHOR     "<ilw@linux.intel.com>"
82
#define DRV_VERSION     IWL39_VERSION
Z
Zhu Yi 已提交
83 84 85 86


MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
87
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
Z
Zhu Yi 已提交
88 89
MODULE_LICENSE("GPL");

90 91 92
 /* module parameters */
struct iwl_mod_params iwl3945_mod_params = {
	.num_of_queues = IWL39_MAX_NUM_QUEUES,
93
	.sw_crypto = 1,
94
	.restart_fw = 1,
95 96 97
	/* the rest are 0 by default */
};

Z
Zhu Yi 已提交
98
/*************** STATION TABLE MANAGEMENT ****
99
 * mac80211 should be examined to determine if sta_info is duplicating
Z
Zhu Yi 已提交
100 101 102 103
 * the functionality provided here
 */

/**************************************************************/
104
#if 0 /* temporary disable till we add real remove station */
105 106 107 108 109
/**
 * iwl3945_remove_station - Remove driver's knowledge of station.
 *
 * NOTE:  This does not remove station from device's station table.
 */
110
static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
Z
Zhu Yi 已提交
111 112 113 114 115 116 117 118 119 120
{
	int index = IWL_INVALID_STATION;
	int i;
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);

	if (is_ap)
		index = IWL_AP_ID;
	else if (is_broadcast_ether_addr(addr))
121
		index = priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
122
	else
123
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
124 125
			if (priv->stations_39[i].used &&
			    !compare_ether_addr(priv->stations_39[i].sta.sta.addr,
Z
Zhu Yi 已提交
126 127 128 129 130 131 132 133
						addr)) {
				index = i;
				break;
			}

	if (unlikely(index == IWL_INVALID_STATION))
		goto out;

134 135
	if (priv->stations_39[index].used) {
		priv->stations_39[index].used = 0;
Z
Zhu Yi 已提交
136 137 138 139 140 141 142 143 144
		priv->num_stations--;
	}

	BUG_ON(priv->num_stations < 0);

out:
	spin_unlock_irqrestore(&priv->sta_lock, flags);
	return 0;
}
145
#endif
146 147 148 149 150 151

/**
 * iwl3945_clear_stations_table - Clear the driver's station table
 *
 * NOTE:  This does not clear or otherwise alter the device's station table.
 */
152
static void iwl3945_clear_stations_table(struct iwl_priv *priv)
Z
Zhu Yi 已提交
153 154 155 156 157 158
{
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);

	priv->num_stations = 0;
159
	memset(priv->stations_39, 0, sizeof(priv->stations_39));
Z
Zhu Yi 已提交
160 161 162 163

	spin_unlock_irqrestore(&priv->sta_lock, flags);
}

164 165 166
/**
 * iwl3945_add_station - Add station to station tables in driver and device
 */
167
u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
Z
Zhu Yi 已提交
168 169 170
{
	int i;
	int index = IWL_INVALID_STATION;
C
Christoph Hellwig 已提交
171
	struct iwl3945_station_entry *station;
Z
Zhu Yi 已提交
172
	unsigned long flags_spin;
173
	u8 rate;
Z
Zhu Yi 已提交
174 175 176 177 178

	spin_lock_irqsave(&priv->sta_lock, flags_spin);
	if (is_ap)
		index = IWL_AP_ID;
	else if (is_broadcast_ether_addr(addr))
179
		index = priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
180
	else
181
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
182
			if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
Z
Zhu Yi 已提交
183 184 185 186 187
						addr)) {
				index = i;
				break;
			}

188
			if (!priv->stations_39[i].used &&
Z
Zhu Yi 已提交
189 190 191 192
			    index == IWL_INVALID_STATION)
				index = i;
		}

193
	/* These two conditions has the same outcome but keep them separate
Z
Zhu Yi 已提交
194 195 196 197 198 199
	  since they have different meaning */
	if (unlikely(index == IWL_INVALID_STATION)) {
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return index;
	}

200 201
	if (priv->stations_39[index].used &&
	   !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) {
Z
Zhu Yi 已提交
202 203 204 205
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return index;
	}

206
	IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr);
207
	station = &priv->stations_39[index];
Z
Zhu Yi 已提交
208 209 210
	station->used = 1;
	priv->num_stations++;

211
	/* Set up the REPLY_ADD_STA command to send to device */
C
Christoph Hellwig 已提交
212
	memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd));
Z
Zhu Yi 已提交
213 214 215 216 217
	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
	station->sta.mode = 0;
	station->sta.sta.sta_id = index;
	station->sta.station_flags = 0;

218
	if (priv->band == IEEE80211_BAND_5GHZ)
219 220 221
		rate = IWL_RATE_6M_PLCP;
	else
		rate =	IWL_RATE_1M_PLCP;
222 223 224

	/* Turn on both antennas for the station... */
	station->sta.rate_n_flags =
C
Christoph Hellwig 已提交
225
			iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
226

Z
Zhu Yi 已提交
227
	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
228 229

	/* Add station to device's station table */
230 231
	iwl_send_add_sta(priv,
			 (struct iwl_addsta_cmd *)&station->sta, flags);
Z
Zhu Yi 已提交
232 233 234 235
	return index;

}

236
static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
Z
Zhu Yi 已提交
237 238
{
	int rc = 0;
239
	struct iwl_rx_packet *res = NULL;
C
Christoph Hellwig 已提交
240
	struct iwl3945_rxon_assoc_cmd rxon_assoc;
241
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
242 243 244 245 246
		.id = REPLY_RXON_ASSOC,
		.len = sizeof(rxon_assoc),
		.meta.flags = CMD_WANT_SKB,
		.data = &rxon_assoc,
	};
247 248
	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
Z
Zhu Yi 已提交
249 250 251 252 253

	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)) {
254
		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
Z
Zhu Yi 已提交
255 256 257
		return 0;
	}

258 259 260 261
	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;
Z
Zhu Yi 已提交
262 263
	rxon_assoc.reserved = 0;

264
	rc = iwl_send_cmd_sync(priv, &cmd);
Z
Zhu Yi 已提交
265 266 267
	if (rc)
		return rc;

268
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
Z
Zhu Yi 已提交
269
	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
270
		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
Z
Zhu Yi 已提交
271 272 273 274 275 276 277 278 279
		rc = -EIO;
	}

	priv->alloc_rxb_skb--;
	dev_kfree_skb_any(cmd.meta.u.skb);

	return rc;
}

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
/**
 * iwl3945_get_antenna_flags - Get antenna flags for RXON command
 * @priv: eeprom and antenna fields are used to determine antenna flags
 *
 * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
 * iwl3945_mod_params.antenna specifies the antenna diversity mode:
 *
 * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
 * IWL_ANTENNA_MAIN      - Force MAIN antenna
 * IWL_ANTENNA_AUX       - Force AUX antenna
 */
__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
{
	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;

	switch (iwl3945_mod_params.antenna) {
	case IWL_ANTENNA_DIVERSITY:
		return 0;

	case IWL_ANTENNA_MAIN:
		if (eeprom->antenna_switch_type)
			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;

	case IWL_ANTENNA_AUX:
		if (eeprom->antenna_switch_type)
			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
	}

	/* bad antenna selector value */
	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
		iwl3945_mod_params.antenna);

	return 0;		/* "diversity" is default if error */
}

Z
Zhu Yi 已提交
317
/**
C
Christoph Hellwig 已提交
318
 * iwl3945_commit_rxon - commit staging_rxon to hardware
Z
Zhu Yi 已提交
319
 *
320
 * The RXON command in staging_rxon is committed to the hardware and
Z
Zhu Yi 已提交
321 322 323 324
 * 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.
 */
325
static int iwl3945_commit_rxon(struct iwl_priv *priv)
Z
Zhu Yi 已提交
326 327
{
	/* cast away the const for active_rxon in this function */
328 329
	struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
	struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
Z
Zhu Yi 已提交
330 331
	int rc = 0;

332
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
333 334 335
		return -1;

	/* always get timestamp with Rx frame */
336
	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
Z
Zhu Yi 已提交
337 338

	/* select antenna */
339
	staging_rxon->flags &=
Z
Zhu Yi 已提交
340
	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
341
	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
Z
Zhu Yi 已提交
342

343
	rc = iwl_check_rxon_cmd(priv);
Z
Zhu Yi 已提交
344
	if (rc) {
345
		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
Z
Zhu Yi 已提交
346 347 348 349
		return -EINVAL;
	}

	/* If we don't need to send a full RXON, we can use
C
Christoph Hellwig 已提交
350
	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
Z
Zhu Yi 已提交
351
	 * and other flags for the current radio configuration. */
352
	if (!iwl_full_rxon_required(priv)) {
C
Christoph Hellwig 已提交
353
		rc = iwl3945_send_rxon_assoc(priv);
Z
Zhu Yi 已提交
354
		if (rc) {
355
			IWL_ERR(priv, "Error setting RXON_ASSOC "
Z
Zhu Yi 已提交
356 357 358 359
				  "configuration (%d).\n", rc);
			return rc;
		}

360
		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
Z
Zhu Yi 已提交
361 362 363 364 365 366 367 368

		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 */
369 370
	if (iwl_is_associated(priv) &&
	    (staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK)) {
371
		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
Z
Zhu Yi 已提交
372 373
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;

374 375 376 377 378 379
		/*
		 * 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;
380
		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
C
Christoph Hellwig 已提交
381
				      sizeof(struct iwl3945_rxon_cmd),
382
				      &priv->active_rxon);
Z
Zhu Yi 已提交
383 384 385 386 387

		/* 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;
388
			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
Z
Zhu Yi 已提交
389 390 391 392 393
				  "configuration (%d).\n", rc);
			return rc;
		}
	}

394
	IWL_DEBUG_INFO(priv, "Sending RXON\n"
Z
Zhu Yi 已提交
395 396
		       "* with%s RXON_FILTER_ASSOC_MSK\n"
		       "* channel = %d\n"
J
Johannes Berg 已提交
397
		       "* bssid = %pM\n",
398
		       ((priv->staging_rxon.filter_flags &
Z
Zhu Yi 已提交
399
			 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
400 401 402 403 404 405 406 407 408
		       le16_to_cpu(staging_rxon->channel),
		       staging_rxon->bssid_addr);

	/*
	 * 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;
Z
Zhu Yi 已提交
409 410

	/* Apply the new configuration */
411
	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
412 413
			      sizeof(struct iwl3945_rxon_cmd),
			      staging_rxon);
Z
Zhu Yi 已提交
414
	if (rc) {
415
		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
Z
Zhu Yi 已提交
416 417 418
		return rc;
	}

419
	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
Z
Zhu Yi 已提交
420

C
Christoph Hellwig 已提交
421
	iwl3945_clear_stations_table(priv);
422

Z
Zhu Yi 已提交
423 424
	/* 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
Samuel Ortiz 已提交
425
	rc = priv->cfg->ops->lib->send_tx_power(priv);
Z
Zhu Yi 已提交
426
	if (rc) {
427
		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
Z
Zhu Yi 已提交
428 429 430 431
		return rc;
	}

	/* Add the broadcast address so we can send broadcast frames */
432
	if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) ==
Z
Zhu Yi 已提交
433
	    IWL_INVALID_STATION) {
434
		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
Z
Zhu Yi 已提交
435 436 437 438 439
		return -EIO;
	}

	/* If we have set the ASSOC_MSK and we are in BSS mode then
	 * add the IWL_AP_ID to the station rate table */
440
	if (iwl_is_associated(priv) &&
441
	    (priv->iw_mode == NL80211_IFTYPE_STATION))
442 443
		if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr,
					1, 0)
Z
Zhu Yi 已提交
444
		    == IWL_INVALID_STATION) {
445
			IWL_ERR(priv, "Error adding AP address for transmit\n");
Z
Zhu Yi 已提交
446 447 448
			return -EIO;
		}

449
	/* Init the hardware's rate fallback order based on the band */
Z
Zhu Yi 已提交
450 451
	rc = iwl3945_init_hw_rate_table(priv);
	if (rc) {
452
		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
Z
Zhu Yi 已提交
453 454 455 456 457 458
		return -EIO;
	}

	return 0;
}

459
static int iwl3945_update_sta_key_info(struct iwl_priv *priv,
Z
Zhu Yi 已提交
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
				   struct ieee80211_key_conf *keyconf,
				   u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;

	switch (keyconf->alg) {
	case ALG_CCMP:
		key_flags |= STA_KEY_FLG_CCMP;
		key_flags |= cpu_to_le16(
				keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
		key_flags &= ~STA_KEY_FLG_INVALID;
		break;
	case ALG_TKIP:
	case ALG_WEP:
	default:
		return -EINVAL;
	}
	spin_lock_irqsave(&priv->sta_lock, flags);
479 480 481
	priv->stations_39[sta_id].keyinfo.alg = keyconf->alg;
	priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen;
	memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key,
Z
Zhu Yi 已提交
482 483
	       keyconf->keylen);

484
	memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
Z
Zhu Yi 已提交
485
	       keyconf->keylen);
486 487 488
	priv->stations_39[sta_id].sta.key.key_flags = key_flags;
	priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Z
Zhu Yi 已提交
489 490 491

	spin_unlock_irqrestore(&priv->sta_lock, flags);

492
	IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
493 494
	iwl_send_add_sta(priv,
		(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
Z
Zhu Yi 已提交
495 496 497
	return 0;
}

498
static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
Z
Zhu Yi 已提交
499 500 501 502
{
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);
503 504
	memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
	memset(&priv->stations_39[sta_id].sta.key, 0,
505
		sizeof(struct iwl4965_keyinfo));
506 507 508
	priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
	priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Z
Zhu Yi 已提交
509 510
	spin_unlock_irqrestore(&priv->sta_lock, flags);

511
	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
512 513
	iwl_send_add_sta(priv,
		(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
Z
Zhu Yi 已提交
514 515 516
	return 0;
}

517
static void iwl3945_clear_free_frames(struct iwl_priv *priv)
Z
Zhu Yi 已提交
518 519 520
{
	struct list_head *element;

521
	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
Z
Zhu Yi 已提交
522 523 524 525 526
		       priv->frames_count);

	while (!list_empty(&priv->free_frames)) {
		element = priv->free_frames.next;
		list_del(element);
C
Christoph Hellwig 已提交
527
		kfree(list_entry(element, struct iwl3945_frame, list));
Z
Zhu Yi 已提交
528 529 530 531
		priv->frames_count--;
	}

	if (priv->frames_count) {
532
		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
Z
Zhu Yi 已提交
533 534 535 536 537
			    priv->frames_count);
		priv->frames_count = 0;
	}
}

538
static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
Z
Zhu Yi 已提交
539
{
C
Christoph Hellwig 已提交
540
	struct iwl3945_frame *frame;
Z
Zhu Yi 已提交
541 542 543 544
	struct list_head *element;
	if (list_empty(&priv->free_frames)) {
		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
		if (!frame) {
545
			IWL_ERR(priv, "Could not allocate frame!\n");
Z
Zhu Yi 已提交
546 547 548 549 550 551 552 553 554
			return NULL;
		}

		priv->frames_count++;
		return frame;
	}

	element = priv->free_frames.next;
	list_del(element);
C
Christoph Hellwig 已提交
555
	return list_entry(element, struct iwl3945_frame, list);
Z
Zhu Yi 已提交
556 557
}

558
static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
Z
Zhu Yi 已提交
559 560 561 562 563
{
	memset(frame, 0, sizeof(*frame));
	list_add(&frame->list, &priv->free_frames);
}

564
unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
Z
Zhu Yi 已提交
565
				struct ieee80211_hdr *hdr,
566
				int left)
Z
Zhu Yi 已提交
567 568
{

569
	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
570 571
	    ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
	     (priv->iw_mode != NL80211_IFTYPE_AP)))
Z
Zhu Yi 已提交
572 573 574 575 576 577 578 579 580 581
		return 0;

	if (priv->ibss_beacon->len > left)
		return 0;

	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);

	return priv->ibss_beacon->len;
}

582
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
Z
Zhu Yi 已提交
583
{
C
Christoph Hellwig 已提交
584
	struct iwl3945_frame *frame;
Z
Zhu Yi 已提交
585 586 587 588
	unsigned int frame_size;
	int rc;
	u8 rate;

C
Christoph Hellwig 已提交
589
	frame = iwl3945_get_free_frame(priv);
Z
Zhu Yi 已提交
590 591

	if (!frame) {
592
		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
Z
Zhu Yi 已提交
593 594 595 596
			  "command.\n");
		return -ENOMEM;
	}

597
	rate = iwl_rate_get_lowest_plcp(priv);
Z
Zhu Yi 已提交
598

C
Christoph Hellwig 已提交
599
	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
Z
Zhu Yi 已提交
600

601
	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
Z
Zhu Yi 已提交
602 603
			      &frame->u.cmd[0]);

C
Christoph Hellwig 已提交
604
	iwl3945_free_frame(priv, frame);
Z
Zhu Yi 已提交
605 606 607 608

	return rc;
}

609
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
Z
Zhu Yi 已提交
610
{
611
	if (priv->shared_virt)
Z
Zhu Yi 已提交
612
		pci_free_consistent(priv->pci_dev,
C
Christoph Hellwig 已提交
613
				    sizeof(struct iwl3945_shared),
614 615
				    priv->shared_virt,
				    priv->shared_phys);
Z
Zhu Yi 已提交
616 617 618 619 620
}

/*
 * QoS  support
*/
621
static int iwl3945_send_qos_params_command(struct iwl_priv *priv,
622
				       struct iwl_qosparam_cmd *qos)
Z
Zhu Yi 已提交
623 624
{

625
	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
626
				sizeof(struct iwl_qosparam_cmd), qos);
Z
Zhu Yi 已提交
627 628
}

629
static void iwl3945_activate_qos(struct iwl_priv *priv, u8 force)
Z
Zhu Yi 已提交
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
{
	unsigned long flags;

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	spin_lock_irqsave(&priv->lock, flags);
	priv->qos_data.def_qos_parm.qos_flags = 0;

	if (priv->qos_data.qos_cap.q_AP.queue_request &&
	    !priv->qos_data.qos_cap.q_AP.txop_request)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_TXOP_TYPE_MSK;

	if (priv->qos_data.qos_active)
		priv->qos_data.def_qos_parm.qos_flags |=
			QOS_PARAM_FLG_UPDATE_EDCA_MSK;

	spin_unlock_irqrestore(&priv->lock, flags);

650
	if (force || iwl_is_associated(priv)) {
651
		IWL_DEBUG_QOS(priv, "send QoS cmd with QoS active %d \n",
Z
Zhu Yi 已提交
652 653
			      priv->qos_data.qos_active);

C
Christoph Hellwig 已提交
654
		iwl3945_send_qos_params_command(priv,
Z
Zhu Yi 已提交
655 656 657 658 659 660 661 662
				&(priv->qos_data.def_qos_parm));
	}
}


#define MAX_UCODE_BEACON_INTERVAL	1024
#define INTEL_CONN_LISTEN_INTERVAL	__constant_cpu_to_le16(0xA)

C
Christoph Hellwig 已提交
663
static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
Z
Zhu Yi 已提交
664 665 666 667 668 669 670 671 672 673 674 675
{
	u16 new_val = 0;
	u16 beacon_factor = 0;

	beacon_factor =
	    (beacon_val + MAX_UCODE_BEACON_INTERVAL)
		/ MAX_UCODE_BEACON_INTERVAL;
	new_val = beacon_val / beacon_factor;

	return cpu_to_le16(new_val);
}

676
static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
Z
Zhu Yi 已提交
677 678 679 680 681 682 683 684 685 686
{
	u64 interval_tm_unit;
	u64 tsf, result;
	unsigned long flags;
	struct ieee80211_conf *conf = NULL;
	u16 beacon_int = 0;

	conf = ieee80211_get_hw_conf(priv->hw);

	spin_lock_irqsave(&priv->lock, flags);
687
	priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
Z
Zhu Yi 已提交
688 689
	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;

690
	tsf = priv->timestamp;
Z
Zhu Yi 已提交
691 692 693 694

	beacon_int = priv->beacon_int;
	spin_unlock_irqrestore(&priv->lock, flags);

695
	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
Z
Zhu Yi 已提交
696 697 698 699 700 701 702
		if (beacon_int == 0) {
			priv->rxon_timing.beacon_interval = cpu_to_le16(100);
			priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
		} else {
			priv->rxon_timing.beacon_interval =
				cpu_to_le16(beacon_int);
			priv->rxon_timing.beacon_interval =
C
Christoph Hellwig 已提交
703
			    iwl3945_adjust_beacon_interval(
Z
Zhu Yi 已提交
704 705 706 707 708 709
				le16_to_cpu(priv->rxon_timing.beacon_interval));
		}

		priv->rxon_timing.atim_window = 0;
	} else {
		priv->rxon_timing.beacon_interval =
C
Christoph Hellwig 已提交
710
			iwl3945_adjust_beacon_interval(conf->beacon_int);
Z
Zhu Yi 已提交
711 712 713 714 715 716 717 718 719 720 721
		/* TODO: we need to get atim_window from upper stack
		 * for now we set to 0 */
		priv->rxon_timing.atim_window = 0;
	}

	interval_tm_unit =
		(le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
	result = do_div(tsf, interval_tm_unit);
	priv->rxon_timing.beacon_init_val =
	    cpu_to_le32((u32) ((u64) interval_tm_unit - result));

722 723
	IWL_DEBUG_ASSOC(priv,
		"beacon interval %d beacon timer %d beacon tim %d\n",
Z
Zhu Yi 已提交
724 725 726 727 728
		le16_to_cpu(priv->rxon_timing.beacon_interval),
		le32_to_cpu(priv->rxon_timing.beacon_init_val),
		le16_to_cpu(priv->rxon_timing.atim_window));
}

729
static int iwl3945_scan_initiate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
730
{
731
	if (!iwl_is_ready_rf(priv)) {
732
		IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
Z
Zhu Yi 已提交
733 734 735 736
		return -EIO;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
737
		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
Z
Zhu Yi 已提交
738 739 740 741
		return -EAGAIN;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
742
		IWL_DEBUG_SCAN(priv, "Scan request while abort pending.  "
Z
Zhu Yi 已提交
743 744 745 746
			       "Queuing.\n");
		return -EAGAIN;
	}

747
	IWL_DEBUG_INFO(priv, "Starting scan...\n");
748 749 750 751
	if (priv->cfg->sku & IWL_SKU_G)
		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
	if (priv->cfg->sku & IWL_SKU_A)
		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
Z
Zhu Yi 已提交
752 753 754 755 756 757 758 759 760
	set_bit(STATUS_SCANNING, &priv->status);
	priv->scan_start = jiffies;
	priv->scan_pass_start = priv->scan_start;

	queue_work(priv->workqueue, &priv->request_scan);

	return 0;
}

761
static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
Z
Zhu Yi 已提交
762
{
763
	if (mode == NL80211_IFTYPE_ADHOC) {
764
		const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
765

766
		ch_info = iwl_get_channel_info(priv,
767
			priv->band,
768
			le16_to_cpu(priv->staging_rxon.channel));
Z
Zhu Yi 已提交
769 770

		if (!ch_info || !is_channel_ibss(ch_info)) {
771
			IWL_ERR(priv, "channel %d not IBSS channel\n",
772
				  le16_to_cpu(priv->staging_rxon.channel));
Z
Zhu Yi 已提交
773 774 775 776
			return -EINVAL;
		}
	}

777
	iwl_connection_init_rx_config(priv, mode);
Z
Zhu Yi 已提交
778

C
Christoph Hellwig 已提交
779
	iwl3945_clear_stations_table(priv);
Z
Zhu Yi 已提交
780

T
Tomas Winkler 已提交
781
	/* don't commit rxon if rf-kill is on*/
782
	if (!iwl_is_ready_rf(priv))
783 784 785
		return -EAGAIN;

	cancel_delayed_work(&priv->scan_check);
786
	if (iwl_scan_cancel_timeout(priv, 100)) {
787
		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
788
		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
789 790 791
		return -EAGAIN;
	}

C
Christoph Hellwig 已提交
792
	iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
793 794 795 796

	return 0;
}

797
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
798
				      struct ieee80211_tx_info *info,
799
				      struct iwl_cmd *cmd,
Z
Zhu Yi 已提交
800 801 802
				      struct sk_buff *skb_frag,
				      int last_frag)
{
803
	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
804
	struct iwl3945_hw_key *keyinfo =
805
	    &priv->stations_39[info->control.hw_key->hw_key_idx].keyinfo;
Z
Zhu Yi 已提交
806 807 808

	switch (keyinfo->alg) {
	case ALG_CCMP:
809 810
		tx->sec_ctl = TX_CMD_SEC_CCM;
		memcpy(tx->key, keyinfo->key, keyinfo->keylen);
811
		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
Z
Zhu Yi 已提交
812 813 814 815
		break;

	case ALG_TKIP:
#if 0
816
		tx->sec_ctl = TX_CMD_SEC_TKIP;
Z
Zhu Yi 已提交
817 818

		if (last_frag)
819
			memcpy(tx->tkip_mic.byte, skb_frag->tail - 8,
Z
Zhu Yi 已提交
820 821
			       8);
		else
822
			memset(tx->tkip_mic.byte, 0, 8);
Z
Zhu Yi 已提交
823 824 825 826
#endif
		break;

	case ALG_WEP:
827
		tx->sec_ctl = TX_CMD_SEC_WEP |
828
		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
Z
Zhu Yi 已提交
829 830

		if (keyinfo->keylen == 13)
831
			tx->sec_ctl |= TX_CMD_SEC_KEY128;
Z
Zhu Yi 已提交
832

833
		memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen);
Z
Zhu Yi 已提交
834

835
		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
836
			     "with key %d\n", info->control.hw_key->hw_key_idx);
Z
Zhu Yi 已提交
837 838 839
		break;

	default:
T
Tomas Winkler 已提交
840
		IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
Z
Zhu Yi 已提交
841 842 843 844 845 846 847
		break;
	}
}

/*
 * handle build REPLY_TX command notification.
 */
848
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
849
				  struct iwl_cmd *cmd,
850
				  struct ieee80211_tx_info *info,
851
				  struct ieee80211_hdr *hdr, u8 std_id)
Z
Zhu Yi 已提交
852
{
853 854
	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
	__le32 tx_flags = tx->tx_flags;
855
	__le16 fc = hdr->frame_control;
856
	u8 rc_flags = info->control.rates[0].flags;
Z
Zhu Yi 已提交
857

858
	tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
859
	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
Z
Zhu Yi 已提交
860
		tx_flags |= TX_CMD_FLG_ACK_MSK;
861
		if (ieee80211_is_mgmt(fc))
Z
Zhu Yi 已提交
862
			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
863
		if (ieee80211_is_probe_resp(fc) &&
Z
Zhu Yi 已提交
864 865 866 867 868 869 870
		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
			tx_flags |= TX_CMD_FLG_TSF_MSK;
	} else {
		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
	}

871
	tx->sta_id = std_id;
872
	if (ieee80211_has_morefrags(fc))
Z
Zhu Yi 已提交
873 874
		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;

875 876
	if (ieee80211_is_data_qos(fc)) {
		u8 *qc = ieee80211_get_qos_ctl(hdr);
877
		tx->tid_tspec = qc[0] & 0xf;
Z
Zhu Yi 已提交
878
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
879
	} else {
Z
Zhu Yi 已提交
880
		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
881
	}
Z
Zhu Yi 已提交
882

883
	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
Z
Zhu Yi 已提交
884 885
		tx_flags |= TX_CMD_FLG_RTS_MSK;
		tx_flags &= ~TX_CMD_FLG_CTS_MSK;
886
	} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
Z
Zhu Yi 已提交
887 888 889 890 891 892 893 894
		tx_flags &= ~TX_CMD_FLG_RTS_MSK;
		tx_flags |= TX_CMD_FLG_CTS_MSK;
	}

	if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
		tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;

	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
895 896
	if (ieee80211_is_mgmt(fc)) {
		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
897
			tx->timeout.pm_frame_timeout = cpu_to_le16(3);
Z
Zhu Yi 已提交
898
		else
899
			tx->timeout.pm_frame_timeout = cpu_to_le16(2);
M
Mohamed Abbas 已提交
900
	} else {
901
		tx->timeout.pm_frame_timeout = 0;
M
Mohamed Abbas 已提交
902 903 904 905
#ifdef CONFIG_IWL3945_LEDS
		priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
#endif
	}
Z
Zhu Yi 已提交
906

907 908 909
	tx->driver_txop = 0;
	tx->tx_flags = tx_flags;
	tx->next_frame_len = 0;
Z
Zhu Yi 已提交
910 911
}

912 913 914
/**
 * iwl3945_get_sta_id - Find station's index within station table
 */
915
static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
Z
Zhu Yi 已提交
916 917 918 919
{
	int sta_id;
	u16 fc = le16_to_cpu(hdr->frame_control);

920
	/* If this frame is broadcast or management, use broadcast station id */
Z
Zhu Yi 已提交
921 922
	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
	    is_multicast_ether_addr(hdr->addr1))
923
		return priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
924 925 926

	switch (priv->iw_mode) {

927 928
	/* If we are a client station in a BSS network, use the special
	 * AP station entry (that's the only station we communicate with) */
929
	case NL80211_IFTYPE_STATION:
Z
Zhu Yi 已提交
930 931 932
		return IWL_AP_ID;

	/* If we are an AP, then find the station, or use BCAST */
933
	case NL80211_IFTYPE_AP:
C
Christoph Hellwig 已提交
934
		sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
935 936
		if (sta_id != IWL_INVALID_STATION)
			return sta_id;
937
		return priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
938

939 940
	/* If this frame is going out to an IBSS network, find the station,
	 * or create a new station table entry */
941
	case NL80211_IFTYPE_ADHOC: {
942
		/* Create new station table entry */
C
Christoph Hellwig 已提交
943
		sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
Z
Zhu Yi 已提交
944 945 946
		if (sta_id != IWL_INVALID_STATION)
			return sta_id;

C
Christoph Hellwig 已提交
947
		sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
Z
Zhu Yi 已提交
948 949 950 951

		if (sta_id != IWL_INVALID_STATION)
			return sta_id;

952
		IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
Z
Zhu Yi 已提交
953
			       "Defaulting to broadcast...\n",
J
Johannes Berg 已提交
954
			       hdr->addr1);
955
		iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
956
		return priv->hw_params.bcast_sta_id;
957
	}
958 959
	/* If we are in monitor mode, use BCAST. This is required for
	 * packet injection. */
960
	case NL80211_IFTYPE_MONITOR:
961
		return priv->hw_params.bcast_sta_id;
962

Z
Zhu Yi 已提交
963
	default:
964 965
		IWL_WARN(priv, "Unknown mode of operation: %d\n",
			priv->iw_mode);
966
		return priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
967 968 969 970 971 972
	}
}

/*
 * start REPLY_TX command process
 */
973
static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
Z
Zhu Yi 已提交
974 975
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
976
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
977
	struct iwl3945_tx_cmd *tx;
978
	struct iwl_tx_queue *txq = NULL;
979
	struct iwl_queue *q = NULL;
980
	struct iwl_cmd *out_cmd = NULL;
Z
Zhu Yi 已提交
981 982
	dma_addr_t phys_addr;
	dma_addr_t txcmd_phys;
983
	int txq_id = skb_get_queue_mapping(skb);
984 985 986
	u16 len, idx, len_org, hdr_len;
	u8 id;
	u8 unicast;
Z
Zhu Yi 已提交
987
	u8 sta_id;
988
	u8 tid = 0;
Z
Zhu Yi 已提交
989
	u16 seq_number = 0;
990
	__le16 fc;
Z
Zhu Yi 已提交
991
	u8 wait_write_ptr = 0;
992
	u8 *qc = NULL;
Z
Zhu Yi 已提交
993 994 995 996
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&priv->lock, flags);
997
	if (iwl_is_rfkill(priv)) {
998
		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
Z
Zhu Yi 已提交
999 1000 1001
		goto drop_unlock;
	}

1002
	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
1003
		IWL_ERR(priv, "ERROR: No TX rate available.\n");
Z
Zhu Yi 已提交
1004 1005 1006 1007 1008 1009
		goto drop_unlock;
	}

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

1010
	fc = hdr->frame_control;
Z
Zhu Yi 已提交
1011

S
Samuel Ortiz 已提交
1012
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
1013
	if (ieee80211_is_auth(fc))
1014
		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
1015
	else if (ieee80211_is_assoc_req(fc))
1016
		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
1017
	else if (ieee80211_is_reassoc_req(fc))
1018
		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
Z
Zhu Yi 已提交
1019 1020
#endif

1021
	/* drop all data frame if we are not associated */
1022
	if (ieee80211_is_data(fc) &&
1023
	    (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
1024
	    (!iwl_is_associated(priv) ||
1025
	     ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
1026
		IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
Z
Zhu Yi 已提交
1027 1028 1029 1030 1031
		goto drop_unlock;
	}

	spin_unlock_irqrestore(&priv->lock, flags);

1032
	hdr_len = ieee80211_hdrlen(fc);
1033 1034

	/* Find (or create) index into station table for destination station */
C
Christoph Hellwig 已提交
1035
	sta_id = iwl3945_get_sta_id(priv, hdr);
Z
Zhu Yi 已提交
1036
	if (sta_id == IWL_INVALID_STATION) {
1037
		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
J
Johannes Berg 已提交
1038
			       hdr->addr1);
Z
Zhu Yi 已提交
1039 1040 1041
		goto drop;
	}

1042
	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
Z
Zhu Yi 已提交
1043

1044 1045
	if (ieee80211_is_data_qos(fc)) {
		qc = ieee80211_get_qos_ctl(hdr);
1046
		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
1047
		seq_number = priv->stations_39[sta_id].tid[tid].seq_number &
Z
Zhu Yi 已提交
1048 1049 1050 1051 1052 1053
				IEEE80211_SCTL_SEQ;
		hdr->seq_ctrl = cpu_to_le16(seq_number) |
			(hdr->seq_ctrl &
				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
		seq_number += 0x10;
	}
1054 1055

	/* Descriptor for chosen Tx queue */
1056
	txq = &priv->txq[txq_id];
Z
Zhu Yi 已提交
1057 1058 1059 1060
	q = &txq->q;

	spin_lock_irqsave(&priv->lock, flags);

1061
	idx = get_cmd_index(q, q->write_ptr, 0);
Z
Zhu Yi 已提交
1062

1063
	/* Set up driver data for this TFD */
W
Winkler, Tomas 已提交
1064
	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
1065
	txq->txb[q->write_ptr].skb[0] = skb;
1066 1067

	/* Init first empty entry in queue's array of Tx/cmd buffers */
1068
	out_cmd = txq->cmd[idx];
1069
	tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
Z
Zhu Yi 已提交
1070
	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
1071
	memset(tx, 0, sizeof(*tx));
1072 1073 1074 1075 1076 1077 1078

	/*
	 * Set up the Tx-command (not MAC!) header.
	 * Store the chosen Tx queue and TFD index within the sequence field;
	 * after Tx, uCode's Tx response will return this value so driver can
	 * locate the frame within the tx queue and do post-tx processing.
	 */
Z
Zhu Yi 已提交
1079 1080
	out_cmd->hdr.cmd = REPLY_TX;
	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
1081
				INDEX_TO_SEQ(q->write_ptr)));
1082 1083

	/* Copy MAC header from skb into command buffer */
1084
	memcpy(tx->hdr, hdr, hdr_len);
Z
Zhu Yi 已提交
1085

1086 1087 1088 1089 1090 1091 1092 1093 1094
	/*
	 * Use the first empty entry in this queue's command buffer array
	 * to contain the Tx command and MAC header concatenated together
	 * (payload data will be in another buffer).
	 * Size of this varies, due to varying MAC header length.
	 * If end is not dword aligned, we'll have 2 extra bytes at the end
	 * of the MAC header (device reads on dword boundaries).
	 * We'll tell device about this padding later.
	 */
1095
	len = sizeof(struct iwl3945_tx_cmd) +
1096
			sizeof(struct iwl_cmd_header) + hdr_len;
Z
Zhu Yi 已提交
1097 1098 1099 1100 1101 1102 1103 1104 1105

	len_org = len;
	len = (len + 3) & ~3;

	if (len_org != len)
		len_org = 1;
	else
		len_org = 0;

1106 1107
	/* Physical address of this Tx command's header (not MAC header!),
	 * within command buffer array. */
1108 1109 1110 1111 1112 1113 1114 1115
	txcmd_phys = pci_map_single(priv->pci_dev,
				    out_cmd, sizeof(struct iwl_cmd),
				    PCI_DMA_TODEVICE);
	pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
	pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
	/* Add buffer containing Tx command and MAC(!) header to TFD's
	 * first entry */
	txcmd_phys += offsetof(struct iwl_cmd, hdr);
Z
Zhu Yi 已提交
1116

1117 1118
	/* Add buffer containing Tx command and MAC(!) header to TFD's
	 * first entry */
1119 1120
	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
						   txcmd_phys, len, 1, 0);
Z
Zhu Yi 已提交
1121

1122
	if (info->control.hw_key)
1123
		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0);
Z
Zhu Yi 已提交
1124

1125 1126
	/* Set up TFD's 2nd entry to point directly to remainder of skb,
	 * if any (802.11 null frames have no payload). */
Z
Zhu Yi 已提交
1127 1128 1129 1130
	len = skb->len - hdr_len;
	if (len) {
		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
					   len, PCI_DMA_TODEVICE);
1131 1132 1133
		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
							   phys_addr, len,
							   0, U32_PAD(len));
Z
Zhu Yi 已提交
1134 1135
	}

1136
	/* Total # bytes to be transmitted */
Z
Zhu Yi 已提交
1137
	len = (u16)skb->len;
1138
	tx->len = cpu_to_le16(len);
Z
Zhu Yi 已提交
1139 1140

	/* TODO need this for burst mode later on */
1141
	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
Z
Zhu Yi 已提交
1142 1143

	/* set is_hcca to 0; it probably will never be implemented */
1144
	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
Z
Zhu Yi 已提交
1145

1146 1147
	tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
	tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
Z
Zhu Yi 已提交
1148

1149
	if (!ieee80211_has_morefrags(hdr->frame_control)) {
Z
Zhu Yi 已提交
1150
		txq->need_update = 1;
1151
		if (qc)
1152
			priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
Z
Zhu Yi 已提交
1153 1154 1155 1156 1157
	} else {
		wait_write_ptr = 1;
		txq->need_update = 0;
	}

1158
	iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
Z
Zhu Yi 已提交
1159

1160
	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
1161
			   ieee80211_hdrlen(fc));
Z
Zhu Yi 已提交
1162

1163
	/* Tell device the write index *just past* this latest filled TFD */
T
Tomas Winkler 已提交
1164
	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
1165
	rc = iwl_txq_update_write_ptr(priv, txq);
Z
Zhu Yi 已提交
1166 1167 1168 1169 1170
	spin_unlock_irqrestore(&priv->lock, flags);

	if (rc)
		return rc;

1171
	if ((iwl_queue_space(q) < q->high_mark)
Z
Zhu Yi 已提交
1172 1173 1174 1175
	    && priv->mac80211_registered) {
		if (wait_write_ptr) {
			spin_lock_irqsave(&priv->lock, flags);
			txq->need_update = 1;
1176
			iwl_txq_update_write_ptr(priv, txq);
Z
Zhu Yi 已提交
1177 1178 1179
			spin_unlock_irqrestore(&priv->lock, flags);
		}

1180
		ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb));
Z
Zhu Yi 已提交
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
	}

	return 0;

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

1191
static void iwl3945_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
Z
Zhu Yi 已提交
1192 1193 1194 1195 1196 1197
{
	unsigned long flags;

	if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
		return;

1198
	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO %s\n",
Z
Zhu Yi 已提交
1199 1200 1201
			  disable_radio ? "OFF" : "ON");

	if (disable_radio) {
1202
		iwl_scan_cancel(priv);
Z
Zhu Yi 已提交
1203
		/* FIXME: This is a workaround for AP */
1204
		if (priv->iw_mode != NL80211_IFTYPE_AP) {
Z
Zhu Yi 已提交
1205
			spin_lock_irqsave(&priv->lock, flags);
1206
			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
1207 1208
				    CSR_UCODE_SW_BIT_RFKILL);
			spin_unlock_irqrestore(&priv->lock, flags);
1209
			iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
Z
Zhu Yi 已提交
1210 1211 1212 1213 1214 1215
			set_bit(STATUS_RF_KILL_SW, &priv->status);
		}
		return;
	}

	spin_lock_irqsave(&priv->lock, flags);
1216
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Z
Zhu Yi 已提交
1217 1218 1219 1220 1221 1222 1223 1224

	clear_bit(STATUS_RF_KILL_SW, &priv->status);
	spin_unlock_irqrestore(&priv->lock, flags);

	/* wake up ucode */
	msleep(10);

	spin_lock_irqsave(&priv->lock, flags);
1225 1226 1227
	iwl_read32(priv, CSR_UCODE_DRV_GP1);
	if (!iwl_grab_nic_access(priv))
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
1228 1229 1230
	spin_unlock_irqrestore(&priv->lock, flags);

	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
1231
		IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
Z
Zhu Yi 已提交
1232 1233 1234 1235
				  "disabled by HW switch\n");
		return;
	}

1236 1237
	if (priv->is_open)
		queue_work(priv->workqueue, &priv->restart);
Z
Zhu Yi 已提交
1238 1239 1240
	return;
}

1241
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255

#include "iwl-spectrum.h"

#define BEACON_TIME_MASK_LOW	0x00FFFFFF
#define BEACON_TIME_MASK_HIGH	0xFF000000
#define TIME_UNIT		1024

/*
 * extended beacon time format
 * time in usec will be changed into a 32-bit value in 8:24 format
 * the high 1 byte is the beacon counts
 * the lower 3 bytes is the time in usec within one beacon interval
 */

C
Christoph Hellwig 已提交
1256
static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval)
Z
Zhu Yi 已提交
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
{
	u32 quot;
	u32 rem;
	u32 interval = beacon_interval * 1024;

	if (!interval || !usec)
		return 0;

	quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
	rem = (usec % interval) & BEACON_TIME_MASK_LOW;

	return (quot << 24) + rem;
}

/* base is usually what we get from ucode with each received frame,
 * the same as HW timer counter counting down
 */

C
Christoph Hellwig 已提交
1275
static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
Z
Zhu Yi 已提交
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
{
	u32 base_low = base & BEACON_TIME_MASK_LOW;
	u32 addon_low = addon & BEACON_TIME_MASK_LOW;
	u32 interval = beacon_interval * TIME_UNIT;
	u32 res = (base & BEACON_TIME_MASK_HIGH) +
	    (addon & BEACON_TIME_MASK_HIGH);

	if (base_low > addon_low)
		res += base_low - addon_low;
	else if (base_low < addon_low) {
		res += interval + base_low - addon_low;
		res += (1 << 24);
	} else
		res += (1 << 24);

	return cpu_to_le32(res);
}

1294
static int iwl3945_get_measurement(struct iwl_priv *priv,
Z
Zhu Yi 已提交
1295 1296 1297
			       struct ieee80211_measurement_params *params,
			       u8 type)
{
1298
	struct iwl_spectrum_cmd spectrum;
1299
	struct iwl_rx_packet *res;
1300
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
1301 1302 1303 1304 1305 1306 1307 1308 1309
		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
		.data = (void *)&spectrum,
		.meta.flags = CMD_WANT_SKB,
	};
	u32 add_time = le64_to_cpu(params->start_time);
	int rc;
	int spectrum_resp_status;
	int duration = le16_to_cpu(params->duration);

1310
	if (iwl_is_associated(priv))
Z
Zhu Yi 已提交
1311
		add_time =
C
Christoph Hellwig 已提交
1312
		    iwl3945_usecs_to_beacons(
Z
Zhu Yi 已提交
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
			le64_to_cpu(params->start_time) - priv->last_tsf,
			le16_to_cpu(priv->rxon_timing.beacon_interval));

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

	spectrum.channel_count = cpu_to_le16(1);
	spectrum.flags =
	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
	cmd.len = sizeof(spectrum);
	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));

1325
	if (iwl_is_associated(priv))
Z
Zhu Yi 已提交
1326
		spectrum.start_time =
C
Christoph Hellwig 已提交
1327
		    iwl3945_add_beacon_time(priv->last_beacon_time,
Z
Zhu Yi 已提交
1328 1329 1330 1331 1332 1333 1334 1335
				add_time,
				le16_to_cpu(priv->rxon_timing.beacon_interval));
	else
		spectrum.start_time = 0;

	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
	spectrum.channels[0].channel = params->channel;
	spectrum.channels[0].type = type;
1336
	if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
Z
Zhu Yi 已提交
1337 1338 1339
		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;

1340
	rc = iwl_send_cmd_sync(priv, &cmd);
Z
Zhu Yi 已提交
1341 1342 1343
	if (rc)
		return rc;

1344
	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
Z
Zhu Yi 已提交
1345
	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
1346
		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
Z
Zhu Yi 已提交
1347 1348 1349 1350 1351 1352 1353
		rc = -EIO;
	}

	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
	switch (spectrum_resp_status) {
	case 0:		/* Command will be handled */
		if (res->u.spectrum.id != 0xff) {
1354
			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
1355
						res->u.spectrum.id);
Z
Zhu Yi 已提交
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
			priv->measurement_status &= ~MEASUREMENT_READY;
		}
		priv->measurement_status |= MEASUREMENT_ACTIVE;
		rc = 0;
		break;

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

	dev_kfree_skb_any(cmd.meta.u.skb);

	return rc;
}
#endif

1373
static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
1374
			       struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1375
{
1376 1377
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
	struct iwl_alive_resp *palive;
Z
Zhu Yi 已提交
1378 1379 1380 1381
	struct delayed_work *pwork;

	palive = &pkt->u.alive_frame;

1382
	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
Z
Zhu Yi 已提交
1383 1384 1385 1386 1387
		       "0x%01X 0x%01X\n",
		       palive->is_valid, palive->ver_type,
		       palive->ver_subtype);

	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
1388
		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
1389 1390
		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
		       sizeof(struct iwl_alive_resp));
Z
Zhu Yi 已提交
1391 1392
		pwork = &priv->init_alive_start;
	} else {
1393
		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
Z
Zhu Yi 已提交
1394
		memcpy(&priv->card_alive, &pkt->u.alive_frame,
1395
		       sizeof(struct iwl_alive_resp));
Z
Zhu Yi 已提交
1396
		pwork = &priv->alive_start;
C
Christoph Hellwig 已提交
1397
		iwl3945_disable_events(priv);
Z
Zhu Yi 已提交
1398 1399 1400 1401 1402 1403 1404 1405
	}

	/* We delay the ALIVE response by 5ms to
	 * give the HW RF Kill time to activate... */
	if (palive->is_valid == UCODE_VALID_OK)
		queue_delayed_work(priv->workqueue, pwork,
				   msecs_to_jiffies(5));
	else
1406
		IWL_WARN(priv, "uCode did not respond OK.\n");
Z
Zhu Yi 已提交
1407 1408
}

1409
static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
1410
				 struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1411
{
1412
#ifdef CONFIG_IWLWIFI_DEBUG
1413
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1414
#endif
Z
Zhu Yi 已提交
1415

1416
	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
Z
Zhu Yi 已提交
1417 1418 1419
	return;
}

1420
static void iwl3945_rx_reply_error(struct iwl_priv *priv,
1421
			       struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1422
{
1423
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
Z
Zhu Yi 已提交
1424

1425
	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
Z
Zhu Yi 已提交
1426 1427 1428 1429 1430 1431 1432 1433
		"seq 0x%04X ser 0x%08X\n",
		le32_to_cpu(pkt->u.err_resp.error_type),
		get_cmd_string(pkt->u.err_resp.cmd_id),
		pkt->u.err_resp.cmd_id,
		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
		le32_to_cpu(pkt->u.err_resp.error_info));
}

1434
static void iwl3945_rx_spectrum_measure_notif(struct iwl_priv *priv,
1435
					  struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1436
{
1437
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
1438
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1439
	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
Z
Zhu Yi 已提交
1440 1441

	if (!report->state) {
1442
		IWL_DEBUG(priv, IWL_DL_11H | IWL_DL_INFO,
Z
Zhu Yi 已提交
1443 1444 1445 1446 1447 1448 1449 1450 1451
			  "Spectrum Measure Notification: Start\n");
		return;
	}

	memcpy(&priv->measure_report, report, sizeof(*report));
	priv->measurement_status |= MEASUREMENT_READY;
#endif
}

1452
static void iwl3945_rx_pm_sleep_notif(struct iwl_priv *priv,
1453
				  struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1454
{
S
Samuel Ortiz 已提交
1455
#ifdef CONFIG_IWLWIFI_DEBUG
1456
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1457
	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
1458
	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
Z
Zhu Yi 已提交
1459 1460 1461 1462
		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}

1463
static void iwl3945_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
1464
					     struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1465
{
1466
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1467
	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
Z
Zhu Yi 已提交
1468 1469
			"notification for %s:\n",
			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
1470 1471
	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw,
			   le32_to_cpu(pkt->len));
Z
Zhu Yi 已提交
1472 1473
}

C
Christoph Hellwig 已提交
1474
static void iwl3945_bg_beacon_update(struct work_struct *work)
Z
Zhu Yi 已提交
1475
{
1476 1477
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, beacon_update);
Z
Zhu Yi 已提交
1478 1479 1480
	struct sk_buff *beacon;

	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
1481
	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
Z
Zhu Yi 已提交
1482 1483

	if (!beacon) {
1484
		IWL_ERR(priv, "update beacon failed\n");
Z
Zhu Yi 已提交
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
		return;
	}

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

	priv->ibss_beacon = beacon;
	mutex_unlock(&priv->mutex);

C
Christoph Hellwig 已提交
1496
	iwl3945_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
1497 1498
}

1499
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
1500
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1501
{
S
Samuel Ortiz 已提交
1502
#ifdef CONFIG_IWLWIFI_DEBUG
1503
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
C
Christoph Hellwig 已提交
1504
	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
Z
Zhu Yi 已提交
1505 1506
	u8 rate = beacon->beacon_notify_hdr.rate;

1507
	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
Z
Zhu Yi 已提交
1508 1509 1510 1511 1512 1513 1514 1515
		"tsf %d %d rate %d\n",
		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
		beacon->beacon_notify_hdr.failure_frame,
		le32_to_cpu(beacon->ibss_mgr_status),
		le32_to_cpu(beacon->high_tsf),
		le32_to_cpu(beacon->low_tsf), rate);
#endif

1516
	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
Z
Zhu Yi 已提交
1517 1518 1519 1520 1521
	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
		queue_work(priv->workqueue, &priv->beacon_update);
}

/* Service response to REPLY_SCAN_CMD (0x80) */
1522
static void iwl3945_rx_reply_scan(struct iwl_priv *priv,
1523
			      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1524
{
S
Samuel Ortiz 已提交
1525
#ifdef CONFIG_IWLWIFI_DEBUG
1526
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1527 1528
	struct iwl_scanreq_notification *notif =
	    (struct iwl_scanreq_notification *)pkt->u.raw;
Z
Zhu Yi 已提交
1529

1530
	IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status);
Z
Zhu Yi 已提交
1531 1532 1533 1534
#endif
}

/* Service SCAN_START_NOTIFICATION (0x82) */
1535
static void iwl3945_rx_scan_start_notif(struct iwl_priv *priv,
1536
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1537
{
1538
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1539 1540
	struct iwl_scanstart_notification *notif =
	    (struct iwl_scanstart_notification *)pkt->u.raw;
Z
Zhu Yi 已提交
1541
	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
1542
	IWL_DEBUG_SCAN(priv, "Scan start: "
Z
Zhu Yi 已提交
1543 1544 1545 1546 1547 1548 1549 1550 1551
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       notif->tsf_high,
		       notif->tsf_low, notif->status, notif->beacon_timer);
}

/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
1552
static void iwl3945_rx_scan_results_notif(struct iwl_priv *priv,
1553
				      struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1554
{
1555
#ifdef CONFIG_IWLWIFI_DEBUG
1556
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1557 1558
	struct iwl_scanresults_notification *notif =
	    (struct iwl_scanresults_notification *)pkt->u.raw;
1559
#endif
Z
Zhu Yi 已提交
1560

1561
	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
Z
Zhu Yi 已提交
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d "
		       "elapsed=%lu usec (%dms since last)\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       le32_to_cpu(notif->tsf_high),
		       le32_to_cpu(notif->tsf_low),
		       le32_to_cpu(notif->statistics[0]),
		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
		       jiffies_to_msecs(elapsed_jiffies
					(priv->last_scan_jiffies, jiffies)));

	priv->last_scan_jiffies = jiffies;
1575
	priv->next_scan_jiffies = 0;
Z
Zhu Yi 已提交
1576 1577 1578
}

/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
1579
static void iwl3945_rx_scan_complete_notif(struct iwl_priv *priv,
1580
				       struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1581
{
1582
#ifdef CONFIG_IWLWIFI_DEBUG
1583
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
1584
	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
1585
#endif
Z
Zhu Yi 已提交
1586

1587
	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
Z
Zhu Yi 已提交
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
		       scan_notif->scanned_channels,
		       scan_notif->tsf_low,
		       scan_notif->tsf_high, scan_notif->status);

	/* The HW is no longer scanning */
	clear_bit(STATUS_SCAN_HW, &priv->status);

	/* The scan completion notification came in, so kill that timer... */
	cancel_delayed_work(&priv->scan_check);

1598
	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
1599 1600
		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
							"2.4" : "5.2",
Z
Zhu Yi 已提交
1601 1602 1603
		       jiffies_to_msecs(elapsed_jiffies
					(priv->scan_pass_start, jiffies)));

1604 1605 1606 1607 1608 1609 1610
	/* Remove this scanned band from the list of pending
	 * bands to scan, band G precedes A in order of scanning
	 * as seen in iwl3945_bg_request_scan */
	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
		priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
	else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
		priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
Z
Zhu Yi 已提交
1611 1612 1613 1614 1615

	/* If a request to abort was given, or the scan did not succeed
	 * then we reset the scan state machine and terminate,
	 * re-queuing another scan if one has been requested */
	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
1616
		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
Z
Zhu Yi 已提交
1617 1618 1619 1620 1621 1622 1623 1624
		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
	} else {
		/* If there are more bands on this scan pass reschedule */
		if (priv->scan_bands > 0)
			goto reschedule;
	}

	priv->last_scan_jiffies = jiffies;
1625
	priv->next_scan_jiffies = 0;
1626
	IWL_DEBUG_INFO(priv, "Setting scan to off\n");
Z
Zhu Yi 已提交
1627 1628 1629

	clear_bit(STATUS_SCANNING, &priv->status);

1630
	IWL_DEBUG_INFO(priv, "Scan took %dms\n",
Z
Zhu Yi 已提交
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));

	queue_work(priv->workqueue, &priv->scan_completed);

	return;

reschedule:
	priv->scan_pass_start = jiffies;
	queue_work(priv->workqueue, &priv->request_scan);
}

/* Handle notification from uCode that card's power state is changing
 * due to software, hardware, or critical temperature RFKILL */
1644
static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
1645
				    struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1646
{
1647
	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
Z
Zhu Yi 已提交
1648 1649 1650
	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
	unsigned long status = priv->status;

1651
	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
Z
Zhu Yi 已提交
1652 1653 1654
			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");

1655
	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
Z
Zhu Yi 已提交
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

	if (flags & HW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_HW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_HW, &priv->status);


	if (flags & SW_CARD_DISABLED)
		set_bit(STATUS_RF_KILL_SW, &priv->status);
	else
		clear_bit(STATUS_RF_KILL_SW, &priv->status);

1669
	iwl_scan_cancel(priv);
Z
Zhu Yi 已提交
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680

	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
	    (test_bit(STATUS_RF_KILL_SW, &status) !=
	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
		queue_work(priv->workqueue, &priv->rf_kill);
	else
		wake_up_interruptible(&priv->wait_command_queue);
}

/**
C
Christoph Hellwig 已提交
1681
 * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
Z
Zhu Yi 已提交
1682 1683 1684 1685 1686 1687 1688
 *
 * Setup the RX handlers for each of the reply types sent from the uCode
 * to the host.
 *
 * This function chains into the hardware specific files for them to setup
 * any hardware specific handlers as well.
 */
1689
static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1690
{
C
Christoph Hellwig 已提交
1691 1692 1693
	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
	priv->rx_handlers[REPLY_ERROR] = iwl3945_rx_reply_error;
1694
	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
Z
Zhu Yi 已提交
1695
	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
C
Christoph Hellwig 已提交
1696 1697
	    iwl3945_rx_spectrum_measure_notif;
	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl3945_rx_pm_sleep_notif;
Z
Zhu Yi 已提交
1698
	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
C
Christoph Hellwig 已提交
1699 1700
	    iwl3945_rx_pm_debug_statistics_notif;
	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
Z
Zhu Yi 已提交
1701

1702 1703 1704 1705
	/*
	 * The same handler is used for both the REPLY to a discrete
	 * statistics request from the host as well as for the periodic
	 * statistics notifications (after received beacons) from the uCode.
Z
Zhu Yi 已提交
1706
	 */
C
Christoph Hellwig 已提交
1707 1708
	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
Z
Zhu Yi 已提交
1709

C
Christoph Hellwig 已提交
1710 1711
	priv->rx_handlers[REPLY_SCAN_CMD] = iwl3945_rx_reply_scan;
	priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl3945_rx_scan_start_notif;
Z
Zhu Yi 已提交
1712
	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
C
Christoph Hellwig 已提交
1713
	    iwl3945_rx_scan_results_notif;
Z
Zhu Yi 已提交
1714
	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
C
Christoph Hellwig 已提交
1715 1716
	    iwl3945_rx_scan_complete_notif;
	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
Z
Zhu Yi 已提交
1717

1718
	/* Set up hardware specific Rx handlers */
C
Christoph Hellwig 已提交
1719
	iwl3945_hw_rx_handler_setup(priv);
Z
Zhu Yi 已提交
1720 1721
}

1722 1723 1724 1725 1726
/**
 * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
 * When FW advances 'R' index, all entries between old and new 'R' index
 * need to be reclaimed.
 */
1727
static void iwl3945_cmd_queue_reclaim(struct iwl_priv *priv,
1728 1729
				      int txq_id, int index)
{
1730
	struct iwl_tx_queue *txq = &priv->txq[txq_id];
1731
	struct iwl_queue *q = &txq->q;
1732 1733
	int nfreed = 0;

1734
	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
1735
		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
1736 1737 1738 1739 1740 1741 1742 1743
			  "is out of range [0-%d] %d %d.\n", txq_id,
			  index, q->n_bd, q->write_ptr, q->read_ptr);
		return;
	}

	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
		if (nfreed > 1) {
1744
			IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", index,
1745 1746 1747 1748 1749 1750 1751 1752 1753
					q->write_ptr, q->read_ptr);
			queue_work(priv->workqueue, &priv->restart);
			break;
		}
		nfreed++;
	}
}


Z
Zhu Yi 已提交
1754
/**
C
Christoph Hellwig 已提交
1755
 * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
Z
Zhu Yi 已提交
1756 1757 1758 1759 1760 1761
 * @rxb: Rx buffer to reclaim
 *
 * If an Rx buffer has an async callback associated with it the callback
 * will be executed.  The attached skb (if present) will only be freed
 * if the callback returns 1
 */
1762
static void iwl3945_tx_cmd_complete(struct iwl_priv *priv,
1763
				struct iwl_rx_mem_buffer *rxb)
Z
Zhu Yi 已提交
1764
{
1765
	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
1766 1767 1768
	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
	int txq_id = SEQ_TO_QUEUE(sequence);
	int index = SEQ_TO_INDEX(sequence);
1769
	int huge =  !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
Z
Zhu Yi 已提交
1770
	int cmd_index;
1771
	struct iwl_cmd *cmd;
Z
Zhu Yi 已提交
1772

1773 1774 1775 1776 1777 1778 1779 1780
	if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
		 "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n",
		  txq_id, sequence,
		  priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
		  priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
		iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32);
		return;
	}
Z
Zhu Yi 已提交
1781

1782 1783
	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
	cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
Z
Zhu Yi 已提交
1784 1785 1786 1787 1788 1789 1790 1791 1792

	/* Input error checking is done when commands are added to queue. */
	if (cmd->meta.flags & CMD_WANT_SKB) {
		cmd->meta.source->u.skb = rxb->skb;
		rxb->skb = NULL;
	} else if (cmd->meta.u.callback &&
		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
		rxb->skb = NULL;

1793
	iwl3945_cmd_queue_reclaim(priv, txq_id, index);
Z
Zhu Yi 已提交
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822

	if (!(cmd->meta.flags & CMD_ASYNC)) {
		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
		wake_up_interruptible(&priv->wait_command_queue);
	}
}

/************************** RX-FUNCTIONS ****************************/
/*
 * Rx theory of operation
 *
 * The host allocates 32 DMA target addresses and passes the host address
 * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
 * 0 to 31
 *
 * Rx Queue Indexes
 * The host/firmware share two index registers for managing the Rx buffers.
 *
 * The READ index maps to the first position that the firmware may be writing
 * to -- the driver can read up to (but not including) this position and get
 * good data.
 * The READ index is managed by the firmware once the card is enabled.
 *
 * The WRITE index maps to the last position the driver has read from -- the
 * position preceding WRITE is the last slot the firmware can place a packet.
 *
 * The queue is empty (no good data) if WRITE = READ - 1, and is full if
 * WRITE = READ.
 *
1823
 * During initialization, the host sets up the READ queue position to the first
Z
Zhu Yi 已提交
1824 1825
 * INDEX position, and WRITE to the last (READ - 1 wrapped)
 *
1826
 * When the firmware places a packet in a buffer, it will advance the READ index
Z
Zhu Yi 已提交
1827 1828 1829 1830 1831 1832 1833
 * and fire the RX interrupt.  The driver can then query the READ index and
 * process as many packets as possible, moving the WRITE index forward as it
 * resets the Rx queue buffers with new memory.
 *
 * The management in the driver is as follows:
 * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
 *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
1834
 *   to replenish the iwl->rxq->rx_free.
C
Christoph Hellwig 已提交
1835
 * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
Z
Zhu Yi 已提交
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
 *   iwl->rxq is replenished and the READ INDEX is updated (updating the
 *   'processed' and 'read' driver indexes as well)
 * + A received packet is processed and handed to the kernel network stack,
 *   detached from the iwl->rxq.  The driver 'processed' index is updated.
 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
 *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
 *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
 *   were enough free buffers and RX_STALLED is set it is cleared.
 *
 *
 * Driver sequence:
 *
1848
 * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
C
Christoph Hellwig 已提交
1849
 *                            iwl3945_rx_queue_restock
1850
 * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
Z
Zhu Yi 已提交
1851 1852
 *                            queue, updates firmware pointers, and updates
 *                            the WRITE index.  If insufficient rx_free buffers
C
Christoph Hellwig 已提交
1853
 *                            are available, schedules iwl3945_rx_replenish
Z
Zhu Yi 已提交
1854 1855
 *
 * -- enable interrupts --
1856
 * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
Z
Zhu Yi 已提交
1857 1858
 *                            READ INDEX, detaching the SKB from the pool.
 *                            Moves the packet buffer from queue to rx_used.
C
Christoph Hellwig 已提交
1859
 *                            Calls iwl3945_rx_queue_restock to refill any empty
Z
Zhu Yi 已提交
1860 1861 1862 1863 1864 1865
 *                            slots.
 * ...
 *
 */

/**
1866
 * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
Z
Zhu Yi 已提交
1867
 */
1868
static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
Z
Zhu Yi 已提交
1869 1870 1871 1872 1873 1874
					  dma_addr_t dma_addr)
{
	return cpu_to_le32((u32)dma_addr);
}

/**
C
Christoph Hellwig 已提交
1875
 * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
Z
Zhu Yi 已提交
1876
 *
1877
 * If there are slots in the RX queue that need to be restocked,
Z
Zhu Yi 已提交
1878
 * and we have free pre-allocated buffers, fill the ranks as much
1879
 * as we can, pulling from rx_free.
Z
Zhu Yi 已提交
1880 1881 1882 1883 1884
 *
 * This moves the 'write' index forward to catch up with 'processed', and
 * also updates the memory address in the firmware to reference the new
 * target buffer.
 */
1885
static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1886
{
1887
	struct iwl_rx_queue *rxq = &priv->rxq;
Z
Zhu Yi 已提交
1888
	struct list_head *element;
1889
	struct iwl_rx_mem_buffer *rxb;
Z
Zhu Yi 已提交
1890 1891 1892 1893 1894
	unsigned long flags;
	int write, rc;

	spin_lock_irqsave(&rxq->lock, flags);
	write = rxq->write & ~0x7;
1895
	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
1896
		/* Get next free Rx buffer, remove from free list */
Z
Zhu Yi 已提交
1897
		element = rxq->rx_free.next;
1898
		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
Z
Zhu Yi 已提交
1899
		list_del(element);
1900 1901

		/* Point to Rx buffer via next RBD in circular buffer */
1902
		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);
Z
Zhu Yi 已提交
1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
		rxq->queue[rxq->write] = rxb;
		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
		rxq->free_count--;
	}
	spin_unlock_irqrestore(&rxq->lock, flags);
	/* If the pre-allocated buffer pool is dropping low, schedule to
	 * refill it */
	if (rxq->free_count <= RX_LOW_WATERMARK)
		queue_work(priv->workqueue, &priv->rx_replenish);


1914 1915
	/* If we've added more space for the firmware to place data, tell it.
	 * Increment device's write pointer in multiples of 8. */
Z
Zhu Yi 已提交
1916 1917 1918 1919 1920
	if ((write != (rxq->write & ~0x7))
	    || (abs(rxq->write - rxq->read) > 7)) {
		spin_lock_irqsave(&rxq->lock, flags);
		rxq->need_update = 1;
		spin_unlock_irqrestore(&rxq->lock, flags);
1921
		rc = iwl_rx_queue_update_write_ptr(priv, rxq);
Z
Zhu Yi 已提交
1922 1923 1924 1925 1926 1927 1928 1929
		if (rc)
			return rc;
	}

	return 0;
}

/**
C
Christoph Hellwig 已提交
1930
 * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
Z
Zhu Yi 已提交
1931 1932 1933
 *
 * When moving to rx_free an SKB is allocated for the slot.
 *
C
Christoph Hellwig 已提交
1934
 * Also restock the Rx queue via iwl3945_rx_queue_restock.
1935
 * This is called as a scheduled work item (except for during initialization)
Z
Zhu Yi 已提交
1936
 */
1937
static void iwl3945_rx_allocate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
1938
{
1939
	struct iwl_rx_queue *rxq = &priv->rxq;
Z
Zhu Yi 已提交
1940
	struct list_head *element;
1941
	struct iwl_rx_mem_buffer *rxb;
Z
Zhu Yi 已提交
1942 1943 1944 1945
	unsigned long flags;
	spin_lock_irqsave(&rxq->lock, flags);
	while (!list_empty(&rxq->rx_used)) {
		element = rxq->rx_used.next;
1946
		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
1947 1948

		/* Alloc a new receive buffer */
Z
Zhu Yi 已提交
1949
		rxb->skb =
1950 1951
		    alloc_skb(priv->hw_params.rx_buf_size,
				__GFP_NOWARN | GFP_ATOMIC);
Z
Zhu Yi 已提交
1952 1953
		if (!rxb->skb) {
			if (net_ratelimit())
T
Tomas Winkler 已提交
1954
				IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
Z
Zhu Yi 已提交
1955 1956 1957 1958 1959
			/* We don't reschedule replenish work here -- we will
			 * call the restock method and if it still needs
			 * more buffers it will schedule replenish */
			break;
		}
Z
Zhu Yi 已提交
1960 1961 1962 1963 1964 1965 1966 1967 1968

		/* If radiotap head is required, reserve some headroom here.
		 * The physical head count is a variable rx_stats->phy_count.
		 * We reserve 4 bytes here. Plus these extra bytes, the
		 * headroom of the physical head should be enough for the
		 * radiotap head that iwl3945 supported. See iwl3945_rt.
		 */
		skb_reserve(rxb->skb, 4);

Z
Zhu Yi 已提交
1969 1970
		priv->alloc_rxb_skb++;
		list_del(element);
1971 1972

		/* Get physical address of RB/SKB */
1973 1974 1975 1976
		rxb->real_dma_addr = pci_map_single(priv->pci_dev,
						rxb->skb->data,
						priv->hw_params.rx_buf_size,
						PCI_DMA_FROMDEVICE);
Z
Zhu Yi 已提交
1977 1978 1979 1980
		list_add_tail(&rxb->list, &rxq->rx_free);
		rxq->free_count++;
	}
	spin_unlock_irqrestore(&rxq->lock, flags);
1981 1982 1983 1984 1985
}

/*
 * this should be called while priv->lock is locked
 */
1986
static void __iwl3945_rx_replenish(void *data)
1987
{
1988
	struct iwl_priv *priv = data;
1989 1990 1991 1992 1993 1994 1995 1996

	iwl3945_rx_allocate(priv);
	iwl3945_rx_queue_restock(priv);
}


void iwl3945_rx_replenish(void *data)
{
1997
	struct iwl_priv *priv = data;
1998 1999 2000
	unsigned long flags;

	iwl3945_rx_allocate(priv);
Z
Zhu Yi 已提交
2001 2002

	spin_lock_irqsave(&priv->lock, flags);
C
Christoph Hellwig 已提交
2003
	iwl3945_rx_queue_restock(priv);
Z
Zhu Yi 已提交
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
	spin_unlock_irqrestore(&priv->lock, flags);
}

/* Convert linear signal-to-noise ratio into dB */
static u8 ratio2dB[100] = {
/*	 0   1   2   3   4   5   6   7   8   9 */
	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
};

/* Calculates a relative dB value from a ratio of linear
 *   (i.e. not dB) signal levels.
 * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
C
Christoph Hellwig 已提交
2025
int iwl3945_calc_db_from_ratio(int sig_ratio)
Z
Zhu Yi 已提交
2026
{
2027 2028
	/* 1000:1 or higher just report as 60 dB */
	if (sig_ratio >= 1000)
Z
Zhu Yi 已提交
2029 2030
		return 60;

2031
	/* 100:1 or higher, divide by 10 and use table,
Z
Zhu Yi 已提交
2032
	 *   add 20 dB to make up for divide by 10 */
2033
	if (sig_ratio >= 100)
2034
		return 20 + (int)ratio2dB[sig_ratio/10];
Z
Zhu Yi 已提交
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050

	/* We shouldn't see this */
	if (sig_ratio < 1)
		return 0;

	/* Use table for ratios 1:1 - 99:1 */
	return (int)ratio2dB[sig_ratio];
}

#define PERFECT_RSSI (-20) /* dBm */
#define WORST_RSSI (-95)   /* dBm */
#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)

/* Calculate an indication of rx signal quality (a percentage, not dBm!).
 * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
 *   about formulas used below. */
C
Christoph Hellwig 已提交
2051
int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
Z
Zhu Yi 已提交
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085
{
	int sig_qual;
	int degradation = PERFECT_RSSI - rssi_dbm;

	/* If we get a noise measurement, use signal-to-noise ratio (SNR)
	 * as indicator; formula is (signal dbm - noise dbm).
	 * SNR at or above 40 is a great signal (100%).
	 * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
	 * Weakest usable signal is usually 10 - 15 dB SNR. */
	if (noise_dbm) {
		if (rssi_dbm - noise_dbm >= 40)
			return 100;
		else if (rssi_dbm < noise_dbm)
			return 0;
		sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;

	/* Else use just the signal level.
	 * This formula is a least squares fit of data points collected and
	 *   compared with a reference system that had a percentage (%) display
	 *   for signal quality. */
	} else
		sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
			    (15 * RSSI_RANGE + 62 * degradation)) /
			   (RSSI_RANGE * RSSI_RANGE);

	if (sig_qual > 100)
		sig_qual = 100;
	else if (sig_qual < 1)
		sig_qual = 0;

	return sig_qual;
}

/**
2086
 * iwl3945_rx_handle - Main entry function for receiving responses from uCode
Z
Zhu Yi 已提交
2087 2088 2089 2090 2091
 *
 * Uses the priv->rx_handlers callback function array to invoke
 * the appropriate handlers, including command responses,
 * frame-received notifications, and other notifications.
 */
2092
static void iwl3945_rx_handle(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2093
{
2094
	struct iwl_rx_mem_buffer *rxb;
2095
	struct iwl_rx_packet *pkt;
2096
	struct iwl_rx_queue *rxq = &priv->rxq;
Z
Zhu Yi 已提交
2097 2098 2099
	u32 r, i;
	int reclaim;
	unsigned long flags;
2100
	u8 fill_rx = 0;
M
Mohamed Abbas 已提交
2101
	u32 count = 8;
Z
Zhu Yi 已提交
2102

2103 2104
	/* uCode's read index (stored in shared DRAM) indicates the last Rx
	 * buffer that the driver may process (last buffer filled by ucode). */
W
Winkler, Tomas 已提交
2105
	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
Z
Zhu Yi 已提交
2106 2107
	i = rxq->read;

2108
	if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
2109
		fill_rx = 1;
Z
Zhu Yi 已提交
2110 2111
	/* Rx interrupt, but nothing sent from uCode */
	if (i == r)
2112
		IWL_DEBUG(priv, IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
Z
Zhu Yi 已提交
2113 2114 2115 2116

	while (i != r) {
		rxb = rxq->queue[i];

2117
		/* If an RXB doesn't have a Rx queue slot associated with it,
Z
Zhu Yi 已提交
2118 2119 2120 2121 2122 2123
		 * then a bug has been introduced in the queue refilling
		 * routines -- catch it here */
		BUG_ON(rxb == NULL);

		rxq->queue[i] = NULL;

2124
		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
2125
					    priv->hw_params.rx_buf_size,
Z
Zhu Yi 已提交
2126
					    PCI_DMA_FROMDEVICE);
2127
		pkt = (struct iwl_rx_packet *)rxb->skb->data;
Z
Zhu Yi 已提交
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140

		/* Reclaim a command buffer only if this packet is a response
		 *   to a (driver-originated) command.
		 * If the packet (e.g. Rx frame) originated from uCode,
		 *   there is no command buffer to reclaim.
		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
		 *   but apparently a few don't get set; catch them here. */
		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
			(pkt->hdr.cmd != REPLY_TX);

		/* Based on type of command response or notification,
		 *   handle those that need handling via function in
C
Christoph Hellwig 已提交
2141
		 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
Z
Zhu Yi 已提交
2142
		if (priv->rx_handlers[pkt->hdr.cmd]) {
2143
			IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
Z
Zhu Yi 已提交
2144 2145 2146 2147 2148
				"r = %d, i = %d, %s, 0x%02x\n", r, i,
				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
		} else {
			/* No handling needed */
2149
			IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
Z
Zhu Yi 已提交
2150 2151 2152 2153 2154 2155
				"r %d i %d No handler needed for %s, 0x%02x\n",
				r, i, get_cmd_string(pkt->hdr.cmd),
				pkt->hdr.cmd);
		}

		if (reclaim) {
2156
			/* Invoke any callbacks, transfer the skb to caller, and
2157
			 * fire off the (possibly) blocking iwl_send_cmd()
Z
Zhu Yi 已提交
2158 2159
			 * as we reclaim the driver command queue */
			if (rxb && rxb->skb)
C
Christoph Hellwig 已提交
2160
				iwl3945_tx_cmd_complete(priv, rxb);
Z
Zhu Yi 已提交
2161
			else
2162
				IWL_WARN(priv, "Claim null rxb?\n");
Z
Zhu Yi 已提交
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
		}

		/* For now we just don't re-use anything.  We can tweak this
		 * later to try and re-use notification packets and SKBs that
		 * fail to Rx correctly */
		if (rxb->skb != NULL) {
			priv->alloc_rxb_skb--;
			dev_kfree_skb_any(rxb->skb);
			rxb->skb = NULL;
		}

2174
		pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
2175 2176
				priv->hw_params.rx_buf_size,
				PCI_DMA_FROMDEVICE);
Z
Zhu Yi 已提交
2177 2178 2179 2180
		spin_lock_irqsave(&rxq->lock, flags);
		list_add_tail(&rxb->list, &priv->rxq.rx_used);
		spin_unlock_irqrestore(&rxq->lock, flags);
		i = (i + 1) & RX_QUEUE_MASK;
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
		/* If there are a lot of unused frames,
		 * restock the Rx queue so ucode won't assert. */
		if (fill_rx) {
			count++;
			if (count >= 8) {
				priv->rxq.read = i;
				__iwl3945_rx_replenish(priv);
				count = 0;
			}
		}
Z
Zhu Yi 已提交
2191 2192 2193 2194
	}

	/* Backtrack one entry */
	priv->rxq.read = i;
C
Christoph Hellwig 已提交
2195
	iwl3945_rx_queue_restock(priv);
Z
Zhu Yi 已提交
2196 2197
}

2198
static void iwl3945_enable_interrupts(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2199
{
2200
	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
Z
Zhu Yi 已提交
2201
	set_bit(STATUS_INT_ENABLED, &priv->status);
2202
	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
Z
Zhu Yi 已提交
2203 2204
}

2205 2206

/* call this function to flush any scheduled tasklet */
2207
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
2208
{
T
Tomas Winkler 已提交
2209
	/* wait to make sure we flush pending tasklet*/
2210 2211 2212 2213 2214
	synchronize_irq(priv->pci_dev->irq);
	tasklet_kill(&priv->irq_tasklet);
}


2215
static inline void iwl3945_disable_interrupts(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2216 2217 2218 2219
{
	clear_bit(STATUS_INT_ENABLED, &priv->status);

	/* disable interrupts from uCode/NIC to host */
2220
	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
Z
Zhu Yi 已提交
2221 2222 2223

	/* acknowledge/clear/reset any interrupts still pending
	 * from uCode or flow handler (Rx/Tx DMA) */
2224 2225
	iwl_write32(priv, CSR_INT, 0xffffffff);
	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
2226
	IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
Z
Zhu Yi 已提交
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251
}

static const char *desc_lookup(int i)
{
	switch (i) {
	case 1:
		return "FAIL";
	case 2:
		return "BAD_PARAM";
	case 3:
		return "BAD_CHECKSUM";
	case 4:
		return "NMI_INTERRUPT";
	case 5:
		return "SYSASSERT";
	case 6:
		return "FATAL_ERROR";
	}

	return "UNKNOWN";
}

#define ERROR_START_OFFSET  (1 * sizeof(u32))
#define ERROR_ELEM_SIZE     (7 * sizeof(u32))

2252
static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2253 2254 2255 2256 2257 2258 2259 2260
{
	u32 i;
	u32 desc, time, count, base, data1;
	u32 blink1, blink2, ilink1, ilink2;
	int rc;

	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);

C
Christoph Hellwig 已提交
2261
	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
2262
		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
Z
Zhu Yi 已提交
2263 2264 2265
		return;
	}

2266
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
2267
	if (rc) {
2268
		IWL_WARN(priv, "Can not read from adapter at this time.\n");
Z
Zhu Yi 已提交
2269 2270 2271
		return;
	}

2272
	count = iwl_read_targ_mem(priv, base);
Z
Zhu Yi 已提交
2273 2274

	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
2275 2276 2277
		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
			priv->status, count);
Z
Zhu Yi 已提交
2278 2279
	}

2280
	IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
Z
Zhu Yi 已提交
2281 2282 2283 2284
		  "ilink1  nmiPC   Line\n");
	for (i = ERROR_START_OFFSET;
	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
	     i += ERROR_ELEM_SIZE) {
2285
		desc = iwl_read_targ_mem(priv, base + i);
Z
Zhu Yi 已提交
2286
		time =
2287
		    iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32));
Z
Zhu Yi 已提交
2288
		blink1 =
2289
		    iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32));
Z
Zhu Yi 已提交
2290
		blink2 =
2291
		    iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32));
Z
Zhu Yi 已提交
2292
		ilink1 =
2293
		    iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32));
Z
Zhu Yi 已提交
2294
		ilink2 =
2295
		    iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32));
Z
Zhu Yi 已提交
2296
		data1 =
2297
		    iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
Z
Zhu Yi 已提交
2298

2299 2300 2301 2302
		IWL_ERR(priv,
			"%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
			desc_lookup(desc), desc, time, blink1, blink2,
			ilink1, ilink2, data1);
Z
Zhu Yi 已提交
2303 2304
	}

2305
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2306 2307 2308

}

2309
#define EVENT_START_OFFSET  (6 * sizeof(u32))
Z
Zhu Yi 已提交
2310 2311

/**
C
Christoph Hellwig 已提交
2312
 * iwl3945_print_event_log - Dump error event log to syslog
Z
Zhu Yi 已提交
2313
 *
2314
 * NOTE: Must be called with iwl_grab_nic_access() already obtained!
Z
Zhu Yi 已提交
2315
 */
2316
static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
Z
Zhu Yi 已提交
2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
				u32 num_events, u32 mode)
{
	u32 i;
	u32 base;       /* SRAM byte address of event log header */
	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
	u32 ptr;        /* SRAM byte address of log data */
	u32 ev, time, data; /* event log data */

	if (num_events == 0)
		return;

	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);

	if (mode == 0)
		event_size = 2 * sizeof(u32);
	else
		event_size = 3 * sizeof(u32);

	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);

	/* "time" is actually "data" for mode 0 (no timestamp).
	 * place event id # at far right for easier visual parsing. */
	for (i = 0; i < num_events; i++) {
2340
		ev = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
2341
		ptr += sizeof(u32);
2342
		time = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
2343
		ptr += sizeof(u32);
2344 2345 2346 2347
		if (mode == 0) {
			/* data, ev */
			IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
		} else {
2348
			data = iwl_read_targ_mem(priv, ptr);
Z
Zhu Yi 已提交
2349
			ptr += sizeof(u32);
2350
			IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
Z
Zhu Yi 已提交
2351 2352 2353 2354
		}
	}
}

2355
static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2356 2357 2358 2359 2360 2361 2362 2363 2364 2365
{
	int rc;
	u32 base;       /* SRAM byte address of event log header */
	u32 capacity;   /* event log capacity in # entries */
	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
	u32 num_wraps;  /* # times uCode wrapped to top of log */
	u32 next_entry; /* index of next entry to be written by uCode */
	u32 size;       /* # entries that we'll print */

	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
C
Christoph Hellwig 已提交
2366
	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
2367
		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
Z
Zhu Yi 已提交
2368 2369 2370
		return;
	}

2371
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
2372
	if (rc) {
2373
		IWL_WARN(priv, "Can not read from adapter at this time.\n");
Z
Zhu Yi 已提交
2374 2375 2376 2377
		return;
	}

	/* event log header */
2378 2379 2380 2381
	capacity = iwl_read_targ_mem(priv, base);
	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
Z
Zhu Yi 已提交
2382 2383 2384 2385 2386

	size = num_wraps ? capacity : next_entry;

	/* bail out if nothing in log */
	if (size == 0) {
2387
		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
2388
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2389 2390 2391
		return;
	}

2392
	IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
Z
Zhu Yi 已提交
2393 2394 2395 2396 2397
		  size, num_wraps);

	/* if uCode has wrapped back to top of log, start at the oldest entry,
	 * i.e the next one that uCode would fill. */
	if (num_wraps)
C
Christoph Hellwig 已提交
2398
		iwl3945_print_event_log(priv, next_entry,
Z
Zhu Yi 已提交
2399 2400 2401
				    capacity - next_entry, mode);

	/* (then/else) start at top of log */
C
Christoph Hellwig 已提交
2402
	iwl3945_print_event_log(priv, 0, next_entry, mode);
Z
Zhu Yi 已提交
2403

2404
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2405 2406
}

2407
static void iwl3945_error_recovery(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2408 2409 2410
{
	unsigned long flags;

2411 2412 2413
	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
	       sizeof(priv->staging_rxon));
	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
2414
	iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
2415

C
Christoph Hellwig 已提交
2416
	iwl3945_add_station(priv, priv->bssid, 1, 0);
Z
Zhu Yi 已提交
2417 2418

	spin_lock_irqsave(&priv->lock, flags);
2419
	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
Z
Zhu Yi 已提交
2420 2421 2422 2423
	priv->error_recovering = 0;
	spin_unlock_irqrestore(&priv->lock, flags);
}

2424
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2425 2426 2427 2428
{
	u32 inta, handled = 0;
	u32 inta_fh;
	unsigned long flags;
S
Samuel Ortiz 已提交
2429
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
2430 2431 2432 2433 2434 2435 2436 2437
	u32 inta_mask;
#endif

	spin_lock_irqsave(&priv->lock, flags);

	/* Ack/clear/reset pending uCode interrupts.
	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
2438 2439
	inta = iwl_read32(priv, CSR_INT);
	iwl_write32(priv, CSR_INT, inta);
Z
Zhu Yi 已提交
2440 2441 2442 2443

	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
	 * Any new interrupts that happen after this, either while we're
	 * in this tasklet, or later, will show up in next ISR/tasklet. */
2444 2445
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
Z
Zhu Yi 已提交
2446

S
Samuel Ortiz 已提交
2447
#ifdef CONFIG_IWLWIFI_DEBUG
2448
	if (priv->debug_level & IWL_DL_ISR) {
2449
		/* just for debug */
2450
		inta_mask = iwl_read32(priv, CSR_INT_MASK);
2451
		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
Z
Zhu Yi 已提交
2452 2453 2454 2455 2456 2457 2458 2459
			      inta, inta_mask, inta_fh);
	}
#endif

	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
	 * atomic, make sure that inta covers all the interrupts that
	 * we've discovered, even if FH interrupt came in just after
	 * reading CSR_INT. */
T
Tomas Winkler 已提交
2460
	if (inta_fh & CSR39_FH_INT_RX_MASK)
Z
Zhu Yi 已提交
2461
		inta |= CSR_INT_BIT_FH_RX;
T
Tomas Winkler 已提交
2462
	if (inta_fh & CSR39_FH_INT_TX_MASK)
Z
Zhu Yi 已提交
2463 2464 2465 2466
		inta |= CSR_INT_BIT_FH_TX;

	/* Now service all interrupt bits discovered above. */
	if (inta & CSR_INT_BIT_HW_ERR) {
2467
		IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
Z
Zhu Yi 已提交
2468 2469

		/* Tell the device to stop sending interrupts */
C
Christoph Hellwig 已提交
2470
		iwl3945_disable_interrupts(priv);
Z
Zhu Yi 已提交
2471

2472
		iwl_irq_handle_error(priv);
Z
Zhu Yi 已提交
2473 2474 2475 2476 2477 2478 2479 2480

		handled |= CSR_INT_BIT_HW_ERR;

		spin_unlock_irqrestore(&priv->lock, flags);

		return;
	}

S
Samuel Ortiz 已提交
2481
#ifdef CONFIG_IWLWIFI_DEBUG
2482
	if (priv->debug_level & (IWL_DL_ISR)) {
Z
Zhu Yi 已提交
2483
		/* NIC fires this, but we don't use it, redundant with WAKEUP */
2484
		if (inta & CSR_INT_BIT_SCD)
2485
			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
2486
				      "the frame/frames.\n");
Z
Zhu Yi 已提交
2487 2488 2489

		/* Alive notification via Rx interrupt will do the real work */
		if (inta & CSR_INT_BIT_ALIVE)
2490
			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
Z
Zhu Yi 已提交
2491 2492 2493
	}
#endif
	/* Safely ignore these bits for debug checks below */
2494
	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
Z
Zhu Yi 已提交
2495 2496 2497

	/* Error detected by uCode */
	if (inta & CSR_INT_BIT_SW_ERR) {
2498 2499
		IWL_ERR(priv, "Microcode SW error detected. "
			"Restarting 0x%X.\n", inta);
2500
		iwl_irq_handle_error(priv);
Z
Zhu Yi 已提交
2501 2502 2503 2504 2505
		handled |= CSR_INT_BIT_SW_ERR;
	}

	/* uCode wakes up after power-down sleep */
	if (inta & CSR_INT_BIT_WAKEUP) {
2506
		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
2507
		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
2508 2509 2510 2511 2512 2513
		iwl_txq_update_write_ptr(priv, &priv->txq[0]);
		iwl_txq_update_write_ptr(priv, &priv->txq[1]);
		iwl_txq_update_write_ptr(priv, &priv->txq[2]);
		iwl_txq_update_write_ptr(priv, &priv->txq[3]);
		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
Z
Zhu Yi 已提交
2514 2515 2516 2517 2518 2519 2520 2521

		handled |= CSR_INT_BIT_WAKEUP;
	}

	/* All uCode command responses, including Tx command responses,
	 * Rx "responses" (frame-received notification), and other
	 * notifications from uCode come through here*/
	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
C
Christoph Hellwig 已提交
2522
		iwl3945_rx_handle(priv);
Z
Zhu Yi 已提交
2523 2524 2525 2526
		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
	}

	if (inta & CSR_INT_BIT_FH_TX) {
2527
		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
Z
Zhu Yi 已提交
2528

2529 2530 2531
		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
		if (!iwl_grab_nic_access(priv)) {
			iwl_write_direct32(priv, FH39_TCSR_CREDIT
2532
					     (FH39_SRVC_CHNL), 0x0);
2533
			iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2534 2535 2536 2537 2538
		}
		handled |= CSR_INT_BIT_FH_TX;
	}

	if (inta & ~handled)
2539
		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
Z
Zhu Yi 已提交
2540 2541

	if (inta & ~CSR_INI_SET_MASK) {
2542
		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
Z
Zhu Yi 已提交
2543
			 inta & ~CSR_INI_SET_MASK);
2544
		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
Z
Zhu Yi 已提交
2545 2546 2547
	}

	/* Re-enable all interrupts */
2548 2549 2550
	/* only Re-enable if disabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
		iwl3945_enable_interrupts(priv);
Z
Zhu Yi 已提交
2551

S
Samuel Ortiz 已提交
2552
#ifdef CONFIG_IWLWIFI_DEBUG
2553
	if (priv->debug_level & (IWL_DL_ISR)) {
2554 2555 2556
		inta = iwl_read32(priv, CSR_INT);
		inta_mask = iwl_read32(priv, CSR_INT_MASK);
		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
2557
		IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
Z
Zhu Yi 已提交
2558 2559 2560 2561 2562 2563
			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
	}
#endif
	spin_unlock_irqrestore(&priv->lock, flags);
}

C
Christoph Hellwig 已提交
2564
static irqreturn_t iwl3945_isr(int irq, void *data)
Z
Zhu Yi 已提交
2565
{
2566
	struct iwl_priv *priv = data;
Z
Zhu Yi 已提交
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577
	u32 inta, inta_mask;
	u32 inta_fh;
	if (!priv)
		return IRQ_NONE;

	spin_lock(&priv->lock);

	/* Disable (but don't clear!) interrupts here to avoid
	 *    back-to-back ISRs and sporadic interrupts from our NIC.
	 * If we have something to service, the tasklet will re-enable ints.
	 * If we *don't* have something, we'll re-enable before leaving here. */
2578 2579
	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
Z
Zhu Yi 已提交
2580 2581

	/* Discover which interrupts are active/pending */
2582 2583
	inta = iwl_read32(priv, CSR_INT);
	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
Z
Zhu Yi 已提交
2584 2585 2586 2587 2588

	/* Ignore interrupt if there's nothing in NIC to service.
	 * This may be due to IRQ shared with another device,
	 * or due to sporadic interrupts thrown from our NIC. */
	if (!inta && !inta_fh) {
2589
		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
Z
Zhu Yi 已提交
2590 2591 2592 2593 2594
		goto none;
	}

	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
		/* Hardware disappeared */
2595
		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
2596
		goto unplugged;
Z
Zhu Yi 已提交
2597 2598
	}

2599
	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
Z
Zhu Yi 已提交
2600 2601
		      inta, inta_mask, inta_fh);

2602 2603
	inta &= ~CSR_INT_BIT_SCD;

C
Christoph Hellwig 已提交
2604
	/* iwl3945_irq_tasklet() will service interrupts and re-enable them */
2605 2606
	if (likely(inta || inta_fh))
		tasklet_schedule(&priv->irq_tasklet);
2607
unplugged:
Z
Zhu Yi 已提交
2608 2609 2610 2611 2612 2613
	spin_unlock(&priv->lock);

	return IRQ_HANDLED;

 none:
	/* re-enable interrupts here since we don't have anything to service. */
2614 2615 2616
	/* only Re-enable if disabled by irq */
	if (test_bit(STATUS_INT_ENABLED, &priv->status))
		iwl3945_enable_interrupts(priv);
Z
Zhu Yi 已提交
2617 2618 2619 2620
	spin_unlock(&priv->lock);
	return IRQ_NONE;
}

2621
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
2622
					 enum ieee80211_band band,
2623
				     u8 is_active, u8 n_probes,
C
Christoph Hellwig 已提交
2624
				     struct iwl3945_scan_channel *scan_ch)
Z
Zhu Yi 已提交
2625 2626
{
	const struct ieee80211_channel *channels = NULL;
2627
	const struct ieee80211_supported_band *sband;
2628
	const struct iwl_channel_info *ch_info;
Z
Zhu Yi 已提交
2629 2630 2631 2632
	u16 passive_dwell = 0;
	u16 active_dwell = 0;
	int added, i;

K
Kolekar, Abhijeet 已提交
2633
	sband = iwl_get_hw_mode(priv, band);
2634
	if (!sband)
Z
Zhu Yi 已提交
2635 2636
		return 0;

2637
	channels = sband->channels;
Z
Zhu Yi 已提交
2638

S
Samuel Ortiz 已提交
2639 2640
	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
	passive_dwell = iwl_get_passive_dwell_time(priv, band);
Z
Zhu Yi 已提交
2641

2642 2643 2644
	if (passive_dwell <= active_dwell)
		passive_dwell = active_dwell + 1;

2645
	for (i = 0, added = 0; i < sband->n_channels; i++) {
2646 2647 2648
		if (channels[i].flags & IEEE80211_CHAN_DISABLED)
			continue;

2649
		scan_ch->channel = channels[i].hw_value;
Z
Zhu Yi 已提交
2650

2651
		ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
Z
Zhu Yi 已提交
2652
		if (!is_channel_valid(ch_info)) {
2653
			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
Z
Zhu Yi 已提交
2654 2655 2656 2657
				       scan_ch->channel);
			continue;
		}

2658 2659 2660 2661 2662
		scan_ch->active_dwell = cpu_to_le16(active_dwell);
		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
		/* If passive , set up for auto-switch
		 *  and use long active_dwell time.
		 */
Z
Zhu Yi 已提交
2663
		if (!is_active || is_channel_passive(ch_info) ||
2664
		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
Z
Zhu Yi 已提交
2665
			scan_ch->type = 0;	/* passive */
2666 2667 2668
			if (IWL_UCODE_API(priv->ucode_ver) == 1)
				scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
		} else {
Z
Zhu Yi 已提交
2669
			scan_ch->type = 1;	/* active */
2670
		}
Z
Zhu Yi 已提交
2671

2672 2673 2674 2675 2676 2677
		/* Set direct probe bits. These may be used both for active
		 * scan channels (probes gets sent right away),
		 * or for passive channels (probes get se sent only after
		 * hearing clear Rx packet).*/
		if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
			if (n_probes)
2678
				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
2679 2680 2681 2682
		} else {
			/* uCode v1 does not allow setting direct probe bits on
			 * passive channel. */
			if ((scan_ch->type & 1) && n_probes)
2683
				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
2684
		}
Z
Zhu Yi 已提交
2685

2686
		/* Set txpower levels to defaults */
Z
Zhu Yi 已提交
2687 2688 2689 2690
		scan_ch->tpc.dsp_atten = 110;
		/* scan_pwr_info->tpc.dsp_atten; */

		/*scan_pwr_info->tpc.tx_gain; */
2691
		if (band == IEEE80211_BAND_5GHZ)
Z
Zhu Yi 已提交
2692 2693 2694 2695
			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
		else {
			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
2696
			 * power level:
2697
			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
Z
Zhu Yi 已提交
2698 2699 2700
			 */
		}

2701
		IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n",
Z
Zhu Yi 已提交
2702 2703 2704 2705 2706 2707 2708 2709 2710
			       scan_ch->channel,
			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
			       (scan_ch->type & 1) ?
			       active_dwell : passive_dwell);

		scan_ch++;
		added++;
	}

2711
	IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added);
Z
Zhu Yi 已提交
2712 2713 2714
	return added;
}

2715
static void iwl3945_init_hw_rates(struct iwl_priv *priv,
Z
Zhu Yi 已提交
2716 2717 2718 2719 2720
			      struct ieee80211_rate *rates)
{
	int i;

	for (i = 0; i < IWL_RATE_COUNT; i++) {
2721 2722 2723 2724
		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
		rates[i].hw_value = i; /* Rate scaling will work on indexes */
		rates[i].hw_value_short = i;
		rates[i].flags = 0;
2725
		if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
Z
Zhu Yi 已提交
2726
			/*
2727
			 * If CCK != 1M then set short preamble rate flag.
Z
Zhu Yi 已提交
2728
			 */
C
Christoph Hellwig 已提交
2729
			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
2730
				0 : IEEE80211_RATE_SHORT_PREAMBLE;
Z
Zhu Yi 已提交
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740
		}
	}
}

/******************************************************************************
 *
 * uCode download functions
 *
 ******************************************************************************/

2741
static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2742
{
2743 2744 2745 2746 2747 2748
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
Z
Zhu Yi 已提交
2749 2750 2751
}

/**
C
Christoph Hellwig 已提交
2752
 * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
Z
Zhu Yi 已提交
2753 2754
 *     looking at all data.
 */
2755
static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
Z
Zhu Yi 已提交
2756 2757 2758 2759 2760 2761
{
	u32 val;
	u32 save_len = len;
	int rc = 0;
	u32 errcnt;

2762
	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
Z
Zhu Yi 已提交
2763

2764
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
2765 2766 2767
	if (rc)
		return rc;

2768
	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
2769
			       IWL39_RTC_INST_LOWER_BOUND);
Z
Zhu Yi 已提交
2770 2771 2772 2773 2774 2775

	errcnt = 0;
	for (; len > 0; len -= sizeof(u32), image++) {
		/* read data comes through single port, auto-incr addr */
		/* NOTE: Use the debugless read so we don't flood kernel log
		 * if IWL_DL_IO is set */
2776
		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
Z
Zhu Yi 已提交
2777
		if (val != le32_to_cpu(*image)) {
2778
			IWL_ERR(priv, "uCode INST section is invalid at "
Z
Zhu Yi 已提交
2779 2780 2781 2782 2783 2784 2785 2786 2787
				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
				  save_len - len, val, le32_to_cpu(*image));
			rc = -EIO;
			errcnt++;
			if (errcnt >= 20)
				break;
		}
	}

2788
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2789 2790

	if (!errcnt)
2791 2792
		IWL_DEBUG_INFO(priv,
			"ucode image in INSTRUCTION memory is good\n");
Z
Zhu Yi 已提交
2793 2794 2795 2796 2797 2798

	return rc;
}


/**
C
Christoph Hellwig 已提交
2799
 * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
Z
Zhu Yi 已提交
2800 2801 2802
 *   using sample data 100 bytes apart.  If these sample points are good,
 *   it's a pretty good bet that everything between them is good, too.
 */
2803
static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
Z
Zhu Yi 已提交
2804 2805 2806 2807 2808 2809
{
	u32 val;
	int rc = 0;
	u32 errcnt = 0;
	u32 i;

2810
	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
Z
Zhu Yi 已提交
2811

2812
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
2813 2814 2815 2816 2817 2818 2819
	if (rc)
		return rc;

	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
		/* read data comes through single port, auto-incr addr */
		/* NOTE: Use the debugless read so we don't flood kernel log
		 * if IWL_DL_IO is set */
2820
		iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
2821
			i + IWL39_RTC_INST_LOWER_BOUND);
2822
		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
Z
Zhu Yi 已提交
2823 2824
		if (val != le32_to_cpu(*image)) {
#if 0 /* Enable this if you want to see details */
2825
			IWL_ERR(priv, "uCode INST section is invalid at "
Z
Zhu Yi 已提交
2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
				  i, val, *image);
#endif
			rc = -EIO;
			errcnt++;
			if (errcnt >= 3)
				break;
		}
	}

2836
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
2837 2838 2839 2840 2841 2842

	return rc;
}


/**
C
Christoph Hellwig 已提交
2843
 * iwl3945_verify_ucode - determine which instruction image is in SRAM,
Z
Zhu Yi 已提交
2844 2845
 *    and verify its contents
 */
2846
static int iwl3945_verify_ucode(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2847 2848 2849 2850 2851 2852 2853 2854
{
	__le32 *image;
	u32 len;
	int rc = 0;

	/* Try bootstrap */
	image = (__le32 *)priv->ucode_boot.v_addr;
	len = priv->ucode_boot.len;
C
Christoph Hellwig 已提交
2855
	rc = iwl3945_verify_inst_sparse(priv, image, len);
Z
Zhu Yi 已提交
2856
	if (rc == 0) {
2857
		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
Z
Zhu Yi 已提交
2858 2859 2860 2861 2862 2863
		return 0;
	}

	/* Try initialize */
	image = (__le32 *)priv->ucode_init.v_addr;
	len = priv->ucode_init.len;
C
Christoph Hellwig 已提交
2864
	rc = iwl3945_verify_inst_sparse(priv, image, len);
Z
Zhu Yi 已提交
2865
	if (rc == 0) {
2866
		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
Z
Zhu Yi 已提交
2867 2868 2869 2870 2871 2872
		return 0;
	}

	/* Try runtime/protocol */
	image = (__le32 *)priv->ucode_code.v_addr;
	len = priv->ucode_code.len;
C
Christoph Hellwig 已提交
2873
	rc = iwl3945_verify_inst_sparse(priv, image, len);
Z
Zhu Yi 已提交
2874
	if (rc == 0) {
2875
		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
Z
Zhu Yi 已提交
2876 2877 2878
		return 0;
	}

2879
	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
Z
Zhu Yi 已提交
2880

2881 2882 2883
	/* Since nothing seems to match, show first several data entries in
	 * instruction SRAM, so maybe visual inspection will give a clue.
	 * Selection of bootstrap image (vs. other images) is arbitrary. */
Z
Zhu Yi 已提交
2884 2885
	image = (__le32 *)priv->ucode_boot.v_addr;
	len = priv->ucode_boot.len;
C
Christoph Hellwig 已提交
2886
	rc = iwl3945_verify_inst_full(priv, image, len);
Z
Zhu Yi 已提交
2887 2888 2889 2890

	return rc;
}

2891
static void iwl3945_nic_start(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2892 2893
{
	/* Remove all resets to allow NIC to operate */
2894
	iwl_write32(priv, CSR_RESET, 0);
Z
Zhu Yi 已提交
2895 2896 2897
}

/**
C
Christoph Hellwig 已提交
2898
 * iwl3945_read_ucode - Read uCode images from disk file.
Z
Zhu Yi 已提交
2899 2900 2901
 *
 * Copy into buffers for card to fetch via bus-mastering
 */
2902
static int iwl3945_read_ucode(struct iwl_priv *priv)
Z
Zhu Yi 已提交
2903
{
2904
	struct iwl_ucode *ucode;
2905
	int ret = -EINVAL, index;
Z
Zhu Yi 已提交
2906 2907
	const struct firmware *ucode_raw;
	/* firmware file name contains uCode/driver compatibility version */
2908 2909 2910 2911
	const char *name_pre = priv->cfg->fw_name_pre;
	const unsigned int api_max = priv->cfg->ucode_api_max;
	const unsigned int api_min = priv->cfg->ucode_api_min;
	char buf[25];
Z
Zhu Yi 已提交
2912 2913
	u8 *src;
	size_t len;
2914
	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
Z
Zhu Yi 已提交
2915 2916 2917

	/* Ask kernel firmware_class module to get the boot firmware off disk.
	 * request_firmware() is synchronous, file is in memory on return. */
2918 2919 2920 2921
	for (index = api_max; index >= api_min; index--) {
		sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
		ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
		if (ret < 0) {
2922
			IWL_ERR(priv, "%s firmware file req failed: %d\n",
2923 2924 2925 2926 2927 2928 2929
				  buf, ret);
			if (ret == -ENOENT)
				continue;
			else
				goto error;
		} else {
			if (index < api_max)
2930 2931 2932
				IWL_ERR(priv, "Loaded firmware %s, "
					"which is deprecated. "
					" Please use API v%u instead.\n",
2933
					  buf, api_max);
2934 2935
			IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
				       "(%zd bytes) from disk\n",
2936 2937 2938
				       buf, ucode_raw->size);
			break;
		}
Z
Zhu Yi 已提交
2939 2940
	}

2941 2942
	if (ret < 0)
		goto error;
Z
Zhu Yi 已提交
2943 2944 2945

	/* Make sure that we got at least our header! */
	if (ucode_raw->size < sizeof(*ucode)) {
2946
		IWL_ERR(priv, "File size way too small!\n");
2947
		ret = -EINVAL;
Z
Zhu Yi 已提交
2948 2949 2950 2951 2952 2953
		goto err_release;
	}

	/* Data from ucode file:  header followed by uCode images */
	ucode = (void *)ucode_raw->data;

2954
	priv->ucode_ver = le32_to_cpu(ucode->ver);
2955
	api_ver = IWL_UCODE_API(priv->ucode_ver);
Z
Zhu Yi 已提交
2956 2957 2958 2959 2960 2961
	inst_size = le32_to_cpu(ucode->inst_size);
	data_size = le32_to_cpu(ucode->data_size);
	init_size = le32_to_cpu(ucode->init_size);
	init_data_size = le32_to_cpu(ucode->init_data_size);
	boot_size = le32_to_cpu(ucode->boot_size);

2962 2963 2964 2965 2966
	/* api_ver should match the api version forming part of the
	 * firmware filename ... but we don't check for that and only rely
	 * on the API version read from firware header from here on forward */

	if (api_ver < api_min || api_ver > api_max) {
2967
		IWL_ERR(priv, "Driver unable to support your firmware API. "
2968 2969 2970 2971 2972 2973 2974
			  "Driver supports v%u, firmware is v%u.\n",
			  api_max, api_ver);
		priv->ucode_ver = 0;
		ret = -EINVAL;
		goto err_release;
	}
	if (api_ver != api_max)
2975
		IWL_ERR(priv, "Firmware has old API version. Expected %u, "
2976 2977 2978 2979
			  "got %u. New firmware can be obtained "
			  "from http://www.intellinuxwireless.org.\n",
			  api_max, api_ver);

T
Tomas Winkler 已提交
2980 2981 2982 2983 2984 2985
	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
		IWL_UCODE_MAJOR(priv->ucode_ver),
		IWL_UCODE_MINOR(priv->ucode_ver),
		IWL_UCODE_API(priv->ucode_ver),
		IWL_UCODE_SERIAL(priv->ucode_ver));

2986
	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
2987
		       priv->ucode_ver);
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997
	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
		       inst_size);
	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
		       data_size);
	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
		       init_size);
	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
		       init_data_size);
	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
		       boot_size);
Z
Zhu Yi 已提交
2998

2999

Z
Zhu Yi 已提交
3000 3001 3002 3003 3004
	/* Verify size of file vs. image size info in file's header */
	if (ucode_raw->size < sizeof(*ucode) +
		inst_size + data_size + init_size +
		init_data_size + boot_size) {

3005 3006
		IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
			       ucode_raw->size);
3007
		ret = -EINVAL;
Z
Zhu Yi 已提交
3008 3009 3010 3011
		goto err_release;
	}

	/* Verify that uCode images will fit in card's SRAM */
3012
	if (inst_size > IWL39_MAX_INST_SIZE) {
3013
		IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
3014 3015
			       inst_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3016 3017 3018
		goto err_release;
	}

3019
	if (data_size > IWL39_MAX_DATA_SIZE) {
3020
		IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
3021 3022
			       data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3023 3024
		goto err_release;
	}
3025
	if (init_size > IWL39_MAX_INST_SIZE) {
3026 3027
		IWL_DEBUG_INFO(priv,
				"uCode init instr len %d too large to fit in\n",
3028 3029
				init_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3030 3031
		goto err_release;
	}
3032
	if (init_data_size > IWL39_MAX_DATA_SIZE) {
3033 3034
		IWL_DEBUG_INFO(priv,
				"uCode init data len %d too large to fit in\n",
3035 3036
				init_data_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3037 3038
		goto err_release;
	}
3039
	if (boot_size > IWL39_MAX_BSM_SIZE) {
3040 3041
		IWL_DEBUG_INFO(priv,
				"uCode boot instr len %d too large to fit in\n",
3042 3043
				boot_size);
		ret = -EINVAL;
Z
Zhu Yi 已提交
3044 3045 3046 3047 3048 3049 3050 3051 3052
		goto err_release;
	}

	/* Allocate ucode buffers for card's bus-master loading ... */

	/* Runtime instructions and 2 copies of data:
	 * 1) unmodified from disk
	 * 2) backup cache for save/restore during power-downs */
	priv->ucode_code.len = inst_size;
3053
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
Z
Zhu Yi 已提交
3054 3055

	priv->ucode_data.len = data_size;
3056
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
Z
Zhu Yi 已提交
3057 3058

	priv->ucode_data_backup.len = data_size;
3059
	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
Z
Zhu Yi 已提交
3060

3061 3062 3063
	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
	    !priv->ucode_data_backup.v_addr)
		goto err_pci_alloc;
Z
Zhu Yi 已提交
3064 3065

	/* Initialization instructions and data */
3066 3067
	if (init_size && init_data_size) {
		priv->ucode_init.len = init_size;
3068
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
3069 3070

		priv->ucode_init_data.len = init_data_size;
3071
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
3072 3073 3074 3075

		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
			goto err_pci_alloc;
	}
Z
Zhu Yi 已提交
3076 3077

	/* Bootstrap (instructions only, no data) */
3078 3079
	if (boot_size) {
		priv->ucode_boot.len = boot_size;
3080
		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
Z
Zhu Yi 已提交
3081

3082 3083 3084
		if (!priv->ucode_boot.v_addr)
			goto err_pci_alloc;
	}
Z
Zhu Yi 已提交
3085 3086 3087 3088 3089 3090

	/* Copy images into buffers for card's bus-master reads ... */

	/* Runtime instructions (first block of data in file) */
	src = &ucode->data[0];
	len = priv->ucode_code.len;
3091 3092
	IWL_DEBUG_INFO(priv,
		"Copying (but not loading) uCode instr len %zd\n", len);
Z
Zhu Yi 已提交
3093
	memcpy(priv->ucode_code.v_addr, src, len);
3094
	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
Z
Zhu Yi 已提交
3095 3096 3097
		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);

	/* Runtime data (2nd block)
C
Christoph Hellwig 已提交
3098
	 * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
Z
Zhu Yi 已提交
3099 3100
	src = &ucode->data[inst_size];
	len = priv->ucode_data.len;
3101 3102
	IWL_DEBUG_INFO(priv,
		"Copying (but not loading) uCode data len %zd\n", len);
Z
Zhu Yi 已提交
3103 3104 3105 3106 3107 3108 3109
	memcpy(priv->ucode_data.v_addr, src, len);
	memcpy(priv->ucode_data_backup.v_addr, src, len);

	/* Initialization instructions (3rd block) */
	if (init_size) {
		src = &ucode->data[inst_size + data_size];
		len = priv->ucode_init.len;
3110 3111
		IWL_DEBUG_INFO(priv,
			"Copying (but not loading) init instr len %zd\n", len);
Z
Zhu Yi 已提交
3112 3113 3114 3115 3116 3117 3118
		memcpy(priv->ucode_init.v_addr, src, len);
	}

	/* Initialization data (4th block) */
	if (init_data_size) {
		src = &ucode->data[inst_size + data_size + init_size];
		len = priv->ucode_init_data.len;
3119 3120
		IWL_DEBUG_INFO(priv,
			"Copying (but not loading) init data len %zd\n", len);
Z
Zhu Yi 已提交
3121 3122 3123 3124 3125 3126
		memcpy(priv->ucode_init_data.v_addr, src, len);
	}

	/* Bootstrap instructions (5th block) */
	src = &ucode->data[inst_size + data_size + init_size + init_data_size];
	len = priv->ucode_boot.len;
3127 3128
	IWL_DEBUG_INFO(priv,
		"Copying (but not loading) boot instr len %zd\n", len);
Z
Zhu Yi 已提交
3129 3130 3131 3132 3133 3134 3135
	memcpy(priv->ucode_boot.v_addr, src, len);

	/* We have our copies now, allow OS release its copies */
	release_firmware(ucode_raw);
	return 0;

 err_pci_alloc:
3136
	IWL_ERR(priv, "failed to allocate pci memory\n");
3137
	ret = -ENOMEM;
C
Christoph Hellwig 已提交
3138
	iwl3945_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
3139 3140 3141 3142 3143

 err_release:
	release_firmware(ucode_raw);

 error:
3144
	return ret;
Z
Zhu Yi 已提交
3145 3146 3147 3148
}


/**
C
Christoph Hellwig 已提交
3149
 * iwl3945_set_ucode_ptrs - Set uCode address location
Z
Zhu Yi 已提交
3150 3151 3152 3153 3154 3155 3156
 *
 * Tell initialization uCode where to find runtime uCode.
 *
 * BSM registers initially contain pointers to initialization uCode.
 * We need to replace them to load runtime uCode inst and data,
 * and to save runtime data when powering down.
 */
3157
static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168
{
	dma_addr_t pinst;
	dma_addr_t pdata;
	int rc = 0;
	unsigned long flags;

	/* bits 31:0 for 3945 */
	pinst = priv->ucode_code.p_addr;
	pdata = priv->ucode_data_backup.p_addr;

	spin_lock_irqsave(&priv->lock, flags);
3169
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
3170 3171 3172 3173 3174 3175
	if (rc) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return rc;
	}

	/* Tell bootstrap uCode where to find image to load */
3176 3177 3178
	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
Z
Zhu Yi 已提交
3179 3180
				 priv->ucode_data.len);

T
Tomas Winkler 已提交
3181
	/* Inst byte count must be last to set up, bit 31 signals uCode
Z
Zhu Yi 已提交
3182
	 *   that all new ptr/size info is in place */
3183
	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
Z
Zhu Yi 已提交
3184 3185
				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);

3186
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3187 3188 3189

	spin_unlock_irqrestore(&priv->lock, flags);

3190
	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
Z
Zhu Yi 已提交
3191 3192 3193 3194 3195

	return rc;
}

/**
C
Christoph Hellwig 已提交
3196
 * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
Z
Zhu Yi 已提交
3197 3198 3199 3200
 *
 * Called after REPLY_ALIVE notification received from "initialize" uCode.
 *
 * Tell "initialize" uCode to go ahead and load the runtime uCode.
3201
 */
3202
static void iwl3945_init_alive_start(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3203 3204 3205 3206 3207
{
	/* 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 */
3208
		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
Z
Zhu Yi 已提交
3209 3210 3211 3212 3213 3214
		goto restart;
	}

	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
	 * This is a paranoid check, because we would not have gotten the
	 * "initialize" alive if code weren't properly loaded.  */
C
Christoph Hellwig 已提交
3215
	if (iwl3945_verify_ucode(priv)) {
Z
Zhu Yi 已提交
3216 3217
		/* Runtime instruction load was bad;
		 * take it all the way back down so we can try again */
3218
		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
Z
Zhu Yi 已提交
3219 3220 3221 3222 3223 3224
		goto restart;
	}

	/* Send pointers to protocol/runtime uCode image ... init code will
	 * load and launch runtime uCode, which will send us another "Alive"
	 * notification. */
3225
	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
C
Christoph Hellwig 已提交
3226
	if (iwl3945_set_ucode_ptrs(priv)) {
Z
Zhu Yi 已提交
3227 3228
		/* Runtime instruction load won't happen;
		 * take it all the way back down so we can try again */
3229
		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
Z
Zhu Yi 已提交
3230 3231 3232 3233 3234 3235 3236 3237 3238
		goto restart;
	}
	return;

 restart:
	queue_work(priv->workqueue, &priv->restart);
}


3239 3240 3241 3242
/* temporary */
static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
				     struct sk_buff *skb);

Z
Zhu Yi 已提交
3243
/**
C
Christoph Hellwig 已提交
3244
 * iwl3945_alive_start - called after REPLY_ALIVE notification received
Z
Zhu Yi 已提交
3245
 *                   from protocol/runtime uCode (initialization uCode's
C
Christoph Hellwig 已提交
3246
 *                   Alive gets handled by iwl3945_init_alive_start()).
Z
Zhu Yi 已提交
3247
 */
3248
static void iwl3945_alive_start(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3249 3250 3251 3252 3253
{
	int rc = 0;
	int thermal_spin = 0;
	u32 rfkill;

3254
	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
Z
Zhu Yi 已提交
3255 3256 3257 3258

	if (priv->card_alive.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 */
3259
		IWL_DEBUG_INFO(priv, "Alive failed.\n");
Z
Zhu Yi 已提交
3260 3261 3262 3263 3264 3265
		goto restart;
	}

	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
	 * This is a paranoid check, because we would not have gotten the
	 * "runtime" alive if code weren't properly loaded.  */
C
Christoph Hellwig 已提交
3266
	if (iwl3945_verify_ucode(priv)) {
Z
Zhu Yi 已提交
3267 3268
		/* Runtime instruction load was bad;
		 * take it all the way back down so we can try again */
3269
		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
Z
Zhu Yi 已提交
3270 3271 3272
		goto restart;
	}

C
Christoph Hellwig 已提交
3273
	iwl3945_clear_stations_table(priv);
Z
Zhu Yi 已提交
3274

3275
	rc = iwl_grab_nic_access(priv);
Z
Zhu Yi 已提交
3276
	if (rc) {
3277
		IWL_WARN(priv, "Can not read RFKILL status from adapter\n");
Z
Zhu Yi 已提交
3278 3279 3280
		return;
	}

3281
	rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
3282
	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
3283
	iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3284 3285 3286

	if (rfkill & 0x1) {
		clear_bit(STATUS_RF_KILL_HW, &priv->status);
T
Tomas Winkler 已提交
3287
		/* if RFKILL is not on, then wait for thermal
Z
Zhu Yi 已提交
3288
		 * sensor in adapter to kick in */
C
Christoph Hellwig 已提交
3289
		while (iwl3945_hw_get_temperature(priv) == 0) {
Z
Zhu Yi 已提交
3290 3291 3292 3293 3294
			thermal_spin++;
			udelay(10);
		}

		if (thermal_spin)
3295
			IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
Z
Zhu Yi 已提交
3296 3297 3298 3299
				       thermal_spin * 10);
	} else
		set_bit(STATUS_RF_KILL_HW, &priv->status);

3300
	/* After the ALIVE response, we can send commands to 3945 uCode */
Z
Zhu Yi 已提交
3301 3302 3303 3304 3305
	set_bit(STATUS_ALIVE, &priv->status);

	/* Clear out the uCode error bit if it is set */
	clear_bit(STATUS_FW_ERROR, &priv->status);

3306
	if (iwl_is_rfkill(priv))
Z
Zhu Yi 已提交
3307 3308
		return;

3309
	ieee80211_wake_queues(priv->hw);
Z
Zhu Yi 已提交
3310 3311 3312 3313

	priv->active_rate = priv->rates_mask;
	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;

3314
	iwl_power_update_mode(priv, false);
Z
Zhu Yi 已提交
3315

3316
	if (iwl_is_associated(priv)) {
C
Christoph Hellwig 已提交
3317
		struct iwl3945_rxon_cmd *active_rxon =
3318
				(struct iwl3945_rxon_cmd *)(&priv->active_rxon);
Z
Zhu Yi 已提交
3319

3320 3321
		memcpy(&priv->staging_rxon, &priv->active_rxon,
		       sizeof(priv->staging_rxon));
Z
Zhu Yi 已提交
3322 3323 3324
		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
	} else {
		/* Initialize our rx_config data */
3325
		iwl_connection_init_rx_config(priv, priv->iw_mode);
Z
Zhu Yi 已提交
3326 3327
	}

3328
	/* Configure Bluetooth device coexistence support */
3329
	iwl_send_bt_config(priv);
Z
Zhu Yi 已提交
3330 3331

	/* Configure the adapter for unassociated operation */
C
Christoph Hellwig 已提交
3332
	iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
3333 3334 3335

	iwl3945_reg_txpower_periodic(priv);

3336 3337
	iwl3945_led_register(priv);

3338
	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
3339
	set_bit(STATUS_READY, &priv->status);
3340
	wake_up_interruptible(&priv->wait_command_queue);
Z
Zhu Yi 已提交
3341 3342

	if (priv->error_recovering)
C
Christoph Hellwig 已提交
3343
		iwl3945_error_recovery(priv);
Z
Zhu Yi 已提交
3344

3345 3346 3347 3348 3349 3350 3351 3352
	/* reassociate for ADHOC mode */
	if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
		struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
								priv->vif);
		if (beacon)
			iwl3945_mac_beacon_update(priv->hw, beacon);
	}

Z
Zhu Yi 已提交
3353 3354 3355 3356 3357 3358
	return;

 restart:
	queue_work(priv->workqueue, &priv->restart);
}

3359
static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
Z
Zhu Yi 已提交
3360

3361
static void __iwl3945_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3362 3363 3364 3365 3366
{
	unsigned long flags;
	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
	struct ieee80211_conf *conf = NULL;

3367
	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
Z
Zhu Yi 已提交
3368 3369 3370 3371 3372 3373

	conf = ieee80211_get_hw_conf(priv->hw);

	if (!exit_pending)
		set_bit(STATUS_EXIT_PENDING, &priv->status);

M
Mohamed Abbas 已提交
3374
	iwl3945_led_unregister(priv);
C
Christoph Hellwig 已提交
3375
	iwl3945_clear_stations_table(priv);
Z
Zhu Yi 已提交
3376 3377 3378 3379 3380 3381 3382 3383 3384 3385

	/* Unblock any waiting calls */
	wake_up_interruptible_all(&priv->wait_command_queue);

	/* Wipe out the EXIT_PENDING status bit if we are not actually
	 * exiting the module */
	if (!exit_pending)
		clear_bit(STATUS_EXIT_PENDING, &priv->status);

	/* stop and reset the on-board processor */
3386
	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Z
Zhu Yi 已提交
3387 3388

	/* tell the device to stop sending interrupts */
3389
	spin_lock_irqsave(&priv->lock, flags);
C
Christoph Hellwig 已提交
3390
	iwl3945_disable_interrupts(priv);
3391 3392
	spin_unlock_irqrestore(&priv->lock, flags);
	iwl_synchronize_irq(priv);
Z
Zhu Yi 已提交
3393 3394 3395 3396

	if (priv->mac80211_registered)
		ieee80211_stop_queues(priv->hw);

C
Christoph Hellwig 已提交
3397
	/* If we have not previously called iwl3945_init() then
Z
Zhu Yi 已提交
3398
	 * clear all bits but the RF Kill and SUSPEND bits and return */
3399
	if (!iwl_is_init(priv)) {
Z
Zhu Yi 已提交
3400 3401 3402 3403
		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
					STATUS_RF_KILL_HW |
			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
					STATUS_RF_KILL_SW |
3404 3405
			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
					STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
3406
			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
3407 3408 3409
					STATUS_IN_SUSPEND |
				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
					STATUS_EXIT_PENDING;
Z
Zhu Yi 已提交
3410 3411 3412 3413 3414 3415 3416 3417 3418
		goto exit;
	}

	/* ...otherwise clear out all the status bits but the RF Kill and
	 * SUSPEND bits and continue taking the NIC down. */
	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
				STATUS_RF_KILL_HW |
			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
				STATUS_RF_KILL_SW |
3419 3420
			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
				STATUS_GEO_CONFIGURED |
Z
Zhu Yi 已提交
3421 3422 3423
			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
				STATUS_IN_SUSPEND |
			test_bit(STATUS_FW_ERROR, &priv->status) <<
3424 3425 3426
				STATUS_FW_ERROR |
			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
				STATUS_EXIT_PENDING;
Z
Zhu Yi 已提交
3427

3428
	priv->cfg->ops->lib->apm_ops.reset(priv);
Z
Zhu Yi 已提交
3429
	spin_lock_irqsave(&priv->lock, flags);
3430
	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Z
Zhu Yi 已提交
3431 3432
	spin_unlock_irqrestore(&priv->lock, flags);

C
Christoph Hellwig 已提交
3433 3434
	iwl3945_hw_txq_ctx_stop(priv);
	iwl3945_hw_rxq_stop(priv);
Z
Zhu Yi 已提交
3435 3436

	spin_lock_irqsave(&priv->lock, flags);
3437 3438
	if (!iwl_grab_nic_access(priv)) {
		iwl_write_prph(priv, APMG_CLK_DIS_REG,
Z
Zhu Yi 已提交
3439
					 APMG_CLK_VAL_DMA_CLK_RQT);
3440
		iwl_release_nic_access(priv);
Z
Zhu Yi 已提交
3441 3442 3443 3444 3445
	}
	spin_unlock_irqrestore(&priv->lock, flags);

	udelay(5);

3446 3447 3448 3449 3450
	if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
		priv->cfg->ops->lib->apm_ops.stop(priv);
	else
		priv->cfg->ops->lib->apm_ops.reset(priv);

Z
Zhu Yi 已提交
3451
 exit:
3452
	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
Z
Zhu Yi 已提交
3453 3454 3455 3456 3457 3458

	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);
	priv->ibss_beacon = NULL;

	/* clear out any free frames */
C
Christoph Hellwig 已提交
3459
	iwl3945_clear_free_frames(priv);
Z
Zhu Yi 已提交
3460 3461
}

3462
static void iwl3945_down(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3463 3464
{
	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
3465
	__iwl3945_down(priv);
Z
Zhu Yi 已提交
3466
	mutex_unlock(&priv->mutex);
3467

C
Christoph Hellwig 已提交
3468
	iwl3945_cancel_deferred_work(priv);
Z
Zhu Yi 已提交
3469 3470 3471 3472
}

#define MAX_HW_RESTARTS 5

3473
static int __iwl3945_up(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3474 3475 3476 3477
{
	int rc, i;

	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
3478
		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
Z
Zhu Yi 已提交
3479 3480 3481 3482
		return -EIO;
	}

	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
3483
		IWL_WARN(priv, "Radio disabled by SW RF kill (module "
Z
Zhu Yi 已提交
3484
			    "parameter)\n");
3485 3486 3487
		return -ENODEV;
	}

3488
	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
3489
		IWL_ERR(priv, "ucode not available for device bring up\n");
3490 3491 3492
		return -EIO;
	}

3493
	/* If platform's RF_KILL switch is NOT set to KILL */
3494
	if (iwl_read32(priv, CSR_GP_CNTRL) &
3495 3496 3497 3498 3499
				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
		clear_bit(STATUS_RF_KILL_HW, &priv->status);
	else {
		set_bit(STATUS_RF_KILL_HW, &priv->status);
		if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
3500
			IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
3501 3502
			return -ENODEV;
		}
Z
Zhu Yi 已提交
3503
	}
3504

3505
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
Z
Zhu Yi 已提交
3506

C
Christoph Hellwig 已提交
3507
	rc = iwl3945_hw_nic_init(priv);
Z
Zhu Yi 已提交
3508
	if (rc) {
3509
		IWL_ERR(priv, "Unable to int nic\n");
Z
Zhu Yi 已提交
3510 3511 3512 3513
		return rc;
	}

	/* make sure rfkill handshake bits are cleared */
3514 3515
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
Z
Zhu Yi 已提交
3516 3517 3518
		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);

	/* clear (again), then enable host interrupts */
3519
	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
C
Christoph Hellwig 已提交
3520
	iwl3945_enable_interrupts(priv);
Z
Zhu Yi 已提交
3521 3522

	/* really make sure rfkill handshake bits are cleared */
3523 3524
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Z
Zhu Yi 已提交
3525 3526 3527 3528 3529

	/* Copy original ucode data image from disk into backup cache.
	 * This will be used to initialize the on-board processor's
	 * data SRAM for a clean start when the runtime program first loads. */
	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
3530
	       priv->ucode_data.len);
Z
Zhu Yi 已提交
3531

3532 3533 3534 3535
	/* We return success when we resume from suspend and rf_kill is on. */
	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
		return 0;

Z
Zhu Yi 已提交
3536 3537
	for (i = 0; i < MAX_HW_RESTARTS; i++) {

C
Christoph Hellwig 已提交
3538
		iwl3945_clear_stations_table(priv);
Z
Zhu Yi 已提交
3539 3540 3541 3542

		/* load bootstrap state machine,
		 * load bootstrap program into processor's memory,
		 * prepare to load the "initialize" uCode */
K
Kolekar, Abhijeet 已提交
3543
		priv->cfg->ops->lib->load_ucode(priv);
Z
Zhu Yi 已提交
3544 3545

		if (rc) {
3546 3547
			IWL_ERR(priv,
				"Unable to set up bootstrap uCode: %d\n", rc);
Z
Zhu Yi 已提交
3548 3549 3550 3551
			continue;
		}

		/* start card; "initialize" will load runtime ucode */
C
Christoph Hellwig 已提交
3552
		iwl3945_nic_start(priv);
Z
Zhu Yi 已提交
3553

3554
		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
Z
Zhu Yi 已提交
3555 3556 3557 3558 3559

		return 0;
	}

	set_bit(STATUS_EXIT_PENDING, &priv->status);
C
Christoph Hellwig 已提交
3560
	__iwl3945_down(priv);
3561
	clear_bit(STATUS_EXIT_PENDING, &priv->status);
Z
Zhu Yi 已提交
3562 3563 3564

	/* tried to restart and config the device for as long as our
	 * patience could withstand */
3565
	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
Z
Zhu Yi 已提交
3566 3567 3568 3569 3570 3571 3572 3573 3574 3575
	return -EIO;
}


/*****************************************************************************
 *
 * Workqueue callbacks
 *
 *****************************************************************************/

C
Christoph Hellwig 已提交
3576
static void iwl3945_bg_init_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
3577
{
3578 3579
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, init_alive_start.work);
Z
Zhu Yi 已提交
3580 3581 3582 3583 3584

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
3585
	iwl3945_init_alive_start(priv);
Z
Zhu Yi 已提交
3586 3587 3588
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
3589
static void iwl3945_bg_alive_start(struct work_struct *data)
Z
Zhu Yi 已提交
3590
{
3591 3592
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, alive_start.work);
Z
Zhu Yi 已提交
3593 3594 3595 3596 3597

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
3598
	iwl3945_alive_start(priv);
Z
Zhu Yi 已提交
3599 3600 3601
	mutex_unlock(&priv->mutex);
}

3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620
static void iwl3945_rfkill_poll(struct work_struct *data)
{
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, rfkill_poll.work);
	unsigned long status = priv->status;

	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
		clear_bit(STATUS_RF_KILL_HW, &priv->status);
	else
		set_bit(STATUS_RF_KILL_HW, &priv->status);

	if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
		queue_work(priv->workqueue, &priv->rf_kill);

	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
			   round_jiffies_relative(2 * HZ));

}

Z
Zhu Yi 已提交
3621
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
C
Christoph Hellwig 已提交
3622
static void iwl3945_bg_request_scan(struct work_struct *data)
Z
Zhu Yi 已提交
3623
{
3624 3625
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, request_scan);
3626
	struct iwl_host_cmd cmd = {
Z
Zhu Yi 已提交
3627
		.id = REPLY_SCAN_CMD,
C
Christoph Hellwig 已提交
3628
		.len = sizeof(struct iwl3945_scan_cmd),
Z
Zhu Yi 已提交
3629 3630 3631
		.meta.flags = CMD_SIZE_HUGE,
	};
	int rc = 0;
C
Christoph Hellwig 已提交
3632
	struct iwl3945_scan_cmd *scan;
Z
Zhu Yi 已提交
3633
	struct ieee80211_conf *conf = NULL;
3634
	u8 n_probes = 2;
3635
	enum ieee80211_band band;
3636
	DECLARE_SSID_BUF(ssid);
Z
Zhu Yi 已提交
3637 3638 3639 3640 3641

	conf = ieee80211_get_hw_conf(priv->hw);

	mutex_lock(&priv->mutex);

3642
	if (!iwl_is_ready(priv)) {
3643
		IWL_WARN(priv, "request scan called when driver not ready.\n");
Z
Zhu Yi 已提交
3644 3645 3646
		goto done;
	}

T
Tomas Winkler 已提交
3647
	/* Make sure the scan wasn't canceled before this queued work
Z
Zhu Yi 已提交
3648 3649 3650 3651 3652 3653 3654
	 * was given the chance to run... */
	if (!test_bit(STATUS_SCANNING, &priv->status))
		goto done;

	/* This should never be called or scheduled if there is currently
	 * a scan active in the hardware. */
	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
3655 3656
		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests  "
				"Ignoring second request.\n");
Z
Zhu Yi 已提交
3657 3658 3659 3660 3661
		rc = -EIO;
		goto done;
	}

	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
3662
		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
Z
Zhu Yi 已提交
3663 3664 3665 3666
		goto done;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
3667 3668
		IWL_DEBUG_HC(priv,
			"Scan request while abort pending. Queuing.\n");
Z
Zhu Yi 已提交
3669 3670 3671
		goto done;
	}

3672
	if (iwl_is_rfkill(priv)) {
3673
		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
Z
Zhu Yi 已提交
3674 3675 3676 3677
		goto done;
	}

	if (!test_bit(STATUS_READY, &priv->status)) {
3678 3679
		IWL_DEBUG_HC(priv,
			"Scan request while uninitialized. Queuing.\n");
Z
Zhu Yi 已提交
3680 3681 3682 3683
		goto done;
	}

	if (!priv->scan_bands) {
3684
		IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
Z
Zhu Yi 已提交
3685 3686 3687
		goto done;
	}

W
Winkler, Tomas 已提交
3688 3689
	if (!priv->scan) {
		priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
Z
Zhu Yi 已提交
3690
				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
W
Winkler, Tomas 已提交
3691
		if (!priv->scan) {
Z
Zhu Yi 已提交
3692 3693 3694 3695
			rc = -ENOMEM;
			goto done;
		}
	}
W
Winkler, Tomas 已提交
3696
	scan = priv->scan;
C
Christoph Hellwig 已提交
3697
	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
Z
Zhu Yi 已提交
3698 3699 3700 3701

	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;

3702
	if (iwl_is_associated(priv)) {
Z
Zhu Yi 已提交
3703 3704 3705 3706 3707 3708
		u16 interval = 0;
		u32 extra;
		u32 suspend_time = 100;
		u32 scan_suspend_time = 100;
		unsigned long flags;

3709
		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
Z
Zhu Yi 已提交
3710 3711 3712 3713 3714 3715

		spin_lock_irqsave(&priv->lock, flags);
		interval = priv->beacon_int;
		spin_unlock_irqrestore(&priv->lock, flags);

		scan->suspend_time = 0;
3716
		scan->max_out_time = cpu_to_le32(200 * 1024);
Z
Zhu Yi 已提交
3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730
		if (!interval)
			interval = suspend_time;
		/*
		 * suspend time format:
		 *  0-19: beacon interval in usec (time before exec.)
		 * 20-23: 0
		 * 24-31: number of beacons (suspend between channels)
		 */

		extra = (suspend_time / interval) << 24;
		scan_suspend_time = 0xFF0FFFFF &
		    (extra | ((suspend_time % interval) * 1024));

		scan->suspend_time = cpu_to_le32(scan_suspend_time);
3731
		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
Z
Zhu Yi 已提交
3732 3733 3734 3735 3736
			       scan_suspend_time, interval);
	}

	/* We should add the ability for user to lock to PASSIVE ONLY */
	if (priv->one_direct_scan) {
3737 3738
		IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n",
				print_ssid(ssid, priv->direct_ssid,
3739
				priv->direct_ssid_len));
Z
Zhu Yi 已提交
3740 3741 3742 3743
		scan->direct_scan[0].id = WLAN_EID_SSID;
		scan->direct_scan[0].len = priv->direct_ssid_len;
		memcpy(scan->direct_scan[0].ssid,
		       priv->direct_ssid, priv->direct_ssid_len);
3744 3745
		n_probes++;
	} else
3746
		IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n");
Z
Zhu Yi 已提交
3747 3748 3749 3750

	/* We don't build a direct scan probe request; the uCode will do
	 * that based on the direct_mask added to each channel entry */
	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
3751
	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
Z
Zhu Yi 已提交
3752 3753 3754 3755
	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;

	/* flags + rate selection */

3756
	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
Z
Zhu Yi 已提交
3757 3758 3759
		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
		scan->good_CRC_th = 0;
3760
		band = IEEE80211_BAND_2GHZ;
3761
	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
Z
Zhu Yi 已提交
3762 3763
		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
		scan->good_CRC_th = IWL_GOOD_CRC_TH;
3764
		band = IEEE80211_BAND_5GHZ;
3765
	} else {
3766
		IWL_WARN(priv, "Invalid scan band count\n");
Z
Zhu Yi 已提交
3767 3768 3769
		goto done;
	}

S
Samuel Ortiz 已提交
3770 3771 3772 3773 3774
	scan->tx_cmd.len = cpu_to_le16(
		iwl_fill_probe_req(priv, band,
				   (struct ieee80211_mgmt *)scan->data,
				   IWL_MAX_SCAN_SIZE - sizeof(*scan)));

Z
Zhu Yi 已提交
3775 3776 3777
	/* select Rx antennas */
	scan->flags |= iwl3945_get_antenna_flags(priv);

3778
	if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
Z
Zhu Yi 已提交
3779 3780
		scan->filter_flags = RXON_FILTER_PROMISC_MSK;

3781 3782 3783 3784
	scan->channel_count =
		iwl3945_get_channels_for_scan(priv, band, 1, /* active */
					      n_probes,
			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
Z
Zhu Yi 已提交
3785

3786
	if (scan->channel_count == 0) {
3787
		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
3788 3789 3790
		goto done;
	}

Z
Zhu Yi 已提交
3791
	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
C
Christoph Hellwig 已提交
3792
	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
Z
Zhu Yi 已提交
3793 3794 3795 3796
	cmd.data = scan;
	scan->len = cpu_to_le16(cmd.len);

	set_bit(STATUS_SCAN_HW, &priv->status);
3797
	rc = iwl_send_cmd_sync(priv, &cmd);
Z
Zhu Yi 已提交
3798 3799 3800 3801 3802 3803 3804 3805 3806 3807
	if (rc)
		goto done;

	queue_delayed_work(priv->workqueue, &priv->scan_check,
			   IWL_SCAN_CHECK_WATCHDOG);

	mutex_unlock(&priv->mutex);
	return;

 done:
3808 3809 3810 3811 3812 3813 3814 3815
	/* can not perform scan make sure we clear scanning
	 * bits from status so next scan request can be performed.
	 * if we dont clear scanning status bit here all next scan
	 * will fail
	*/
	clear_bit(STATUS_SCAN_HW, &priv->status);
	clear_bit(STATUS_SCANNING, &priv->status);

3816
	/* inform mac80211 scan aborted */
Z
Zhu Yi 已提交
3817 3818 3819 3820
	queue_work(priv->workqueue, &priv->scan_completed);
	mutex_unlock(&priv->mutex);
}

C
Christoph Hellwig 已提交
3821
static void iwl3945_bg_up(struct work_struct *data)
Z
Zhu Yi 已提交
3822
{
3823
	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
Z
Zhu Yi 已提交
3824 3825 3826 3827 3828

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
3829
	__iwl3945_up(priv);
Z
Zhu Yi 已提交
3830
	mutex_unlock(&priv->mutex);
S
Samuel Ortiz 已提交
3831
	iwl_rfkill_set_hw_state(priv);
Z
Zhu Yi 已提交
3832 3833
}

C
Christoph Hellwig 已提交
3834
static void iwl3945_bg_restart(struct work_struct *data)
Z
Zhu Yi 已提交
3835
{
3836
	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
Z
Zhu Yi 已提交
3837 3838 3839 3840

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

C
Christoph Hellwig 已提交
3841
	iwl3945_down(priv);
Z
Zhu Yi 已提交
3842 3843 3844
	queue_work(priv->workqueue, &priv->up);
}

C
Christoph Hellwig 已提交
3845
static void iwl3945_bg_rx_replenish(struct work_struct *data)
Z
Zhu Yi 已提交
3846
{
3847 3848
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, rx_replenish);
Z
Zhu Yi 已提交
3849 3850 3851 3852 3853

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	mutex_lock(&priv->mutex);
C
Christoph Hellwig 已提交
3854
	iwl3945_rx_replenish(priv);
Z
Zhu Yi 已提交
3855 3856 3857
	mutex_unlock(&priv->mutex);
}

3858 3859
#define IWL_DELAY_NEXT_SCAN (HZ*2)

3860
static void iwl3945_post_associate(struct iwl_priv *priv)
Z
Zhu Yi 已提交
3861 3862 3863 3864
{
	int rc = 0;
	struct ieee80211_conf *conf = NULL;

3865
	if (priv->iw_mode == NL80211_IFTYPE_AP) {
3866
		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
Z
Zhu Yi 已提交
3867 3868 3869 3870
		return;
	}


3871
	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
3872
			priv->assoc_id, priv->active_rxon.bssid_addr);
Z
Zhu Yi 已提交
3873 3874 3875 3876

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

A
Abhijeet Kolekar 已提交
3877
	if (!priv->vif || !priv->is_open)
3878
		return;
A
Abhijeet Kolekar 已提交
3879

3880
	iwl_scan_cancel_timeout(priv, 200);
3881

Z
Zhu Yi 已提交
3882 3883
	conf = ieee80211_get_hw_conf(priv->hw);

3884
	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
3885
	iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
3886

3887
	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
C
Christoph Hellwig 已提交
3888
	iwl3945_setup_rxon_timing(priv);
3889
	rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
Z
Zhu Yi 已提交
3890 3891
			      sizeof(priv->rxon_timing), &priv->rxon_timing);
	if (rc)
3892
		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
Z
Zhu Yi 已提交
3893 3894
			    "Attempting to continue.\n");

3895
	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
Z
Zhu Yi 已提交
3896

3897
	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
Z
Zhu Yi 已提交
3898

3899
	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
Z
Zhu Yi 已提交
3900 3901 3902
			priv->assoc_id, priv->beacon_int);

	if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3903
		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
Z
Zhu Yi 已提交
3904
	else
3905
		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
Z
Zhu Yi 已提交
3906

3907
	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
Z
Zhu Yi 已提交
3908
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
3909
			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
Z
Zhu Yi 已提交
3910
		else
3911
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
Z
Zhu Yi 已提交
3912

3913
		if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
3914
			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
Z
Zhu Yi 已提交
3915 3916 3917

	}

C
Christoph Hellwig 已提交
3918
	iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
3919 3920

	switch (priv->iw_mode) {
3921
	case NL80211_IFTYPE_STATION:
C
Christoph Hellwig 已提交
3922
		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
Z
Zhu Yi 已提交
3923 3924
		break;

3925
	case NL80211_IFTYPE_ADHOC:
Z
Zhu Yi 已提交
3926

3927
		priv->assoc_id = 1;
C
Christoph Hellwig 已提交
3928
		iwl3945_add_station(priv, priv->bssid, 0, 0);
Z
Zhu Yi 已提交
3929
		iwl3945_sync_sta(priv, IWL_STA_ID,
3930
				 (priv->band == IEEE80211_BAND_5GHZ) ?
Z
Zhu Yi 已提交
3931 3932
				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
				 CMD_ASYNC);
C
Christoph Hellwig 已提交
3933 3934
		iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
		iwl3945_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
3935 3936 3937 3938

		break;

	default:
3939
		 IWL_ERR(priv, "%s Should not be called in %d mode\n",
3940
			   __func__, priv->iw_mode);
Z
Zhu Yi 已提交
3941 3942 3943
		break;
	}

C
Christoph Hellwig 已提交
3944
	iwl3945_activate_qos(priv, 0);
3945

3946 3947
	/* we have just associated, don't start scan too early */
	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
3948 3949
}

3950
static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
3951

Z
Zhu Yi 已提交
3952 3953 3954 3955 3956 3957
/*****************************************************************************
 *
 * mac80211 entry point functions
 *
 *****************************************************************************/

3958 3959
#define UCODE_READY_TIMEOUT	(2 * HZ)

C
Christoph Hellwig 已提交
3960
static int iwl3945_mac_start(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
3961
{
3962
	struct iwl_priv *priv = hw->priv;
3963
	int ret;
Z
Zhu Yi 已提交
3964

3965
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
3966 3967 3968 3969

	/* we should be verifying the device is ready to be opened */
	mutex_lock(&priv->mutex);

3970
	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
3971 3972 3973 3974 3975 3976
	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
	 * ucode filename and max sizes are card-specific. */

	if (!priv->ucode_code.len) {
		ret = iwl3945_read_ucode(priv);
		if (ret) {
3977
			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
3978 3979 3980 3981
			mutex_unlock(&priv->mutex);
			goto out_release_irq;
		}
	}
Z
Zhu Yi 已提交
3982

3983
	ret = __iwl3945_up(priv);
Z
Zhu Yi 已提交
3984 3985

	mutex_unlock(&priv->mutex);
3986

S
Samuel Ortiz 已提交
3987
	iwl_rfkill_set_hw_state(priv);
3988

3989 3990 3991
	if (ret)
		goto out_release_irq;

3992
	IWL_DEBUG_INFO(priv, "Start UP work.\n");
3993 3994 3995 3996

	if (test_bit(STATUS_IN_SUSPEND, &priv->status))
		return 0;

3997 3998 3999 4000 4001 4002 4003
	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
	 * mac80211 will not be run successfully. */
	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
			test_bit(STATUS_READY, &priv->status),
			UCODE_READY_TIMEOUT);
	if (!ret) {
		if (!test_bit(STATUS_READY, &priv->status)) {
4004 4005 4006
			IWL_ERR(priv,
				"Wait for START_ALIVE timeout after %dms.\n",
				jiffies_to_msecs(UCODE_READY_TIMEOUT));
4007 4008 4009 4010 4011
			ret = -ETIMEDOUT;
			goto out_release_irq;
		}
	}

4012 4013 4014 4015
	/* ucode is running and will send rfkill notifications,
	 * no need to poll the killswitch state anymore */
	cancel_delayed_work(&priv->rfkill_poll);

4016
	priv->is_open = 1;
4017
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4018
	return 0;
4019 4020

out_release_irq:
4021
	priv->is_open = 0;
4022
	IWL_DEBUG_MAC80211(priv, "leave - failed\n");
4023
	return ret;
Z
Zhu Yi 已提交
4024 4025
}

C
Christoph Hellwig 已提交
4026
static void iwl3945_mac_stop(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
4027
{
4028
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4029

4030
	IWL_DEBUG_MAC80211(priv, "enter\n");
4031

4032
	if (!priv->is_open) {
4033
		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
4034 4035 4036
		return;
	}

Z
Zhu Yi 已提交
4037
	priv->is_open = 0;
4038

4039
	if (iwl_is_ready_rf(priv)) {
4040 4041 4042
		/* stop mac, cancel any scan request and clear
		 * RXON_FILTER_ASSOC_MSK BIT
		 */
4043
		mutex_lock(&priv->mutex);
4044
		iwl_scan_cancel_timeout(priv, 100);
4045 4046 4047
		mutex_unlock(&priv->mutex);
	}

4048 4049 4050
	iwl3945_down(priv);

	flush_workqueue(priv->workqueue);
4051 4052 4053 4054

	/* start polling the killswitch state again */
	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
			   round_jiffies_relative(2 * HZ));
4055

4056
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4057 4058
}

4059
static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Z
Zhu Yi 已提交
4060
{
4061
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4062

4063
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4064

4065
	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
4066
		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
Z
Zhu Yi 已提交
4067

4068
	if (iwl3945_tx_skb(priv, skb))
Z
Zhu Yi 已提交
4069 4070
		dev_kfree_skb_any(skb);

4071
	IWL_DEBUG_MAC80211(priv, "leave\n");
4072
	return NETDEV_TX_OK;
Z
Zhu Yi 已提交
4073 4074
}

C
Christoph Hellwig 已提交
4075
static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
4076 4077
				 struct ieee80211_if_init_conf *conf)
{
4078
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4079 4080
	unsigned long flags;

4081
	IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
Z
Zhu Yi 已提交
4082

4083
	if (priv->vif) {
4084
		IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
4085
		return -EOPNOTSUPP;
Z
Zhu Yi 已提交
4086 4087 4088
	}

	spin_lock_irqsave(&priv->lock, flags);
4089
	priv->vif = conf->vif;
4090
	priv->iw_mode = conf->type;
Z
Zhu Yi 已提交
4091 4092 4093 4094

	spin_unlock_irqrestore(&priv->lock, flags);

	mutex_lock(&priv->mutex);
4095 4096

	if (conf->mac_addr) {
4097
		IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr);
4098 4099 4100
		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
	}

4101
	if (iwl_is_ready(priv))
4102
		iwl3945_set_mode(priv, conf->type);
Z
Zhu Yi 已提交
4103 4104 4105

	mutex_unlock(&priv->mutex);

4106
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4107 4108 4109 4110
	return 0;
}

/**
C
Christoph Hellwig 已提交
4111
 * iwl3945_mac_config - mac80211 config callback
Z
Zhu Yi 已提交
4112 4113 4114 4115 4116
 *
 * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
 * be set inappropriately and the driver currently sets the hardware up to
 * use it whenever needed.
 */
4117
static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
Z
Zhu Yi 已提交
4118
{
4119
	struct iwl_priv *priv = hw->priv;
4120
	const struct iwl_channel_info *ch_info;
4121
	struct ieee80211_conf *conf = &hw->conf;
Z
Zhu Yi 已提交
4122
	unsigned long flags;
4123
	int ret = 0;
Z
Zhu Yi 已提交
4124 4125

	mutex_lock(&priv->mutex);
4126 4127
	IWL_DEBUG_MAC80211(priv, "enter to channel %d\n",
				conf->channel->hw_value);
Z
Zhu Yi 已提交
4128

4129
	if (!iwl_is_ready(priv)) {
4130
		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
4131 4132
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
4133 4134
	}

4135
	if (unlikely(!iwl3945_mod_params.disable_hw_scan &&
Z
Zhu Yi 已提交
4136
		     test_bit(STATUS_SCANNING, &priv->status))) {
4137
		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
4138
		set_bit(STATUS_CONF_PENDING, &priv->status);
Z
Zhu Yi 已提交
4139
		mutex_unlock(&priv->mutex);
4140
		return 0;
Z
Zhu Yi 已提交
4141 4142 4143 4144
	}

	spin_lock_irqsave(&priv->lock, flags);

4145 4146
	ch_info = iwl_get_channel_info(priv, conf->channel->band,
				       conf->channel->hw_value);
Z
Zhu Yi 已提交
4147
	if (!is_channel_valid(ch_info)) {
4148 4149 4150 4151
		IWL_DEBUG_SCAN(priv,
				"Channel %d [%d] is INVALID for this band.\n",
				conf->channel->hw_value, conf->channel->band);
		IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
Z
Zhu Yi 已提交
4152
		spin_unlock_irqrestore(&priv->lock, flags);
4153 4154
		ret = -EINVAL;
		goto out;
Z
Zhu Yi 已提交
4155 4156
	}

4157
	iwl_set_rxon_channel(priv, conf->channel);
Z
Zhu Yi 已提交
4158

4159
	iwl_set_flags_for_band(priv, conf->channel->band);
Z
Zhu Yi 已提交
4160 4161 4162 4163

	/* The list of supported rates and rate mask can be different
	 * for each phymode; since the phymode may have changed, reset
	 * the rate mask to what mac80211 lists */
4164
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
4165 4166 4167 4168 4169

	spin_unlock_irqrestore(&priv->lock, flags);

#ifdef IEEE80211_CONF_CHANNEL_SWITCH
	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
C
Christoph Hellwig 已提交
4170
		iwl3945_hw_channel_switch(priv, conf->channel);
4171
		goto out;
Z
Zhu Yi 已提交
4172 4173 4174
	}
#endif

C
Christoph Hellwig 已提交
4175
	iwl3945_radio_kill_sw(priv, !conf->radio_enabled);
Z
Zhu Yi 已提交
4176 4177

	if (!conf->radio_enabled) {
4178
		IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
4179
		goto out;
Z
Zhu Yi 已提交
4180 4181
	}

4182
	if (iwl_is_rfkill(priv)) {
4183
		IWL_DEBUG_MAC80211(priv, "leave - RF kill\n");
4184 4185
		ret = -EIO;
		goto out;
Z
Zhu Yi 已提交
4186 4187
	}

4188
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
4189

4190 4191
	if (memcmp(&priv->active_rxon,
		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
C
Christoph Hellwig 已提交
4192
		iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4193
	else
4194
		IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n");
Z
Zhu Yi 已提交
4195

4196
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4197

4198
out:
4199
	clear_bit(STATUS_CONF_PENDING, &priv->status);
Z
Zhu Yi 已提交
4200
	mutex_unlock(&priv->mutex);
4201
	return ret;
Z
Zhu Yi 已提交
4202 4203
}

4204
static void iwl3945_config_ap(struct iwl_priv *priv)
Z
Zhu Yi 已提交
4205 4206 4207
{
	int rc = 0;

4208
	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Z
Zhu Yi 已提交
4209 4210 4211
		return;

	/* The following should be done only at AP bring up */
4212
	if (!(iwl_is_associated(priv))) {
Z
Zhu Yi 已提交
4213 4214

		/* RXON - unassoc (to set timing command) */
4215
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
4216
		iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4217 4218

		/* RXON Timing */
4219
		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
C
Christoph Hellwig 已提交
4220
		iwl3945_setup_rxon_timing(priv);
4221 4222 4223
		rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
				      sizeof(priv->rxon_timing),
				      &priv->rxon_timing);
Z
Zhu Yi 已提交
4224
		if (rc)
4225
			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
Z
Zhu Yi 已提交
4226 4227 4228
					"Attempting to continue.\n");

		/* FIXME: what should be the assoc_id for AP? */
4229
		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
Z
Zhu Yi 已提交
4230
		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
4231
			priv->staging_rxon.flags |=
Z
Zhu Yi 已提交
4232 4233
				RXON_FLG_SHORT_PREAMBLE_MSK;
		else
4234
			priv->staging_rxon.flags &=
Z
Zhu Yi 已提交
4235 4236
				~RXON_FLG_SHORT_PREAMBLE_MSK;

4237
		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
Z
Zhu Yi 已提交
4238 4239
			if (priv->assoc_capability &
				WLAN_CAPABILITY_SHORT_SLOT_TIME)
4240
				priv->staging_rxon.flags |=
Z
Zhu Yi 已提交
4241 4242
					RXON_FLG_SHORT_SLOT_MSK;
			else
4243
				priv->staging_rxon.flags &=
Z
Zhu Yi 已提交
4244 4245
					~RXON_FLG_SHORT_SLOT_MSK;

4246
			if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
4247
				priv->staging_rxon.flags &=
Z
Zhu Yi 已提交
4248 4249 4250
					~RXON_FLG_SHORT_SLOT_MSK;
		}
		/* restore RXON assoc */
4251
		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
4252
		iwl3945_commit_rxon(priv);
4253
		iwl3945_add_station(priv, iwl_bcast_addr, 0, 0);
4254
	}
C
Christoph Hellwig 已提交
4255
	iwl3945_send_beacon_cmd(priv);
Z
Zhu Yi 已提交
4256 4257 4258 4259 4260 4261

	/* FIXME - we need to add code here to detect a totally new
	 * configuration, reset the AP, unassoc, rxon timing, assoc,
	 * clear sta table, add BCAST sta... */
}

4262 4263
static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
					struct ieee80211_vif *vif,
4264
					struct ieee80211_if_conf *conf)
Z
Zhu Yi 已提交
4265
{
4266
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4267 4268 4269 4270 4271
	int rc;

	if (conf == NULL)
		return -EIO;

4272
	if (priv->vif != vif) {
4273
		IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
4274 4275 4276
		return 0;
	}

4277
	/* handle this temporarily here */
4278
	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
4279 4280 4281 4282
	    conf->changed & IEEE80211_IFCC_BEACON) {
		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
		if (!beacon)
			return -ENOMEM;
4283
		mutex_lock(&priv->mutex);
4284
		rc = iwl3945_mac_beacon_update(hw, beacon);
4285
		mutex_unlock(&priv->mutex);
4286 4287 4288 4289
		if (rc)
			return rc;
	}

4290
	if (!iwl_is_alive(priv))
4291 4292
		return -EAGAIN;

Z
Zhu Yi 已提交
4293 4294 4295
	mutex_lock(&priv->mutex);

	if (conf->bssid)
4296
		IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid);
Z
Zhu Yi 已提交
4297

4298 4299 4300
/*
 * very dubious code was here; the probe filtering flag is never set:
 *
Z
Zhu Yi 已提交
4301 4302
	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
4303
 */
Z
Zhu Yi 已提交
4304

4305
	if (priv->iw_mode == NL80211_IFTYPE_AP) {
Z
Zhu Yi 已提交
4306 4307 4308
		if (!conf->bssid) {
			conf->bssid = priv->mac_addr;
			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
4309
			IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
J
Johannes Berg 已提交
4310
					   conf->bssid);
Z
Zhu Yi 已提交
4311 4312 4313 4314
		}
		if (priv->ibss_beacon)
			dev_kfree_skb(priv->ibss_beacon);

4315
		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
Z
Zhu Yi 已提交
4316 4317
	}

4318
	if (iwl_is_rfkill(priv))
4319 4320
		goto done;

Z
Zhu Yi 已提交
4321 4322 4323 4324
	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
	    !is_multicast_ether_addr(conf->bssid)) {
		/* If there is currently a HW scan going on in the background
		 * then we need to cancel it else the RXON below will fail. */
4325
		if (iwl_scan_cancel_timeout(priv, 100)) {
4326
			IWL_WARN(priv, "Aborted scan still in progress "
Z
Zhu Yi 已提交
4327
				    "after 100ms\n");
4328
			IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n");
Z
Zhu Yi 已提交
4329 4330 4331
			mutex_unlock(&priv->mutex);
			return -EAGAIN;
		}
4332
		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
Z
Zhu Yi 已提交
4333 4334 4335 4336 4337 4338 4339

		/* TODO: Audit driver for usage of these members and see
		 * if mac80211 deprecates them (priv->bssid looks like it
		 * shouldn't be there, but I haven't scanned the IBSS code
		 * to verify) - jpk */
		memcpy(priv->bssid, conf->bssid, ETH_ALEN);

4340
		if (priv->iw_mode == NL80211_IFTYPE_AP)
C
Christoph Hellwig 已提交
4341
			iwl3945_config_ap(priv);
Z
Zhu Yi 已提交
4342
		else {
C
Christoph Hellwig 已提交
4343
			rc = iwl3945_commit_rxon(priv);
4344
			if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
C
Christoph Hellwig 已提交
4345
				iwl3945_add_station(priv,
4346
					priv->active_rxon.bssid_addr, 1, 0);
Z
Zhu Yi 已提交
4347 4348 4349
		}

	} else {
4350
		iwl_scan_cancel_timeout(priv, 100);
4351
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
4352
		iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4353 4354
	}

4355
 done:
4356
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4357 4358 4359 4360 4361
	mutex_unlock(&priv->mutex);

	return 0;
}

C
Christoph Hellwig 已提交
4362
static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
4363 4364
				     struct ieee80211_if_init_conf *conf)
{
4365
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4366

4367
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4368 4369

	mutex_lock(&priv->mutex);
4370

4371
	if (iwl_is_ready_rf(priv)) {
4372
		iwl_scan_cancel_timeout(priv, 100);
4373
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
4374 4375
		iwl3945_commit_rxon(priv);
	}
4376 4377
	if (priv->vif == conf->vif) {
		priv->vif = NULL;
Z
Zhu Yi 已提交
4378 4379 4380 4381
		memset(priv->bssid, 0, ETH_ALEN);
	}
	mutex_unlock(&priv->mutex);

4382
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4383 4384
}

4385 4386 4387 4388 4389 4390 4391
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)

static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif,
				     struct ieee80211_bss_conf *bss_conf,
				     u32 changes)
{
4392
	struct iwl_priv *priv = hw->priv;
4393

4394
	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
4395 4396

	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
4397
		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
4398 4399
				   bss_conf->use_short_preamble);
		if (bss_conf->use_short_preamble)
4400
			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
4401
		else
4402 4403
			priv->staging_rxon.flags &=
				~RXON_FLG_SHORT_PREAMBLE_MSK;
4404 4405 4406
	}

	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
4407 4408
		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n",
				   bss_conf->use_cts_prot);
4409
		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
4410
			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
4411
		else
4412
			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
4413 4414 4415
	}

	if (changes & BSS_CHANGED_ASSOC) {
4416
		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
4417 4418 4419 4420 4421 4422 4423
		/* This should never happen as this function should
		 * never be called from interrupt context. */
		if (WARN_ON_ONCE(in_interrupt()))
			return;
		if (bss_conf->assoc) {
			priv->assoc_id = bss_conf->aid;
			priv->beacon_int = bss_conf->beacon_int;
4424
			priv->timestamp = bss_conf->timestamp;
4425
			priv->assoc_capability = bss_conf->assoc_capability;
4426
			priv->power_data.dtim_period = bss_conf->dtim_period;
4427 4428 4429 4430 4431 4432 4433
			priv->next_scan_jiffies = jiffies +
					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
			mutex_lock(&priv->mutex);
			iwl3945_post_associate(priv);
			mutex_unlock(&priv->mutex);
		} else {
			priv->assoc_id = 0;
4434 4435
			IWL_DEBUG_MAC80211(priv,
					"DISASSOC %d\n", bss_conf->assoc);
4436
		}
4437
	} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
4438 4439
			IWL_DEBUG_MAC80211(priv,
					"Associated Changes %d\n", changes);
4440 4441 4442 4443 4444
			iwl3945_send_rxon_assoc(priv);
	}

}

C
Christoph Hellwig 已提交
4445
static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
Z
Zhu Yi 已提交
4446 4447 4448
{
	int rc = 0;
	unsigned long flags;
4449
	struct iwl_priv *priv = hw->priv;
4450
	DECLARE_SSID_BUF(ssid_buf);
Z
Zhu Yi 已提交
4451

4452
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4453

4454
	mutex_lock(&priv->mutex);
Z
Zhu Yi 已提交
4455 4456
	spin_lock_irqsave(&priv->lock, flags);

4457
	if (!iwl_is_ready_rf(priv)) {
Z
Zhu Yi 已提交
4458
		rc = -EIO;
4459
		IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
Z
Zhu Yi 已提交
4460 4461 4462
		goto out_unlock;
	}

4463 4464 4465 4466 4467 4468
	/* we don't schedule scan within next_scan_jiffies period */
	if (priv->next_scan_jiffies &&
			time_after(priv->next_scan_jiffies, jiffies)) {
		rc = -EAGAIN;
		goto out_unlock;
	}
4469 4470 4471 4472
	/* if we just finished scan ask for delay for a broadcast scan */
	if ((len == 0) && priv->last_scan_jiffies &&
	    time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
		       jiffies)) {
Z
Zhu Yi 已提交
4473 4474 4475 4476
		rc = -EAGAIN;
		goto out_unlock;
	}
	if (len) {
4477 4478
		IWL_DEBUG_SCAN(priv, "direct scan for %s [%zd]\n ",
			       print_ssid(ssid_buf, ssid, len), len);
Z
Zhu Yi 已提交
4479 4480 4481 4482 4483

		priv->one_direct_scan = 1;
		priv->direct_ssid_len = (u8)
		    min((u8) len, (u8) IW_ESSID_MAX_SIZE);
		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
4484 4485
	} else
		priv->one_direct_scan = 0;
Z
Zhu Yi 已提交
4486

C
Christoph Hellwig 已提交
4487
	rc = iwl3945_scan_initiate(priv);
Z
Zhu Yi 已提交
4488

4489
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4490 4491 4492

out_unlock:
	spin_unlock_irqrestore(&priv->lock, flags);
4493
	mutex_unlock(&priv->mutex);
Z
Zhu Yi 已提交
4494 4495 4496 4497

	return rc;
}

C
Christoph Hellwig 已提交
4498
static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4499 4500 4501
			       struct ieee80211_vif *vif,
			       struct ieee80211_sta *sta,
			       struct ieee80211_key_conf *key)
Z
Zhu Yi 已提交
4502
{
4503
	struct iwl_priv *priv = hw->priv;
4504
	const u8 *addr;
4505
	int ret;
Z
Zhu Yi 已提交
4506 4507
	u8 sta_id;

4508
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4509

4510
	if (iwl3945_mod_params.sw_crypto) {
4511
		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
Z
Zhu Yi 已提交
4512 4513 4514
		return -EOPNOTSUPP;
	}

4515
	addr = sta ? sta->addr : iwl_bcast_addr;
C
Christoph Hellwig 已提交
4516
	sta_id = iwl3945_hw_find_station(priv, addr);
Z
Zhu Yi 已提交
4517
	if (sta_id == IWL_INVALID_STATION) {
4518
		IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
J
Johannes Berg 已提交
4519
				   addr);
Z
Zhu Yi 已提交
4520 4521 4522 4523 4524
		return -EINVAL;
	}

	mutex_lock(&priv->mutex);

4525
	iwl_scan_cancel_timeout(priv, 100);
4526

Z
Zhu Yi 已提交
4527 4528
	switch (cmd) {
	case  SET_KEY:
4529 4530
		ret = iwl3945_update_sta_key_info(priv, key, sta_id);
		if (!ret) {
4531
			iwl_set_rxon_hwcrypto(priv, 1);
C
Christoph Hellwig 已提交
4532
			iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4533
			key->hw_key_idx = sta_id;
4534 4535
			IWL_DEBUG_MAC80211(priv,
				"set_key success, using hwcrypto\n");
Z
Zhu Yi 已提交
4536 4537 4538 4539
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
		}
		break;
	case DISABLE_KEY:
4540 4541
		ret = iwl3945_clear_sta_key_info(priv, sta_id);
		if (!ret) {
4542
			iwl_set_rxon_hwcrypto(priv, 0);
C
Christoph Hellwig 已提交
4543
			iwl3945_commit_rxon(priv);
4544
			IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
Z
Zhu Yi 已提交
4545 4546 4547
		}
		break;
	default:
4548
		ret = -EINVAL;
Z
Zhu Yi 已提交
4549 4550
	}

4551
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4552 4553
	mutex_unlock(&priv->mutex);

4554
	return ret;
Z
Zhu Yi 已提交
4555 4556
}

J
Johannes Berg 已提交
4557
static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
Z
Zhu Yi 已提交
4558 4559
			   const struct ieee80211_tx_queue_params *params)
{
4560
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4561 4562 4563
	unsigned long flags;
	int q;

4564
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4565

4566
	if (!iwl_is_ready_rf(priv)) {
4567
		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
Z
Zhu Yi 已提交
4568 4569 4570 4571
		return -EIO;
	}

	if (queue >= AC_NUM) {
4572
		IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
Z
Zhu Yi 已提交
4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583
		return 0;
	}

	q = AC_NUM - 1 - queue;

	spin_lock_irqsave(&priv->lock, flags);

	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
	priv->qos_data.def_qos_parm.ac[q].edca_txop =
4584
			cpu_to_le16((params->txop * 32));
Z
Zhu Yi 已提交
4585 4586 4587 4588 4589 4590 4591

	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
	priv->qos_data.qos_active = 1;

	spin_unlock_irqrestore(&priv->lock, flags);

	mutex_lock(&priv->mutex);
4592
	if (priv->iw_mode == NL80211_IFTYPE_AP)
C
Christoph Hellwig 已提交
4593
		iwl3945_activate_qos(priv, 1);
4594
	else if (priv->assoc_id && iwl_is_associated(priv))
C
Christoph Hellwig 已提交
4595
		iwl3945_activate_qos(priv, 0);
Z
Zhu Yi 已提交
4596 4597 4598

	mutex_unlock(&priv->mutex);

4599
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4600 4601 4602
	return 0;
}

C
Christoph Hellwig 已提交
4603
static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
Z
Zhu Yi 已提交
4604 4605
				struct ieee80211_tx_queue_stats *stats)
{
4606
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4607
	int i, avail;
4608
	struct iwl_tx_queue *txq;
4609
	struct iwl_queue *q;
Z
Zhu Yi 已提交
4610 4611
	unsigned long flags;

4612
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4613

4614
	if (!iwl_is_ready_rf(priv)) {
4615
		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
Z
Zhu Yi 已提交
4616 4617 4618 4619 4620 4621
		return -EIO;
	}

	spin_lock_irqsave(&priv->lock, flags);

	for (i = 0; i < AC_NUM; i++) {
4622
		txq = &priv->txq[i];
Z
Zhu Yi 已提交
4623
		q = &txq->q;
4624
		avail = iwl_queue_space(q);
Z
Zhu Yi 已提交
4625

4626 4627 4628
		stats[i].len = q->n_window - avail;
		stats[i].limit = q->n_window - q->high_mark;
		stats[i].count = q->n_window;
Z
Zhu Yi 已提交
4629 4630 4631 4632

	}
	spin_unlock_irqrestore(&priv->lock, flags);

4633
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4634 4635 4636 4637

	return 0;
}

C
Christoph Hellwig 已提交
4638
static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
Z
Zhu Yi 已提交
4639
{
4640
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4641 4642 4643
	unsigned long flags;

	mutex_lock(&priv->mutex);
4644
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4645

4646
	iwl_reset_qos(priv);
4647

Z
Zhu Yi 已提交
4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658
	spin_lock_irqsave(&priv->lock, flags);
	priv->assoc_id = 0;
	priv->assoc_capability = 0;

	/* new association get rid of ibss beacon skb */
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = NULL;

	priv->beacon_int = priv->hw->conf.beacon_int;
4659
	priv->timestamp = 0;
4660
	if ((priv->iw_mode == NL80211_IFTYPE_STATION))
Z
Zhu Yi 已提交
4661 4662 4663 4664
		priv->beacon_int = 0;

	spin_unlock_irqrestore(&priv->lock, flags);

4665
	if (!iwl_is_ready_rf(priv)) {
4666
		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
4667 4668 4669 4670
		mutex_unlock(&priv->mutex);
		return;
	}

4671 4672 4673
	/* we are restarting association process
	 * clear RXON_FILTER_ASSOC_MSK bit
	*/
4674
	if (priv->iw_mode != NL80211_IFTYPE_AP) {
4675
		iwl_scan_cancel_timeout(priv, 100);
4676
		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
C
Christoph Hellwig 已提交
4677
		iwl3945_commit_rxon(priv);
4678 4679
	}

Z
Zhu Yi 已提交
4680
	/* Per mac80211.h: This is only used in IBSS mode... */
4681
	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
4682

4683
		IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
Z
Zhu Yi 已提交
4684 4685 4686 4687
		mutex_unlock(&priv->mutex);
		return;
	}

4688
	iwl_set_rate(priv);
Z
Zhu Yi 已提交
4689 4690 4691

	mutex_unlock(&priv->mutex);

4692
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4693 4694 4695

}

4696
static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
Z
Zhu Yi 已提交
4697
{
4698
	struct iwl_priv *priv = hw->priv;
Z
Zhu Yi 已提交
4699 4700
	unsigned long flags;

4701
	IWL_DEBUG_MAC80211(priv, "enter\n");
Z
Zhu Yi 已提交
4702

4703
	if (!iwl_is_ready_rf(priv)) {
4704
		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
Z
Zhu Yi 已提交
4705 4706 4707
		return -EIO;
	}

4708
	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
4709
		IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
Z
Zhu Yi 已提交
4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721
		return -EIO;
	}

	spin_lock_irqsave(&priv->lock, flags);

	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	priv->ibss_beacon = skb;

	priv->assoc_id = 0;

4722
	IWL_DEBUG_MAC80211(priv, "leave\n");
Z
Zhu Yi 已提交
4723 4724
	spin_unlock_irqrestore(&priv->lock, flags);

4725
	iwl_reset_qos(priv);
Z
Zhu Yi 已提交
4726

4727
	iwl3945_post_associate(priv);
Z
Zhu Yi 已提交
4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738


	return 0;
}

/*****************************************************************************
 *
 * sysfs attributes
 *
 *****************************************************************************/

S
Samuel Ortiz 已提交
4739
#ifdef CONFIG_IWLWIFI_DEBUG
Z
Zhu Yi 已提交
4740 4741 4742 4743 4744 4745 4746 4747

/*
 * The following adds a new attribute to the sysfs representation
 * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
 * used for controlling the debug level.
 *
 * See the level definitions in iwl for details.
 */
4748 4749
static ssize_t show_debug_level(struct device *d,
				struct device_attribute *attr, char *buf)
Z
Zhu Yi 已提交
4750
{
4751
	struct iwl_priv *priv = d->driver_data;
4752 4753

	return sprintf(buf, "0x%08X\n", priv->debug_level);
Z
Zhu Yi 已提交
4754
}
4755 4756
static ssize_t store_debug_level(struct device *d,
				struct device_attribute *attr,
Z
Zhu Yi 已提交
4757 4758
				 const char *buf, size_t count)
{
4759
	struct iwl_priv *priv = d->driver_data;
4760 4761
	unsigned long val;
	int ret;
Z
Zhu Yi 已提交
4762

4763 4764
	ret = strict_strtoul(buf, 0, &val);
	if (ret)
T
Tomas Winkler 已提交
4765
		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
Z
Zhu Yi 已提交
4766
	else
4767
		priv->debug_level = val;
Z
Zhu Yi 已提交
4768 4769 4770 4771

	return strnlen(buf, count);
}

4772 4773
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
			show_debug_level, store_debug_level);
Z
Zhu Yi 已提交
4774

S
Samuel Ortiz 已提交
4775
#endif /* CONFIG_IWLWIFI_DEBUG */
Z
Zhu Yi 已提交
4776 4777 4778 4779

static ssize_t show_temperature(struct device *d,
				struct device_attribute *attr, char *buf)
{
4780
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4781

4782
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
4783 4784
		return -EAGAIN;

C
Christoph Hellwig 已提交
4785
	return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
Z
Zhu Yi 已提交
4786 4787 4788 4789 4790 4791 4792
}

static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);

static ssize_t show_tx_power(struct device *d,
			     struct device_attribute *attr, char *buf)
{
4793
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
4794
	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
Z
Zhu Yi 已提交
4795 4796 4797 4798 4799 4800
}

static ssize_t store_tx_power(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
4801
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4802 4803 4804 4805 4806
	char *p = (char *)buf;
	u32 val;

	val = simple_strtoul(p, &p, 10);
	if (p == buf)
T
Tomas Winkler 已提交
4807
		IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
Z
Zhu Yi 已提交
4808
	else
C
Christoph Hellwig 已提交
4809
		iwl3945_hw_reg_set_txpower(priv, val);
Z
Zhu Yi 已提交
4810 4811 4812 4813 4814 4815 4816 4817 4818

	return count;
}

static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);

static ssize_t show_flags(struct device *d,
			  struct device_attribute *attr, char *buf)
{
4819
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4820

4821
	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
Z
Zhu Yi 已提交
4822 4823 4824 4825 4826 4827
}

static ssize_t store_flags(struct device *d,
			   struct device_attribute *attr,
			   const char *buf, size_t count)
{
4828
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4829 4830 4831
	u32 flags = simple_strtoul(buf, NULL, 0);

	mutex_lock(&priv->mutex);
4832
	if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
Z
Zhu Yi 已提交
4833
		/* Cancel any currently running scans... */
4834
		if (iwl_scan_cancel_timeout(priv, 100))
4835
			IWL_WARN(priv, "Could not cancel scan.\n");
Z
Zhu Yi 已提交
4836
		else {
4837
			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
Z
Zhu Yi 已提交
4838
				       flags);
4839
			priv->staging_rxon.flags = cpu_to_le32(flags);
C
Christoph Hellwig 已提交
4840
			iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852
		}
	}
	mutex_unlock(&priv->mutex);

	return count;
}

static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);

static ssize_t show_filter_flags(struct device *d,
				 struct device_attribute *attr, char *buf)
{
4853
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4854 4855

	return sprintf(buf, "0x%04X\n",
4856
		le32_to_cpu(priv->active_rxon.filter_flags));
Z
Zhu Yi 已提交
4857 4858 4859 4860 4861 4862
}

static ssize_t store_filter_flags(struct device *d,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
4863
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
Z
Zhu Yi 已提交
4864 4865 4866
	u32 filter_flags = simple_strtoul(buf, NULL, 0);

	mutex_lock(&priv->mutex);
4867
	if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
Z
Zhu Yi 已提交
4868
		/* Cancel any currently running scans... */
4869
		if (iwl_scan_cancel_timeout(priv, 100))
4870
			IWL_WARN(priv, "Could not cancel scan.\n");
Z
Zhu Yi 已提交
4871
		else {
4872
			IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
Z
Zhu Yi 已提交
4873
				       "0x%04X\n", filter_flags);
4874
			priv->staging_rxon.filter_flags =
Z
Zhu Yi 已提交
4875
				cpu_to_le32(filter_flags);
C
Christoph Hellwig 已提交
4876
			iwl3945_commit_rxon(priv);
Z
Zhu Yi 已提交
4877 4878 4879 4880 4881 4882 4883 4884 4885 4886
		}
	}
	mutex_unlock(&priv->mutex);

	return count;
}

static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
		   store_filter_flags);

4887
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
4888 4889 4890 4891

static ssize_t show_measurement(struct device *d,
				struct device_attribute *attr, char *buf)
{
4892
	struct iwl_priv *priv = dev_get_drvdata(d);
4893
	struct iwl_spectrum_notification measure_report;
Z
Zhu Yi 已提交
4894
	u32 size = sizeof(measure_report), len = 0, ofs = 0;
4895
	u8 *data = (u8 *)&measure_report;
Z
Zhu Yi 已提交
4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
	if (!(priv->measurement_status & MEASUREMENT_READY)) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return 0;
	}
	memcpy(&measure_report, &priv->measure_report, size);
	priv->measurement_status = 0;
	spin_unlock_irqrestore(&priv->lock, flags);

	while (size && (PAGE_SIZE - len)) {
		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
				   PAGE_SIZE - len, 1);
		len = strlen(buf);
		if (PAGE_SIZE - len)
			buf[len++] = '\n';

		ofs += 16;
		size -= min(size, 16U);
	}

	return len;
}

static ssize_t store_measurement(struct device *d,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
4925
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
4926
	struct ieee80211_measurement_params params = {
4927
		.channel = le16_to_cpu(priv->active_rxon.channel),
Z
Zhu Yi 已提交
4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948
		.start_time = cpu_to_le64(priv->last_tsf),
		.duration = cpu_to_le16(1),
	};
	u8 type = IWL_MEASURE_BASIC;
	u8 buffer[32];
	u8 channel;

	if (count) {
		char *p = buffer;
		strncpy(buffer, buf, min(sizeof(buffer), count));
		channel = simple_strtoul(p, NULL, 0);
		if (channel)
			params.channel = channel;

		p = buffer;
		while (*p && *p != ' ')
			p++;
		if (*p)
			type = simple_strtoul(p + 1, NULL, 0);
	}

4949
	IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
Z
Zhu Yi 已提交
4950
		       "channel %d (for '%s')\n", type, params.channel, buf);
C
Christoph Hellwig 已提交
4951
	iwl3945_get_measurement(priv, &params, type);
Z
Zhu Yi 已提交
4952 4953 4954 4955 4956 4957

	return count;
}

static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
		   show_measurement, store_measurement);
4958
#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
Z
Zhu Yi 已提交
4959 4960 4961 4962 4963

static ssize_t store_retry_rate(struct device *d,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
4964
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975

	priv->retry_rate = simple_strtoul(buf, NULL, 0);
	if (priv->retry_rate <= 0)
		priv->retry_rate = 1;

	return count;
}

static ssize_t show_retry_rate(struct device *d,
			       struct device_attribute *attr, char *buf)
{
4976
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
4977 4978 4979 4980 4981 4982
	return sprintf(buf, "%d", priv->retry_rate);
}

static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
		   store_retry_rate);

4983

Z
Zhu Yi 已提交
4984 4985 4986 4987
static ssize_t store_power_level(struct device *d,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
4988
	struct iwl_priv *priv = dev_get_drvdata(d);
4989 4990 4991
	int ret;
	unsigned long mode;

Z
Zhu Yi 已提交
4992 4993 4994

	mutex_lock(&priv->mutex);

4995
	if (!iwl_is_ready(priv)) {
4996
		ret = -EAGAIN;
Z
Zhu Yi 已提交
4997 4998 4999
		goto out;
	}

5000 5001 5002
	ret = strict_strtoul(buf, 10, &mode);
	if (ret)
		goto out;
Z
Zhu Yi 已提交
5003

5004 5005 5006 5007
	ret = iwl_power_set_user_mode(priv, mode);
	if (ret) {
		IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
		goto out;
Z
Zhu Yi 已提交
5008
	}
5009
	ret = count;
Z
Zhu Yi 已提交
5010 5011 5012

 out:
	mutex_unlock(&priv->mutex);
5013
	return ret;
Z
Zhu Yi 已提交
5014 5015
}

5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046
static ssize_t show_power_level(struct device *d,
				struct device_attribute *attr, char *buf)
{
	struct iwl_priv *priv = dev_get_drvdata(d);
	int mode = priv->power_data.user_power_setting;
	int system = priv->power_data.system_power_setting;
	int level = priv->power_data.power_mode;
	char *p = buf;

	switch (system) {
	case IWL_POWER_SYS_AUTO:
		p += sprintf(p, "SYSTEM:auto");
		break;
	case IWL_POWER_SYS_AC:
		p += sprintf(p, "SYSTEM:ac");
		break;
	case IWL_POWER_SYS_BATTERY:
		p += sprintf(p, "SYSTEM:battery");
		break;
	}

	p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
			"fixed" : "auto");
	p += sprintf(p, "\tINDEX:%d", level);
	p += sprintf(p, "\n");
	return p - buf + 1;
}

static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
		   show_power_level, store_power_level);

Z
Zhu Yi 已提交
5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
#define MAX_WX_STRING 80

/* Values are in microsecond */
static const s32 timeout_duration[] = {
	350000,
	250000,
	75000,
	37000,
	25000,
};
static const s32 period_duration[] = {
	400000,
	700000,
	1000000,
	1000000,
	1000000
};

static ssize_t show_channels(struct device *d,
			     struct device_attribute *attr, char *buf)
{
5068 5069
	/* all this shit doesn't belong into sysfs anyway */
	return 0;
Z
Zhu Yi 已提交
5070 5071 5072 5073 5074 5075 5076
}

static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);

static ssize_t show_statistics(struct device *d,
			       struct device_attribute *attr, char *buf)
{
5077
	struct iwl_priv *priv = dev_get_drvdata(d);
C
Christoph Hellwig 已提交
5078
	u32 size = sizeof(struct iwl3945_notif_statistics);
Z
Zhu Yi 已提交
5079
	u32 len = 0, ofs = 0;
5080
	u8 *data = (u8 *)&priv->statistics_39;
Z
Zhu Yi 已提交
5081 5082
	int rc = 0;

5083
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
5084 5085 5086
		return -EAGAIN;

	mutex_lock(&priv->mutex);
5087
	rc = iwl_send_statistics_request(priv, 0);
Z
Zhu Yi 已提交
5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114
	mutex_unlock(&priv->mutex);

	if (rc) {
		len = sprintf(buf,
			      "Error sending statistics request: 0x%08X\n", rc);
		return len;
	}

	while (size && (PAGE_SIZE - len)) {
		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
				   PAGE_SIZE - len, 1);
		len = strlen(buf);
		if (PAGE_SIZE - len)
			buf[len++] = '\n';

		ofs += 16;
		size -= min(size, 16U);
	}

	return len;
}

static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);

static ssize_t show_antenna(struct device *d,
			    struct device_attribute *attr, char *buf)
{
5115
	struct iwl_priv *priv = dev_get_drvdata(d);
Z
Zhu Yi 已提交
5116

5117
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
5118 5119
		return -EAGAIN;

5120
	return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
Z
Zhu Yi 已提交
5121 5122 5123 5124 5125 5126
}

static ssize_t store_antenna(struct device *d,
			     struct device_attribute *attr,
			     const char *buf, size_t count)
{
5127
	struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
Z
Zhu Yi 已提交
5128 5129 5130 5131 5132 5133
	int ant;

	if (count == 0)
		return 0;

	if (sscanf(buf, "%1i", &ant) != 1) {
5134
		IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
Z
Zhu Yi 已提交
5135 5136 5137 5138
		return count;
	}

	if ((ant >= 0) && (ant <= 2)) {
5139
		IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
5140
		iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
Z
Zhu Yi 已提交
5141
	} else
5142
		IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
Z
Zhu Yi 已提交
5143 5144 5145 5146 5147 5148 5149 5150 5151 5152


	return count;
}

static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);

static ssize_t show_status(struct device *d,
			   struct device_attribute *attr, char *buf)
{
5153
	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
5154
	if (!iwl_is_alive(priv))
Z
Zhu Yi 已提交
5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167
		return -EAGAIN;
	return sprintf(buf, "0x%08x\n", (int)priv->status);
}

static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);

static ssize_t dump_error_log(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
	char *p = (char *)buf;

	if (p[0] == '1')
5168
		iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data);
Z
Zhu Yi 已提交
5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181

	return strnlen(buf, count);
}

static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);

static ssize_t dump_event_log(struct device *d,
			      struct device_attribute *attr,
			      const char *buf, size_t count)
{
	char *p = (char *)buf;

	if (p[0] == '1')
5182
		iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data);
Z
Zhu Yi 已提交
5183 5184 5185 5186 5187 5188 5189 5190

	return strnlen(buf, count);
}

static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);

/*****************************************************************************
 *
T
Tomas Winkler 已提交
5191
 * driver setup and tear down
Z
Zhu Yi 已提交
5192 5193 5194
 *
 *****************************************************************************/

5195
static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
5196 5197 5198 5199 5200
{
	priv->workqueue = create_workqueue(DRV_NAME);

	init_waitqueue_head(&priv->wait_command_queue);

C
Christoph Hellwig 已提交
5201 5202 5203
	INIT_WORK(&priv->up, iwl3945_bg_up);
	INIT_WORK(&priv->restart, iwl3945_bg_restart);
	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
S
Samuel Ortiz 已提交
5204
	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
C
Christoph Hellwig 已提交
5205 5206 5207
	INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
5208
	INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
S
Samuel Ortiz 已提交
5209 5210 5211 5212
	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
	INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
C
Christoph Hellwig 已提交
5213 5214

	iwl3945_hw_setup_deferred_work(priv);
Z
Zhu Yi 已提交
5215 5216

	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
C
Christoph Hellwig 已提交
5217
		     iwl3945_irq_tasklet, (unsigned long)priv);
Z
Zhu Yi 已提交
5218 5219
}

5220
static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
Z
Zhu Yi 已提交
5221
{
C
Christoph Hellwig 已提交
5222
	iwl3945_hw_cancel_deferred_work(priv);
Z
Zhu Yi 已提交
5223

5224
	cancel_delayed_work_sync(&priv->init_alive_start);
Z
Zhu Yi 已提交
5225 5226 5227 5228 5229
	cancel_delayed_work(&priv->scan_check);
	cancel_delayed_work(&priv->alive_start);
	cancel_work_sync(&priv->beacon_update);
}

C
Christoph Hellwig 已提交
5230
static struct attribute *iwl3945_sysfs_entries[] = {
Z
Zhu Yi 已提交
5231 5232 5233 5234 5235 5236
	&dev_attr_antenna.attr,
	&dev_attr_channels.attr,
	&dev_attr_dump_errors.attr,
	&dev_attr_dump_events.attr,
	&dev_attr_flags.attr,
	&dev_attr_filter_flags.attr,
5237
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
Z
Zhu Yi 已提交
5238 5239 5240 5241 5242 5243 5244 5245
	&dev_attr_measurement.attr,
#endif
	&dev_attr_power_level.attr,
	&dev_attr_retry_rate.attr,
	&dev_attr_statistics.attr,
	&dev_attr_status.attr,
	&dev_attr_temperature.attr,
	&dev_attr_tx_power.attr,
S
Samuel Ortiz 已提交
5246
#ifdef CONFIG_IWLWIFI_DEBUG
5247 5248
	&dev_attr_debug_level.attr,
#endif
Z
Zhu Yi 已提交
5249 5250 5251
	NULL
};

C
Christoph Hellwig 已提交
5252
static struct attribute_group iwl3945_attribute_group = {
Z
Zhu Yi 已提交
5253
	.name = NULL,		/* put in device directory */
C
Christoph Hellwig 已提交
5254
	.attrs = iwl3945_sysfs_entries,
Z
Zhu Yi 已提交
5255 5256
};

C
Christoph Hellwig 已提交
5257 5258 5259 5260 5261 5262 5263 5264
static struct ieee80211_ops iwl3945_hw_ops = {
	.tx = iwl3945_mac_tx,
	.start = iwl3945_mac_start,
	.stop = iwl3945_mac_stop,
	.add_interface = iwl3945_mac_add_interface,
	.remove_interface = iwl3945_mac_remove_interface,
	.config = iwl3945_mac_config,
	.config_interface = iwl3945_mac_config_interface,
5265
	.configure_filter = iwl_configure_filter,
C
Christoph Hellwig 已提交
5266 5267 5268 5269
	.set_key = iwl3945_mac_set_key,
	.get_tx_stats = iwl3945_mac_get_tx_stats,
	.conf_tx = iwl3945_mac_conf_tx,
	.reset_tsf = iwl3945_mac_reset_tsf,
5270
	.bss_info_changed = iwl3945_bss_info_changed,
C
Christoph Hellwig 已提交
5271
	.hw_scan = iwl3945_mac_hw_scan
Z
Zhu Yi 已提交
5272 5273
};

5274
static int iwl3945_init_drv(struct iwl_priv *priv)
5275 5276
{
	int ret;
5277
	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
5278 5279 5280 5281 5282

	priv->retry_rate = 1;
	priv->ibss_beacon = NULL;

	spin_lock_init(&priv->lock);
5283
	spin_lock_init(&priv->power_data.lock);
5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306
	spin_lock_init(&priv->sta_lock);
	spin_lock_init(&priv->hcmd_lock);

	INIT_LIST_HEAD(&priv->free_frames);

	mutex_init(&priv->mutex);

	/* Clear the driver's (not device's) station table */
	iwl3945_clear_stations_table(priv);

	priv->data_retry_limit = -1;
	priv->ieee_channels = NULL;
	priv->ieee_rates = NULL;
	priv->band = IEEE80211_BAND_2GHZ;

	priv->iw_mode = NL80211_IFTYPE_STATION;

	iwl_reset_qos(priv);

	priv->qos_data.qos_active = 0;
	priv->qos_data.qos_cap.val = 0;

	priv->rates_mask = IWL_RATES_MASK;
5307 5308
	/* If power management is turned on, default to CAM mode */
	priv->power_mode = IWL_POWER_MODE_CAM;
5309
	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
5310

5311 5312 5313 5314 5315 5316 5317
	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
			 eeprom->version);
		ret = -EINVAL;
		goto err;
	}
	ret = iwl_init_channel_map(priv);
5318 5319 5320 5321 5322
	if (ret) {
		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
		goto err;
	}

5323 5324 5325 5326 5327 5328
	/* Set up txpower settings in driver for all channels */
	if (iwl3945_txpower_set_from_eeprom(priv)) {
		ret = -EIO;
		goto err_free_channel_map;
	}

5329
	ret = iwlcore_init_geos(priv);
5330 5331 5332 5333
	if (ret) {
		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
		goto err_free_channel_map;
	}
5334 5335 5336 5337 5338 5339 5340 5341
	iwl3945_init_hw_rates(priv, priv->ieee_rates);

	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
			&priv->bands[IEEE80211_BAND_2GHZ];
	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
			&priv->bands[IEEE80211_BAND_5GHZ];
5342 5343 5344 5345

	return 0;

err_free_channel_map:
5346
	iwl_free_channel_map(priv);
5347 5348 5349 5350
err:
	return ret;
}

C
Christoph Hellwig 已提交
5351
static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Z
Zhu Yi 已提交
5352 5353
{
	int err = 0;
5354
	struct iwl_priv *priv;
Z
Zhu Yi 已提交
5355
	struct ieee80211_hw *hw;
5356
	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
5357
	struct iwl3945_eeprom *eeprom;
5358
	unsigned long flags;
Z
Zhu Yi 已提交
5359

5360 5361 5362 5363
	/***********************
	 * 1. Allocating HW data
	 * ********************/

Z
Zhu Yi 已提交
5364 5365
	/* mac80211 allocates memory for this device instance, including
	 *   space for this driver's private structure */
5366
	hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
Z
Zhu Yi 已提交
5367
	if (hw == NULL) {
5368
		printk(KERN_ERR DRV_NAME "Can not allocate network device\n");
Z
Zhu Yi 已提交
5369 5370 5371 5372
		err = -ENOMEM;
		goto out;
	}
	priv = hw->priv;
5373
	SET_IEEE80211_DEV(hw, &pdev->dev);
5374

5375 5376
	if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
	     (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) {
5377 5378 5379
		IWL_ERR(priv,
			"invalid queues_num, should be between %d and %d\n",
			IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
5380 5381 5382 5383
		err = -EINVAL;
		goto out;
	}

5384 5385 5386 5387
	/*
	 * Disabling hardware scan means that mac80211 will perform scans
	 * "the hard way", rather than using device's scan.
	 */
5388
	if (iwl3945_mod_params.disable_hw_scan) {
5389
		IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
5390 5391 5392
		iwl3945_hw_ops.hw_scan = NULL;
	}

5393

5394
	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
5395 5396
	priv->cfg = cfg;
	priv->pci_dev = pdev;
5397

S
Samuel Ortiz 已提交
5398
#ifdef CONFIG_IWLWIFI_DEBUG
5399
	priv->debug_level = iwl3945_mod_params.debug;
Z
Zhu Yi 已提交
5400 5401
	atomic_set(&priv->restrict_refcnt, 0);
#endif
5402 5403 5404
	hw->rate_control_algorithm = "iwl-3945-rs";
	hw->sta_data_size = sizeof(struct iwl3945_sta_priv);

5405
	/* Tell mac80211 our characteristics */
5406
	hw->flags = IEEE80211_HW_SIGNAL_DBM |
5407
		    IEEE80211_HW_NOISE_DBM;
Z
Zhu Yi 已提交
5408

5409 5410 5411 5412
	hw->wiphy->interface_modes =
		BIT(NL80211_IFTYPE_STATION) |
		BIT(NL80211_IFTYPE_ADHOC);

5413
	hw->wiphy->custom_regulatory = true;
5414

5415
	/* 4 EDCA QOS priorities */
Z
Zhu Yi 已提交
5416 5417
	hw->queues = 4;

5418 5419 5420
	/***************************
	 * 2. Initializing PCI bus
	 * *************************/
Z
Zhu Yi 已提交
5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431
	if (pci_enable_device(pdev)) {
		err = -ENODEV;
		goto out_ieee80211_free_hw;
	}

	pci_set_master(pdev);

	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
	if (!err)
		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
	if (err) {
T
Tomas Winkler 已提交
5432
		IWL_WARN(priv, "No suitable DMA available.\n");
Z
Zhu Yi 已提交
5433 5434 5435 5436 5437 5438 5439
		goto out_pci_disable_device;
	}

	pci_set_drvdata(pdev, priv);
	err = pci_request_regions(pdev, DRV_NAME);
	if (err)
		goto out_pci_disable_device;
5440

5441 5442 5443
	/***********************
	 * 3. Read REV Register
	 * ********************/
Z
Zhu Yi 已提交
5444 5445 5446 5447 5448 5449
	priv->hw_base = pci_iomap(pdev, 0, 0);
	if (!priv->hw_base) {
		err = -ENODEV;
		goto out_pci_release_regions;
	}

5450
	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
Z
Zhu Yi 已提交
5451
			(unsigned long long) pci_resource_len(pdev, 0));
5452
	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
Z
Zhu Yi 已提交
5453

5454 5455 5456
	/* We disable the RETRY_TIMEOUT register (0x41) to keep
	 * PCI Tx retries from interfering with C3 CPU state */
	pci_write_config_byte(pdev, 0x41, 0x00);
Z
Zhu Yi 已提交
5457

5458 5459
	/* amp init */
	err = priv->cfg->ops->lib->apm_ops.init(priv);
5460
	if (err < 0) {
5461
		IWL_DEBUG_INFO(priv, "Failed to init APMG\n");
5462
		goto out_iounmap;
5463
	}
Z
Zhu Yi 已提交
5464

5465 5466 5467
	/***********************
	 * 4. Read EEPROM
	 * ********************/
5468

5469
	/* Read the EEPROM */
5470
	err = iwl_eeprom_init(priv);
5471
	if (err) {
5472
		IWL_ERR(priv, "Unable to init EEPROM\n");
5473 5474 5475
		goto out_remove_sysfs;
	}
	/* MAC Address location in EEPROM same for 3945/4965 */
5476 5477
	eeprom = (struct iwl3945_eeprom *)priv->eeprom;
	memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN);
5478
	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr);
5479
	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
Z
Zhu Yi 已提交
5480

5481 5482 5483
	/***********************
	 * 5. Setup HW Constants
	 * ********************/
Z
Zhu Yi 已提交
5484
	/* Device-specific setup */
5485
	if (iwl3945_hw_set_hw_params(priv)) {
5486
		IWL_ERR(priv, "failed to set hw settings\n");
Z
Zhu Yi 已提交
5487 5488 5489
		goto out_iounmap;
	}

5490 5491 5492 5493
	/***********************
	 * 6. Setup priv
	 * ********************/

5494
	err = iwl3945_init_drv(priv);
Z
Zhu Yi 已提交
5495
	if (err) {
5496 5497
		IWL_ERR(priv, "initializing driver failed\n");
		goto out_free_geos;
Z
Zhu Yi 已提交
5498 5499
	}

T
Tomas Winkler 已提交
5500 5501
	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
		priv->cfg->name);
5502 5503 5504 5505 5506 5507 5508

	/***********************************
	 * 7. Initialize Module Parameters
	 * **********************************/

	/* Initialize module parameter values here */
	/* Disable radio (SW RF KILL) via parameter when loading driver */
5509
	if (iwl3945_mod_params.disable) {
5510
		set_bit(STATUS_RF_KILL_SW, &priv->status);
5511
		IWL_DEBUG_INFO(priv, "Radio disabled.\n");
5512 5513
	}

5514 5515 5516 5517 5518 5519 5520 5521 5522

	/***********************
	 * 8. Setup Services
	 * ********************/

	spin_lock_irqsave(&priv->lock, flags);
	iwl3945_disable_interrupts(priv);
	spin_unlock_irqrestore(&priv->lock, flags);

5523 5524 5525 5526 5527 5528 5529 5530 5531
	pci_enable_msi(priv->pci_dev);

	err = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
			  DRV_NAME, priv);
	if (err) {
		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
		goto out_disable_msi;
	}

5532
	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
5533
	if (err) {
5534
		IWL_ERR(priv, "failed to create sysfs device attributes\n");
5535
		goto out_release_irq;
5536 5537
	}

5538 5539
	iwl_set_rxon_channel(priv,
			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
5540 5541 5542 5543
	iwl3945_setup_deferred_work(priv);
	iwl3945_setup_rx_handlers(priv);

	/*********************************
5544
	 * 9. Setup and Register mac80211
5545 5546
	 * *******************************/

5547 5548
	err = ieee80211_register_hw(priv->hw);
	if (err) {
5549
		IWL_ERR(priv, "Failed to register network device: %d\n", err);
5550
		goto  out_remove_sysfs;
5551
	}
Z
Zhu Yi 已提交
5552

5553 5554
	priv->hw->conf.beacon_int = 100;
	priv->mac80211_registered = 1;
5555

S
Samuel Ortiz 已提交
5556
	err = iwl_rfkill_init(priv);
5557
	if (err)
5558
		IWL_ERR(priv, "Unable to initialize RFKILL system. "
5559 5560
				  "Ignoring error: %d\n", err);

5561 5562 5563 5564
	/* Start monitoring the killswitch */
	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
			   2 * HZ);

Z
Zhu Yi 已提交
5565 5566
	return 0;

5567 5568
 out_remove_sysfs:
	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
5569
 out_free_geos:
5570
	iwlcore_free_geos(priv);
Z
Zhu Yi 已提交
5571 5572

 out_release_irq:
5573
	free_irq(priv->pci_dev->irq, priv);
Z
Zhu Yi 已提交
5574 5575
	destroy_workqueue(priv->workqueue);
	priv->workqueue = NULL;
5576
	iwl3945_unset_hw_params(priv);
5577 5578
 out_disable_msi:
	pci_disable_msi(priv->pci_dev);
Z
Zhu Yi 已提交
5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591
 out_iounmap:
	pci_iounmap(pdev, priv->hw_base);
 out_pci_release_regions:
	pci_release_regions(pdev);
 out_pci_disable_device:
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
 out_ieee80211_free_hw:
	ieee80211_free_hw(priv->hw);
 out:
	return err;
}

5592
static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
Z
Zhu Yi 已提交
5593
{
5594
	struct iwl_priv *priv = pci_get_drvdata(pdev);
5595
	unsigned long flags;
Z
Zhu Yi 已提交
5596 5597 5598 5599

	if (!priv)
		return;

5600
	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
Z
Zhu Yi 已提交
5601 5602

	set_bit(STATUS_EXIT_PENDING, &priv->status);
5603

5604 5605 5606 5607 5608 5609
	if (priv->mac80211_registered) {
		ieee80211_unregister_hw(priv->hw);
		priv->mac80211_registered = 0;
	} else {
		iwl3945_down(priv);
	}
Z
Zhu Yi 已提交
5610

5611 5612 5613 5614 5615 5616 5617 5618 5619
	/* make sure we flush any pending irq or
	 * tasklet for the driver
	 */
	spin_lock_irqsave(&priv->lock, flags);
	iwl3945_disable_interrupts(priv);
	spin_unlock_irqrestore(&priv->lock, flags);

	iwl_synchronize_irq(priv);

C
Christoph Hellwig 已提交
5620
	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
Z
Zhu Yi 已提交
5621

S
Samuel Ortiz 已提交
5622
	iwl_rfkill_unregister(priv);
5623 5624
	cancel_delayed_work(&priv->rfkill_poll);

C
Christoph Hellwig 已提交
5625
	iwl3945_dealloc_ucode_pci(priv);
Z
Zhu Yi 已提交
5626 5627

	if (priv->rxq.bd)
5628
		iwl_rx_queue_free(priv, &priv->rxq);
C
Christoph Hellwig 已提交
5629
	iwl3945_hw_txq_ctx_free(priv);
Z
Zhu Yi 已提交
5630

5631
	iwl3945_unset_hw_params(priv);
C
Christoph Hellwig 已提交
5632
	iwl3945_clear_stations_table(priv);
Z
Zhu Yi 已提交
5633

5634 5635 5636
	/*netif_stop_queue(dev); */
	flush_workqueue(priv->workqueue);

C
Christoph Hellwig 已提交
5637
	/* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
Z
Zhu Yi 已提交
5638 5639 5640 5641 5642
	 * priv->workqueue... so we can't take down the workqueue
	 * until now... */
	destroy_workqueue(priv->workqueue);
	priv->workqueue = NULL;

5643 5644 5645
	free_irq(pdev->irq, priv);
	pci_disable_msi(pdev);

Z
Zhu Yi 已提交
5646 5647 5648 5649 5650
	pci_iounmap(pdev, priv->hw_base);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);

5651
	iwl_free_channel_map(priv);
5652
	iwlcore_free_geos(priv);
W
Winkler, Tomas 已提交
5653
	kfree(priv->scan);
Z
Zhu Yi 已提交
5654 5655 5656 5657 5658 5659 5660 5661
	if (priv->ibss_beacon)
		dev_kfree_skb(priv->ibss_beacon);

	ieee80211_free_hw(priv->hw);
}

#ifdef CONFIG_PM

C
Christoph Hellwig 已提交
5662
static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
Z
Zhu Yi 已提交
5663
{
5664
	struct iwl_priv *priv = pci_get_drvdata(pdev);
Z
Zhu Yi 已提交
5665

5666 5667 5668 5669 5670
	if (priv->is_open) {
		set_bit(STATUS_IN_SUSPEND, &priv->status);
		iwl3945_mac_stop(priv->hw);
		priv->is_open = 1;
	}
5671 5672
	pci_save_state(pdev);
	pci_disable_device(pdev);
Z
Zhu Yi 已提交
5673 5674 5675 5676 5677
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

C
Christoph Hellwig 已提交
5678
static int iwl3945_pci_resume(struct pci_dev *pdev)
Z
Zhu Yi 已提交
5679
{
5680
	struct iwl_priv *priv = pci_get_drvdata(pdev);
5681
	int ret;
Z
Zhu Yi 已提交
5682 5683

	pci_set_power_state(pdev, PCI_D0);
5684 5685 5686
	ret = pci_enable_device(pdev);
	if (ret)
		return ret;
5687
	pci_restore_state(pdev);
Z
Zhu Yi 已提交
5688

5689 5690
	if (priv->is_open)
		iwl3945_mac_start(priv->hw);
Z
Zhu Yi 已提交
5691

5692
	clear_bit(STATUS_IN_SUSPEND, &priv->status);
Z
Zhu Yi 已提交
5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703
	return 0;
}

#endif /* CONFIG_PM */

/*****************************************************************************
 *
 * driver and module entry point
 *
 *****************************************************************************/

C
Christoph Hellwig 已提交
5704
static struct pci_driver iwl3945_driver = {
Z
Zhu Yi 已提交
5705
	.name = DRV_NAME,
C
Christoph Hellwig 已提交
5706 5707 5708
	.id_table = iwl3945_hw_card_ids,
	.probe = iwl3945_pci_probe,
	.remove = __devexit_p(iwl3945_pci_remove),
Z
Zhu Yi 已提交
5709
#ifdef CONFIG_PM
C
Christoph Hellwig 已提交
5710 5711
	.suspend = iwl3945_pci_suspend,
	.resume = iwl3945_pci_resume,
Z
Zhu Yi 已提交
5712 5713 5714
#endif
};

C
Christoph Hellwig 已提交
5715
static int __init iwl3945_init(void)
Z
Zhu Yi 已提交
5716 5717 5718 5719 5720
{

	int ret;
	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
5721 5722 5723

	ret = iwl3945_rate_control_register();
	if (ret) {
5724 5725
		printk(KERN_ERR DRV_NAME
		       "Unable to register rate control algorithm: %d\n", ret);
5726 5727 5728
		return ret;
	}

C
Christoph Hellwig 已提交
5729
	ret = pci_register_driver(&iwl3945_driver);
Z
Zhu Yi 已提交
5730
	if (ret) {
5731
		printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
5732
		goto error_register;
Z
Zhu Yi 已提交
5733 5734 5735
	}

	return ret;
5736 5737 5738 5739

error_register:
	iwl3945_rate_control_unregister();
	return ret;
Z
Zhu Yi 已提交
5740 5741
}

C
Christoph Hellwig 已提交
5742
static void __exit iwl3945_exit(void)
Z
Zhu Yi 已提交
5743
{
C
Christoph Hellwig 已提交
5744
	pci_unregister_driver(&iwl3945_driver);
5745
	iwl3945_rate_control_unregister();
Z
Zhu Yi 已提交
5746 5747
}

5748
MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
5749

5750
module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
Z
Zhu Yi 已提交
5751
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
5752
module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
Z
Zhu Yi 已提交
5753
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
5754 5755 5756
module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto,
		 "using software crypto (default 1 [software])\n");
5757
module_param_named(debug, iwl3945_mod_params.debug, uint, 0444);
Z
Zhu Yi 已提交
5758
MODULE_PARM_DESC(debug, "debug output mask");
5759
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
Z
Zhu Yi 已提交
5760 5761
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");

5762
module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444);
Z
Zhu Yi 已提交
5763 5764
MODULE_PARM_DESC(queues_num, "number of hw queues.");

5765 5766 5767
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");

C
Christoph Hellwig 已提交
5768 5769
module_exit(iwl3945_exit);
module_init(iwl3945_init);