iwl-sta.c 39.2 KB
Newer Older
1 2
/******************************************************************************
 *
3
 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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>
26 27 28 29 30
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <net/mac80211.h>
31
#include <linux/etherdevice.h>
32
#include <linux/sched.h>
33

34
#include "iwl-dev.h"
35 36
#include "iwl-core.h"
#include "iwl-sta.h"
37

38
/* priv->sta_lock must be held */
39 40 41
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{

42
	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
43 44
		IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n",
			sta_id, priv->stations[sta_id].sta.sta.addr);
45

46 47 48 49 50 51 52 53 54
	if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
		IWL_DEBUG_ASSOC(priv,
				"STA id %u addr %pM already present in uCode (according to driver)\n",
				sta_id, priv->stations[sta_id].sta.sta.addr);
	} else {
		priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
				sta_id, priv->stations[sta_id].sta.sta.addr);
	}
55 56
}

57 58 59 60
static void iwl_process_add_sta_resp(struct iwl_priv *priv,
				     struct iwl_addsta_cmd *addsta,
				     struct iwl_rx_packet *pkt,
				     bool sync)
61
{
62
	u8 sta_id = addsta->sta.sta_id;
63
	unsigned long flags;
64

Zhu Yi's avatar
Zhu Yi committed
65
	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
66
		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
67
			pkt->hdr.flags);
68
		return;
69 70
	}

71 72 73 74 75
	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
		       sta_id);

	spin_lock_irqsave(&priv->sta_lock, flags);

Zhu Yi's avatar
Zhu Yi committed
76
	switch (pkt->u.add_sta.status) {
77
	case ADD_STA_SUCCESS_MSK:
78
		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
79
		iwl_sta_ucode_activate(priv, sta_id);
80 81 82 83 84 85 86 87 88 89
		break;
	case ADD_STA_NO_ROOM_IN_TABLE:
		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
			sta_id);
		break;
	case ADD_STA_NO_BLOCK_ACK_RESOURCE:
		IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n",
			sta_id);
		break;
	case ADD_STA_MODIFY_NON_EXIST_STA:
90
		IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
91 92
			sta_id);
		break;
93
	default:
94 95
		IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
				pkt->u.add_sta.status);
96 97
		break;
	}
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

	IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
		       priv->stations[sta_id].sta.mode ==
		       STA_CONTROL_MODIFY_MSK ?  "Modified" : "Added",
		       sta_id, priv->stations[sta_id].sta.sta.addr);

	/*
	 * XXX: The MAC address in the command buffer is often changed from
	 * the original sent to the device. That is, the MAC address
	 * written to the command buffer often is not the same MAC adress
	 * read from the command buffer when the command returns. This
	 * issue has not yet been resolved and this debugging is left to
	 * observe the problem.
	 */
	IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
		       priv->stations[sta_id].sta.mode ==
		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
		       addsta->sta.addr);
	spin_unlock_irqrestore(&priv->sta_lock, flags);
}

static void iwl_add_sta_callback(struct iwl_priv *priv,
				 struct iwl_device_cmd *cmd,
				 struct iwl_rx_packet *pkt)
{
	struct iwl_addsta_cmd *addsta =
		(struct iwl_addsta_cmd *)cmd->cmd.payload;

	iwl_process_add_sta_resp(priv, addsta, pkt, false);

128 129
}

130
int iwl_send_add_sta(struct iwl_priv *priv,
131 132
		     struct iwl_addsta_cmd *sta, u8 flags)
{
Zhu Yi's avatar
Zhu Yi committed
133
	struct iwl_rx_packet *pkt = NULL;
134 135 136 137
	int ret = 0;
	u8 data[sizeof(*sta)];
	struct iwl_host_cmd cmd = {
		.id = REPLY_ADD_STA,
138
		.flags = flags,
139 140
		.data = data,
	};
141
	u8 sta_id __maybe_unused = sta->sta.sta_id;
142 143 144

	IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
		       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
145

146
	if (flags & CMD_ASYNC)
147
		cmd.callback = iwl_add_sta_callback;
148
	else
149
		cmd.flags |= CMD_WANT_SKB;
150 151 152 153 154 155 156 157

	cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
	ret = iwl_send_cmd(priv, &cmd);

	if (ret || (flags & CMD_ASYNC))
		return ret;

	if (ret == 0) {
158 159
		pkt = (struct iwl_rx_packet *)cmd.reply_page;
		iwl_process_add_sta_resp(priv, sta, pkt, true);
160
	}
161
	iwl_free_pages(priv, cmd.reply_page);
162 163 164

	return ret;
}
165
EXPORT_SYMBOL(iwl_send_add_sta);
166

167
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
168
				   struct ieee80211_sta_ht_cap *sta_ht_inf)
169 170 171 172 173 174 175
{
	__le32 sta_flags;
	u8 mimo_ps_mode;

	if (!sta_ht_inf || !sta_ht_inf->ht_supported)
		goto done;

176
	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
177 178 179 180 181
	IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
			"static" :
			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
			"dynamic" : "disabled");
182 183 184 185 186 187

	sta_flags = priv->stations[index].sta.station_flags;

	sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);

	switch (mimo_ps_mode) {
188
	case WLAN_HT_CAP_SM_PS_STATIC:
189 190
		sta_flags |= STA_FLG_MIMO_DIS_MSK;
		break;
191
	case WLAN_HT_CAP_SM_PS_DYNAMIC:
192 193
		sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
		break;
194
	case WLAN_HT_CAP_SM_PS_DISABLED:
195 196
		break;
	default:
197
		IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
198 199 200 201 202 203 204 205 206
		break;
	}

	sta_flags |= cpu_to_le32(
	      (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);

	sta_flags |= cpu_to_le32(
	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);

207 208
	if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
		sta_flags |= STA_FLG_HT40_EN_MSK;
209
	else
210
		sta_flags &= ~STA_FLG_HT40_EN_MSK;
211 212 213 214 215 216 217

	priv->stations[index].sta.station_flags = sta_flags;
 done:
	return;
}

/**
218 219 220
 * iwl_prep_station - Prepare station information for addition
 *
 * should be called with sta_lock held
221
 */
222 223 224
static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
			   bool is_ap,
			   struct ieee80211_sta_ht_cap *ht_info)
225 226
{
	struct iwl_station_entry *station;
227
	int i;
228
	u8 sta_id = IWL_INVALID_STATION;
229
	u16 rate;
230 231

	if (is_ap)
232
		sta_id = IWL_AP_ID;
233
	else if (is_broadcast_ether_addr(addr))
234
		sta_id = priv->hw_params.bcast_sta_id;
235 236 237 238
	else
		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
			if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
						addr)) {
239
				sta_id = i;
240 241 242 243
				break;
			}

			if (!priv->stations[i].used &&
244 245
			    sta_id == IWL_INVALID_STATION)
				sta_id = i;
246 247
		}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
	/*
	 * These two conditions have the same outcome, but keep them
	 * separate
	 */
	if (unlikely(sta_id == IWL_INVALID_STATION))
		return sta_id;

	/*
	 * uCode is not able to deal with multiple requests to add a
	 * station. Keep track if one is in progress so that we do not send
	 * another.
	 */
	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
		IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n",
				sta_id);
263
		return sta_id;
264 265
	}

266 267
	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
268
	    !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
269 270
		IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n",
				sta_id, addr);
271
		return sta_id;
272 273
	}

274 275
	station = &priv->stations[sta_id];
	station->used = IWL_STA_DRIVER_ACTIVE;
276
	IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
277
			sta_id, addr);
278 279 280 281 282 283
	priv->num_stations++;

	/* Set up the REPLY_ADD_STA command to send to device */
	memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
	station->sta.mode = 0;
284
	station->sta.sta.sta_id = sta_id;
285 286
	station->sta.station_flags = 0;

287 288 289 290 291 292
	/*
	 * OK to call unconditionally, since local stations (IBSS BSSID
	 * STA and broadcast STA) pass in a NULL ht_info, and mac80211
	 * doesn't allow HT IBSS.
	 */
	iwl_set_ht_add_station(priv, sta_id, ht_info);
293

294 295 296 297 298 299
	/* 3945 only */
	rate = (priv->band == IEEE80211_BAND_5GHZ) ?
		IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP;
	/* Turn on both antennas for the station... */
	station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	return sta_id;

}

#define STA_WAIT_TIMEOUT (HZ/2)

/**
 * iwl_add_station_common -
 */
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
				  bool is_ap,
				  struct ieee80211_sta_ht_cap *ht_info,
				  u8 *sta_id_r)
{
	unsigned long flags_spin;
	int ret = 0;
	u8 sta_id;
317
	struct iwl_addsta_cmd sta_cmd;
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

	*sta_id_r = 0;
	spin_lock_irqsave(&priv->sta_lock, flags_spin);
	sta_id = iwl_prep_station(priv, addr, is_ap, ht_info);
	if (sta_id == IWL_INVALID_STATION) {
		IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
			addr);
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return -EINVAL;
	}

	/*
	 * uCode is not able to deal with multiple requests to add a
	 * station. Keep track if one is in progress so that we do not send
	 * another.
	 */
	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
		IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n",
			       sta_id);
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return -EEXIST;
	}

	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
		IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n",
				sta_id, addr);
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
		return -EEXIST;
	}

	priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
350
	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
351 352 353
	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);

	/* Add station to device's station table */
354
	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
355 356
	if (ret) {
		spin_lock_irqsave(&priv->sta_lock, flags_spin);
357 358
		IWL_ERR(priv, "Adding station %pM failed.\n",
			priv->stations[sta_id].sta.sta.addr);
359 360 361 362 363 364
		priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
		priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
	}
	*sta_id_r = sta_id;
	return ret;
365
}
366
EXPORT_SYMBOL(iwl_add_station_common);
367

368 369
static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
						     u8 sta_id)
370
{
371
	int i, r;
372
	struct iwl_link_quality_cmd *link_cmd;
373 374
	u32 rate_flags;

375 376 377 378 379
	link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
	if (!link_cmd) {
		IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
		return NULL;
	}
380 381
	/* Set up the rate scaling to start at selected rate, fall back
	 * all the way down to 1M in IEEE order, and then spin on 1M */
382
	if (priv->band == IEEE80211_BAND_5GHZ)
383 384 385
		r = IWL_RATE_6M_INDEX;
	else
		r = IWL_RATE_1M_INDEX;
386

387 388 389 390
	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
		rate_flags = 0;
		if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
			rate_flags |= RATE_MCS_CCK_MSK;
391

392 393
		rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
				RATE_MCS_ANT_POS;
394

395
		link_cmd->rs_table[i].rate_n_flags =
396 397 398
			iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
		r = iwl_get_prev_ieee_rate(r);
	}
399

400
	link_cmd->general_params.single_stream_ant_msk =
401
				first_antenna(priv->hw_params.valid_tx_ant);
402

403
	link_cmd->general_params.dual_stream_ant_msk =
404 405
		priv->hw_params.valid_tx_ant &
		~first_antenna(priv->hw_params.valid_tx_ant);
406 407
	if (!link_cmd->general_params.dual_stream_ant_msk) {
		link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
408
	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
409
		link_cmd->general_params.dual_stream_ant_msk =
410 411 412
			priv->hw_params.valid_tx_ant;
	}

413 414
	link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
	link_cmd->agg_params.agg_time_limit =
415
		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
416

417
	link_cmd->sta_id = sta_id;
418

419
	return link_cmd;
420 421
}

422
/*
423
 * iwl_add_bssid_station - Add the special IBSS BSSID station
424 425 426
 *
 * Function sleeps.
 */
427
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
Johannes Berg's avatar
Johannes Berg committed
428
			  u8 *sta_id_r)
429
{
430 431
	int ret;
	u8 sta_id;
432 433
	struct iwl_link_quality_cmd *link_cmd;
	unsigned long flags;
434

435
	if (sta_id_r)
Johannes Berg's avatar
Johannes Berg committed
436 437
		*sta_id_r = IWL_INVALID_STATION;

438 439 440 441
	ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
	if (ret) {
		IWL_ERR(priv, "Unable to add station %pM\n", addr);
		return ret;
442 443
	}

Johannes Berg's avatar
Johannes Berg committed
444 445 446
	if (sta_id_r)
		*sta_id_r = sta_id;

447 448 449 450 451
	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].used |= IWL_STA_LOCAL;
	spin_unlock_irqrestore(&priv->sta_lock, flags);

	if (init_rs) {
452
		/* Set up default rate scaling table in device's station table */
453
		link_cmd = iwl_sta_alloc_lq(priv, sta_id);
454 455 456 457 458
		if (!link_cmd) {
			IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
				addr);
			return -ENOMEM;
		}
459 460 461 462 463

		ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true);
		if (ret)
			IWL_ERR(priv, "Link quality command failed (%d)\n", ret);

464 465 466 467 468
		spin_lock_irqsave(&priv->sta_lock, flags);
		priv->stations[sta_id].lq = link_cmd;
		spin_unlock_irqrestore(&priv->sta_lock, flags);
	}

469 470
	return 0;
}
471
EXPORT_SYMBOL(iwl_add_bssid_station);
472 473 474 475 476 477 478 479 480

/**
 * iwl_sta_ucode_deactivate - deactivate ucode status for a station
 *
 * priv->sta_lock must be held
 */
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
{
	/* Ucode must be active and driver must be non active */
481 482
	if ((priv->stations[sta_id].used &
	     (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE)
483 484 485 486 487 488
		IWL_ERR(priv, "removed non active STA %u\n", sta_id);

	priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;

	memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
	IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
489 490
}

491
static int iwl_send_remove_station(struct iwl_priv *priv,
492
				   const u8 *addr, int sta_id)
493
{
Zhu Yi's avatar
Zhu Yi committed
494
	struct iwl_rx_packet *pkt;
495 496
	int ret;

497
	unsigned long flags_spin;
498 499 500 501 502
	struct iwl_rem_sta_cmd rm_sta_cmd;

	struct iwl_host_cmd cmd = {
		.id = REPLY_REMOVE_STA,
		.len = sizeof(struct iwl_rem_sta_cmd),
503
		.flags = CMD_SYNC,
504 505 506 507 508
		.data = &rm_sta_cmd,
	};

	memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
	rm_sta_cmd.num_sta = 1;
509
	memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
510 511

	cmd.flags |= CMD_WANT_SKB;
512 513 514

	ret = iwl_send_cmd(priv, &cmd);

515
	if (ret)
516 517
		return ret;

Zhu Yi's avatar
Zhu Yi committed
518 519
	pkt = (struct iwl_rx_packet *)cmd.reply_page;
	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
520
		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
Zhu Yi's avatar
Zhu Yi committed
521
			  pkt->hdr.flags);
522 523 524 525
		ret = -EIO;
	}

	if (!ret) {
Zhu Yi's avatar
Zhu Yi committed
526
		switch (pkt->u.rem_sta.status) {
527
		case REM_STA_SUCCESS_MSK:
528
			spin_lock_irqsave(&priv->sta_lock, flags_spin);
529
			iwl_sta_ucode_deactivate(priv, sta_id);
530
			spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
531
			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
532 533 534
			break;
		default:
			ret = -EIO;
535
			IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
536 537 538
			break;
		}
	}
539
	iwl_free_pages(priv, cmd.reply_page);
540 541 542

	return ret;
}
543

544 545 546
/**
 * iwl_remove_station - Remove driver's knowledge of station.
 */
Johannes Berg's avatar
Johannes Berg committed
547 548
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
		       const u8 *addr)
549
{
Johannes Berg's avatar
Johannes Berg committed
550
	unsigned long flags;
551 552 553

	if (!iwl_is_ready(priv)) {
		IWL_DEBUG_INFO(priv,
554
			"Unable to remove station %pM, device not ready.\n",
555
			addr);
556 557 558 559 560 561 562
		/*
		 * It is typical for stations to be removed when we are
		 * going down. Return success since device will be down
		 * soon anyway
		 */
		return 0;
	}
563

Johannes Berg's avatar
Johannes Berg committed
564 565
	IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d  %pM\n",
			sta_id, addr);
566

Johannes Berg's avatar
Johannes Berg committed
567 568
	if (WARN_ON(sta_id == IWL_INVALID_STATION))
		return -EINVAL;
569

Johannes Berg's avatar
Johannes Berg committed
570
	spin_lock_irqsave(&priv->sta_lock, flags);
571 572

	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
573
		IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
574
				addr);
Johannes Berg's avatar
Johannes Berg committed
575
		goto out_err;
576 577 578
	}

	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
579
		IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
580
				addr);
Johannes Berg's avatar
Johannes Berg committed
581
		goto out_err;
582 583
	}

584 585 586 587
	if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
		kfree(priv->stations[sta_id].lq);
		priv->stations[sta_id].lq = NULL;
	}
588 589 590 591 592

	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;

	priv->num_stations--;

593
	BUG_ON(priv->num_stations < 0);
594

595
	spin_unlock_irqrestore(&priv->sta_lock, flags);
596

597
	return iwl_send_remove_station(priv, addr, sta_id);
Johannes Berg's avatar
Johannes Berg committed
598
out_err:
599
	spin_unlock_irqrestore(&priv->sta_lock, flags);
Johannes Berg's avatar
Johannes Berg committed
600
	return -EINVAL;
601
}
602
EXPORT_SYMBOL_GPL(iwl_remove_station);
603

604
/**
605 606 607 608 609 610
 * iwl_clear_ucode_stations - clear ucode station table bits
 *
 * This function clears all the bits in the driver indicating
 * which stations are active in the ucode. Call when something
 * other than explicit station management would cause this in
 * the ucode, e.g. unassociated RXON.
611
 */
612
void iwl_clear_ucode_stations(struct iwl_priv *priv)
613
{
614
	int i;
615 616 617
	unsigned long flags_spin;
	bool cleared = false;

618
	IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
619

620
	spin_lock_irqsave(&priv->sta_lock, flags_spin);
621 622 623 624 625
	for (i = 0; i < priv->hw_params.max_stations; i++) {
		if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
			IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
			priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
			cleared = true;
626 627 628 629 630 631 632 633
		}
	}
	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);

	if (!cleared)
		IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
}
EXPORT_SYMBOL(iwl_clear_ucode_stations);
634

635 636 637 638 639
/**
 * iwl_restore_stations() - Restore driver known stations to device
 *
 * All stations considered active by driver, but not present in ucode, is
 * restored.
640 641
 *
 * Function sleeps.
642 643 644
 */
void iwl_restore_stations(struct iwl_priv *priv)
{
645 646
	struct iwl_addsta_cmd sta_cmd;
	struct iwl_link_quality_cmd lq;
647 648 649
	unsigned long flags_spin;
	int i;
	bool found = false;
650
	int ret;
651
	bool send_lq;
652

653 654 655 656
	if (!iwl_is_ready(priv)) {
		IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
		return;
	}
657

658 659 660 661 662 663 664 665 666 667 668 669
	IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
	spin_lock_irqsave(&priv->sta_lock, flags_spin);
	for (i = 0; i < priv->hw_params.max_stations; i++) {
		if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
			    !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
			IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
					priv->stations[i].sta.sta.addr);
			priv->stations[i].sta.mode = 0;
			priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
			found = true;
		}
	}
670

671 672
	for (i = 0; i < priv->hw_params.max_stations; i++) {
		if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
673 674 675 676 677 678 679 680
			memcpy(&sta_cmd, &priv->stations[i].sta,
			       sizeof(struct iwl_addsta_cmd));
			send_lq = false;
			if (priv->stations[i].lq) {
				memcpy(&lq, priv->stations[i].lq,
				       sizeof(struct iwl_link_quality_cmd));
				send_lq = true;
			}
681
			spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
682
			ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
683 684
			if (ret) {
				spin_lock_irqsave(&priv->sta_lock, flags_spin);
685 686
				IWL_ERR(priv, "Adding station %pM failed.\n",
					priv->stations[i].sta.sta.addr);
687 688 689 690 691 692 693 694
				priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE;
				priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
				spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
			}
			/*
			 * Rate scaling has already been initialized, send
			 * current LQ command
			 */
695 696
			if (send_lq)
				iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
697
			spin_lock_irqsave(&priv->sta_lock, flags_spin);
698 699
			priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
		}
700 701
	}

702 703 704 705
	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
	if (!found)
		IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n");
	else
706
		IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n");
707
}
708
EXPORT_SYMBOL(iwl_restore_stations);
709

710
int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
711 712 713 714
{
	int i;

	for (i = 0; i < STA_KEY_MAX_NUM; i++)
715
		if (!test_and_set_bit(i, &priv->ucode_key_table))
716 717
			return i;

718
	return WEP_INVALID_OFFSET;
719
}
720
EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
721

722
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
723 724 725 726 727 728 729 730 731
{
	int i, not_empty = 0;
	u8 buff[sizeof(struct iwl_wep_cmd) +
		sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
	struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
	size_t cmd_size  = sizeof(struct iwl_wep_cmd);
	struct iwl_host_cmd cmd = {
		.id = REPLY_WEPKEY,
		.data = wep_cmd,
732
		.flags = CMD_SYNC,
733 734
	};

735 736
	might_sleep();

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
	memset(wep_cmd, 0, cmd_size +
			(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));

	for (i = 0; i < WEP_KEYS_MAX ; i++) {
		wep_cmd->key[i].key_index = i;
		if (priv->wep_keys[i].key_size) {
			wep_cmd->key[i].key_offset = i;
			not_empty = 1;
		} else {
			wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
		}

		wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
		memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
				priv->wep_keys[i].key_size);
	}

	wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
	wep_cmd->num_keys = WEP_KEYS_MAX;

	cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;

	cmd.len = cmd_size;

	if (not_empty || send_if_empty)
		return iwl_send_cmd(priv, &cmd);
	else
		return 0;
}
766 767 768 769 770 771 772 773

int iwl_restore_default_wep_keys(struct iwl_priv *priv)
{
	WARN_ON(!mutex_is_locked(&priv->mutex));

	return iwl_send_static_wepkey_cmd(priv, 0);
}
EXPORT_SYMBOL(iwl_restore_default_wep_keys);
774 775

int iwl_remove_default_wep_key(struct iwl_priv *priv,
776
			       struct ieee80211_key_conf *keyconf)
777 778 779
{
	int ret;

780 781
	WARN_ON(!mutex_is_locked(&priv->mutex));

782 783
	IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
		      keyconf->keyidx);
784 785

	memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
786 787
	if (iwl_is_rfkill(priv)) {
		IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
788
		/* but keys in device are clear anyway so return success */
789 790
		return 0;
	}
791
	ret = iwl_send_static_wepkey_cmd(priv, 1);
792
	IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
793
		      keyconf->keyidx, ret);
794 795 796

	return ret;
}
797
EXPORT_SYMBOL(iwl_remove_default_wep_key);
798 799 800 801 802

int iwl_set_default_wep_key(struct iwl_priv *priv,
			    struct ieee80211_key_conf *keyconf)
{
	int ret;
803 804

	WARN_ON(!mutex_is_locked(&priv->mutex));
805

806 807
	if (keyconf->keylen != WEP_KEY_LEN_128 &&
	    keyconf->keylen != WEP_KEY_LEN_64) {
808
		IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
809 810 811
		return -EINVAL;
	}

812
	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
813
	keyconf->hw_key_idx = HW_KEY_DEFAULT;
814 815 816 817 818 819 820
	priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;

	priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
	memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
							keyconf->keylen);

	ret = iwl_send_static_wepkey_cmd(priv, 0);
821
	IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
822
		keyconf->keylen, keyconf->keyidx, ret);
823 824 825

	return ret;
}
826
EXPORT_SYMBOL(iwl_set_default_wep_key);
827

828
static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
				struct ieee80211_key_conf *keyconf,
				u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
	int ret;

	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;

	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
	key_flags &= ~STA_KEY_FLG_INVALID;

	if (keyconf->keylen == WEP_KEY_LEN_128)
		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;

Tomas Winkler's avatar
Tomas Winkler committed
845
	if (sta_id == priv->hw_params.bcast_sta_id)
846 847 848 849 850 851 852 853 854 855 856 857 858 859
		key_flags |= STA_KEY_MULTICAST_MSK;

	spin_lock_irqsave(&priv->sta_lock, flags);

	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;

	memcpy(priv->stations[sta_id].keyinfo.key,
				keyconf->key, keyconf->keylen);

	memcpy(&priv->stations[sta_id].sta.key.key[3],
				keyconf->key, keyconf->keylen);

860 861 862
	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
			== STA_KEY_FLG_NO_ENC)
		priv->stations[sta_id].sta.key.key_offset =
863
				 iwl_get_free_ucode_key_index(priv);
864 865
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */
866

867
	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Jiri Slaby's avatar
Jiri Slaby committed
868
		"no space for a new key");
869

870
	priv->stations[sta_id].sta.key.key_flags = key_flags;
871 872 873
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

874
	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
875 876 877 878 879

	spin_unlock_irqrestore(&priv->sta_lock, flags);

	return ret;
}
880 881 882 883 884 885 886

static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
				   struct ieee80211_key_conf *keyconf,
				   u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
887
	int ret;
888 889 890 891 892

	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
	key_flags &= ~STA_KEY_FLG_INVALID;

Tomas Winkler's avatar
Tomas Winkler committed
893
	if (sta_id == priv->hw_params.bcast_sta_id)
894 895 896 897 898 899 900 901 902 903 904 905 906 907
		key_flags |= STA_KEY_MULTICAST_MSK;

	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;

	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;

	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
	       keyconf->keylen);

	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
	       keyconf->keylen);

908 909 910 911 912 913 914
	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
			== STA_KEY_FLG_NO_ENC)
		priv->stations[sta_id].sta.key.key_offset =
				 iwl_get_free_ucode_key_index(priv);
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */

915
	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Jiri Slaby's avatar
Jiri Slaby committed
916
		"no space for a new key");
917

918 919 920 921
	priv->stations[sta_id].sta.key.key_flags = key_flags;
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

922 923
	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);

924 925
	spin_unlock_irqrestore(&priv->sta_lock, flags);

926
	return ret;
927 928 929 930 931 932 933 934
}

static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
				   struct ieee80211_key_conf *keyconf,
				   u8 sta_id)
{
	unsigned long flags;
	int ret = 0;
935 936 937 938 939 940 941 942
	__le16 key_flags = 0;

	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
	key_flags &= ~STA_KEY_FLG_INVALID;

	if (sta_id == priv->hw_params.bcast_sta_id)
		key_flags |= STA_KEY_MULTICAST_MSK;
943 944 945 946 947 948 949 950

	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;

	spin_lock_irqsave(&priv->sta_lock, flags);

	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
	priv->stations[sta_id].keyinfo.keylen = 16;
951 952 953 954

	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
			== STA_KEY_FLG_NO_ENC)
		priv->stations[sta_id].sta.key.key_offset =
955
				 iwl_get_free_ucode_key_index(priv);
956 957
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */
958

959
	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Jiri Slaby's avatar
Jiri Slaby committed
960
		"no space for a new key");
961

962 963 964
	priv->stations[sta_id].sta.key.key_flags = key_flags;


965 966 967 968 969 970 971 972 973 974
	/* This copy is acutally not needed: we get the key with each TX */
	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);

	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);

	spin_unlock_irqrestore(&priv->sta_lock, flags);

	return ret;
}

975 976
void iwl_update_tkip_key(struct iwl_priv *priv,
			struct ieee80211_key_conf *keyconf,
977
			struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
978
{
979
	u8 sta_id;
980 981 982 983 984 985 986 987 988
	unsigned long flags;
	int i;

	if (iwl_scan_cancel(priv)) {
		/* cancel scan failed, just live w/ bad key and rely
		   briefly on SW decryption */
		return;
	}

989 990 991 992
	sta_id = iwl_sta_id_or_broadcast(priv, sta);
	if (sta_id == IWL_INVALID_STATION)
		return;

993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
	spin_lock_irqsave(&priv->sta_lock, flags);

	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;

	for (i = 0; i < 5; i++)
		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
			cpu_to_le16(phase1key[i]);

	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);

	spin_unlock_irqrestore(&priv->sta_lock, flags);

}
EXPORT_SYMBOL(iwl_update_tkip_key);

1011 1012 1013
int iwl_remove_dynamic_key(struct iwl_priv *priv,
				struct ieee80211_key_conf *keyconf,
				u8 sta_id)
1014 1015
{
	unsigned long flags;
1016 1017 1018
	int ret = 0;
	u16 key_flags;
	u8 keyidx;
1019

1020
	priv->key_mapping_key--;
1021 1022

	spin_lock_irqsave(&priv->sta_lock, flags);
1023 1024 1025
	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
	keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;

1026
	IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
1027 1028
		      keyconf->keyidx, sta_id);

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
	if (keyconf->keyidx != keyidx) {
		/* We need to remove a key with index different that the one
		 * in the uCode. This means that the key we need to remove has
		 * been replaced by another one with different index.
		 * Don't do anything and return ok
		 */
		spin_unlock_irqrestore(&priv->sta_lock, flags);
		return 0;
	}

1039
	if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
1040
		IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
1041 1042 1043 1044 1045
			    keyconf->keyidx, key_flags);
		spin_unlock_irqrestore(&priv->sta_lock, flags);
		return 0;
	}

1046 1047
	if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
		&priv->ucode_key_table))
1048
		IWL_ERR(priv, "index %d not used in uCode key table.\n",
1049 1050
			priv->stations[sta_id].sta.key.key_offset);
	memset(&priv->stations[sta_id].keyinfo, 0,
1051
					sizeof(struct iwl_hw_key));
1052 1053
	memset(&priv->stations[sta_id].sta.key, 0,
					sizeof(struct iwl4965_keyinfo));
1054 1055 1056
	priv->stations[sta_id].sta.key.key_flags =
			STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
	priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
1057 1058 1059
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

1060
	if (iwl_is_rfkill(priv)) {
1061
		IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
1062 1063 1064
		spin_unlock_irqrestore(&priv->sta_lock, flags);
		return 0;
	}
1065
	ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1066 1067
	spin_unlock_irqrestore(&priv->sta_lock, flags);
	return ret;
1068
}
1069
EXPORT_SYMBOL(iwl_remove_dynamic_key);
1070 1071

int iwl_set_dynamic_key(struct iwl_priv *priv,
1072
				struct ieee80211_key_conf *keyconf, u8 sta_id)
1073 1074 1075
{
	int ret;

1076 1077
	priv->key_mapping_key++;
	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
1078

1079
	switch (keyconf->alg) {
1080
	case ALG_CCMP:
1081
		ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
1082 1083
		break;
	case ALG_TKIP:
1084
		ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
1085 1086
		break;
	case ALG_WEP:
1087
		ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
1088 1089
		break;
	default:
1090 1091
		IWL_ERR(priv,
			"Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
1092 1093 1094
		ret = -EINVAL;
	}

1095
	IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
1096 1097 1098
		      keyconf->alg, keyconf->keylen, keyconf->keyidx,
		      sta_id, ret);

1099 1100
	return ret;
}
1101
EXPORT_SYMBOL(iwl_set_dynamic_key);
1102

1103 1104 1105 1106 1107
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl_dump_lq_cmd(struct iwl_priv *priv,
			   struct iwl_link_quality_cmd *lq)
{
	int i;
1108 1109
	IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
	IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
1110 1111 1112 1113
		       lq->general_params.single_stream_ant_msk,
		       lq->general_params.dual_stream_ant_msk);

	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
1114
		IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
1115 1116 1117 1118 1119 1120 1121 1122 1123
			       i, lq->rs_table[i].rate_n_flags);
}
#else
static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
				   struct iwl_link_quality_cmd *lq)
{
}
#endif

1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
/**
 * is_lq_table_valid() - Test one aspect of LQ cmd for validity
 *
 * It sometimes happens when a HT rate has been in use and we
 * loose connectivity with AP then mac80211 will first tell us that the
 * current channel is not HT anymore before removing the station. In such a
 * scenario the RXON flags will be updated to indicate we are not
 * communicating HT anymore, but the LQ command may still contain HT rates.
 * Test for this to prevent driver from sending LQ command between the time
 * RXON flags are updated and when LQ command is updated.
 */
static bool is_lq_table_valid(struct iwl_priv *priv,
			      struct iwl_link_quality_cmd *lq)
{
	int i;
	struct iwl_ht_config *ht_conf = &priv->current_ht_config;

	if (ht_conf->is_ht)
		return true;

	IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
		       priv->active_rxon.channel);
	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
		if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
			IWL_DEBUG_INFO(priv,
				       "index %d of LQ expects HT channel\n",
				       i);
			return false;
		}
	}
	return true;
}

1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
/**
 * iwl_send_lq_cmd() - Send link quality command
 * @init: This command is sent as part of station initialization right
 *        after station has been added.
 *
 * The link quality command is sent as the last step of station creation.
 * This is the special case in which init is set and we call a callback in
 * this case to clear the state indicating that station creation is in
 * progress.
 */
1167
int iwl_send_lq_cmd(struct iwl_priv *priv,
1168
		    struct iwl_link_quality_cmd *lq, u8 flags, bool init)
1169
{
1170 1171 1172
	int ret = 0;
	unsigned long flags_spin;

1173 1174 1175
	struct iwl_host_cmd cmd = {
		.id = REPLY_TX_LINK_QUALITY_CMD,
		.len = sizeof(struct iwl_link_quality_cmd),
1176
		.flags = flags,
1177 1178 1179
		.data = lq,
	};

1180
	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
1181 1182
		return -EINVAL;

1183
	iwl_dump_lq_cmd(priv, lq);
1184
	BUG_ON(init && (cmd.flags & CMD_ASYNC));
1185

1186 1187 1188 1189
	if (is_lq_table_valid(priv, lq))
		ret = iwl_send_cmd(priv, &cmd);
	else
		ret = -EINVAL;
1190 1191

	if (cmd.flags & CMD_ASYNC)
1192
		return ret;
1193

1194
	if (init) {
1195
		IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n",
1196 1197 1198 1199 1200
			       lq->sta_id);
		spin_lock_irqsave(&priv->sta_lock, flags_spin);
		priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
	}
1201
	return ret;
1202 1203 1204
}
EXPORT_SYMBOL(iwl_send_lq_cmd);

1205
/**
1206 1207 1208 1209 1210
 * iwl_alloc_bcast_station - add broadcast station into driver's station table.
 *
 * This adds the broadcast station into the driver's station table
 * and marks it driver active, so that it will be restored to the
 * device at the next best time.
1211
 */
1212
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
1213
{
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
	struct iwl_link_quality_cmd *link_cmd;
	unsigned long flags;
	u8 sta_id;

	spin_lock_irqsave(&priv->sta_lock, flags);
	sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL);
	if (sta_id == IWL_INVALID_STATION) {
		IWL_ERR(priv, "Unable to prepare broadcast station\n");
		spin_unlock_irqrestore(&priv->sta_lock, flags);

		return -EINVAL;
	}

	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
	priv->stations[sta_id].used |= IWL_STA_BCAST;
	spin_unlock_irqrestore(&priv->sta_lock, flags);

	if (init_lq) {
		link_cmd = iwl_sta_alloc_lq(priv, sta_id);
		if (!link_cmd) {
			IWL_ERR(priv,
				"Unable to initialize rate scaling for bcast station.\n");
			return -ENOMEM;
		}

		spin_lock_irqsave(&priv->sta_lock, flags);
		priv->stations[sta_id].lq = link_cmd;
		spin_unlock_irqrestore(&priv->sta_lock, flags);
	}

	return 0;
1245
}
1246
EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
1247

1248
void iwl_dealloc_bcast_station(struct iwl_priv *priv)
1249
{
1250 1251
	unsigned long flags;
	int i;
1252

1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
	spin_lock_irqsave(&priv->sta_lock, flags);
	for (i = 0; i < priv->hw_params.max_stations; i++) {
		if (!(priv->stations[i].used & IWL_STA_BCAST))
			continue;

		priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
		priv->num_stations--;
		BUG_ON(priv->num_stations < 0);
		kfree(priv->stations[i].lq);
		priv->stations[i].lq = NULL;
	}
	spin_unlock_irqrestore(&priv->sta_lock, flags);
1265
}
1266
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
1267

1268
/**
1269
 * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
1270
 */
1271
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
1272 1273 1274 1275 1276 1277 1278 1279 1280
{
	unsigned long flags;

	/* Remove "disable" flag, to enable Tx for this TID */
	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1281
	spin_unlock_irqrestore(&priv->sta_lock, flags);
1282
}
1283 1284
EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);

1285 1286
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
			 int tid, u16 ssn)
1287 1288 1289 1290
{
	unsigned long flags;
	int sta_id;

1291
	sta_id = iwl_sta_id(sta);
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
	if (sta_id == IWL_INVALID_STATION)
		return -ENXIO;

	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].sta.station_flags_msk = 0;
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	spin_unlock_irqrestore(&priv->sta_lock, flags);

	return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
1304
				CMD_ASYNC);
1305 1306 1307
}
EXPORT_SYMBOL(iwl_sta_rx_agg_start);

1308 1309
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
			int tid)
1310 1311
{
	unsigned long flags;
1312
	int sta_id, ret;
1313

1314
	sta_id = iwl_sta_id(sta);
1315 1316
	if (sta_id == IWL_INVALID_STATION) {
		IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
1317
		return -ENXIO;
1318
	}
1319 1320 1321 1322 1323 1324

	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].sta.station_flags_msk = 0;
	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1325
	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1326 1327
	spin_unlock_irqrestore(&priv->sta_lock, flags);

1328 1329
	return ret;

1330 1331 1332
}
EXPORT_SYMBOL(iwl_sta_rx_agg_stop);

1333
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
1334 1335 1336 1337 1338 1339 1340
{
	unsigned long flags;

	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
	priv->stations[sta_id].sta.sta.modify_mask = 0;
1341
	priv->stations[sta_id].sta.sleep_tx_count = 0;
1342
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1343
	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1344 1345 1346
	spin_unlock_irqrestore(&priv->sta_lock, flags);

}
1347
EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
1348

1349
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
1350
{
1351
	unsigned long flags;
1352

1353 1354 1355 1356 1357 1358 1359
	spin_lock_irqsave(&priv->sta_lock, flags);
	priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
	priv->stations[sta_id].sta.sta.modify_mask =
					STA_MODIFY_SLEEP_TX_COUNT_MSK;
	priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1360
	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1361
	spin_unlock_irqrestore(&priv->sta_lock, flags);
1362 1363

}
1364
EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
1365 1366

int iwl_mac_sta_remove(struct ieee80211_hw *hw,
Johannes Berg's avatar
Johannes Berg committed
1367 1368
		       struct ieee80211_vif *vif,
		       struct ieee80211_sta *sta)
1369 1370
{
	struct iwl_priv *priv = hw->priv;
Johannes Berg's avatar
Johannes Berg committed
1371 1372 1373
	struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
	int ret;

1374 1375
	IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
			sta->addr);
Johannes Berg's avatar
Johannes Berg committed
1376
	ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
1377 1378 1379 1380 1381 1382
	if (ret)
		IWL_ERR(priv, "Error removing station %pM\n",
			sta->addr);
	return ret;
}
EXPORT_SYMBOL(iwl_mac_sta_remove);