iwl-4965-sta.c 20.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/******************************************************************************
 *
 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
 *
 * 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:
 *  Intel Linux Wireless <ilw@linux.intel.com>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <net/mac80211.h>

#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-sta.h"
#include "iwl-4965.h"

S
Stanislaw Gruszka 已提交
37
static struct il_link_quality_cmd *
S
Stanislaw Gruszka 已提交
38
il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id)
39 40
{
	int i, r;
S
Stanislaw Gruszka 已提交
41
	struct il_link_quality_cmd *link_cmd;
42 43 44
	u32 rate_flags = 0;
	__le32 rate_n_flags;

S
Stanislaw Gruszka 已提交
45
	link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL);
46
	if (!link_cmd) {
47
		IL_ERR("Unable to allocate memory for LQ cmd.\n");
48 49 50 51
		return NULL;
	}
	/* 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 */
S
Stanislaw Gruszka 已提交
52
	if (il->band == IEEE80211_BAND_5GHZ)
S
Stanislaw Gruszka 已提交
53
		r = RATE_6M_IDX;
54
	else
S
Stanislaw Gruszka 已提交
55
		r = RATE_1M_IDX;
56

S
Stanislaw Gruszka 已提交
57
	if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
58 59
		rate_flags |= RATE_MCS_CCK_MSK;

S
Stanislaw Gruszka 已提交
60
	rate_flags |= il4965_first_antenna(il->hw_params.valid_tx_ant) <<
61
				RATE_MCS_ANT_POS;
62
	rate_n_flags = il4965_hw_set_rate_n_flags(il_rates[r].plcp,
63
						   rate_flags);
64 65 66 67
	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
		link_cmd->rs_table[i].rate_n_flags = rate_n_flags;

	link_cmd->general_params.single_stream_ant_msk =
S
Stanislaw Gruszka 已提交
68
				il4965_first_antenna(il->hw_params.valid_tx_ant);
69 70

	link_cmd->general_params.dual_stream_ant_msk =
S
Stanislaw Gruszka 已提交
71 72
		il->hw_params.valid_tx_ant &
		~il4965_first_antenna(il->hw_params.valid_tx_ant);
73 74
	if (!link_cmd->general_params.dual_stream_ant_msk) {
		link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
S
Stanislaw Gruszka 已提交
75
	} else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
76
		link_cmd->general_params.dual_stream_ant_msk =
S
Stanislaw Gruszka 已提交
77
			il->hw_params.valid_tx_ant;
78 79 80 81 82 83 84 85 86 87 88 89
	}

	link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
	link_cmd->agg_params.agg_time_limit =
		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);

	link_cmd->sta_id = sta_id;

	return link_cmd;
}

/*
S
Stanislaw Gruszka 已提交
90
 * il4965_add_bssid_station - Add the special IBSS BSSID station
91 92 93 94
 *
 * Function sleeps.
 */
int
S
Stanislaw Gruszka 已提交
95
il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx,
96 97 98 99
			     const u8 *addr, u8 *sta_id_r)
{
	int ret;
	u8 sta_id;
S
Stanislaw Gruszka 已提交
100
	struct il_link_quality_cmd *link_cmd;
101 102 103
	unsigned long flags;

	if (sta_id_r)
S
Stanislaw Gruszka 已提交
104
		*sta_id_r = IL_INVALID_STATION;
105

S
Stanislaw Gruszka 已提交
106
	ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
107
	if (ret) {
108
		IL_ERR("Unable to add station %pM\n", addr);
109 110 111 112 113 114
		return ret;
	}

	if (sta_id_r)
		*sta_id_r = sta_id;

S
Stanislaw Gruszka 已提交
115 116 117
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].used |= IL_STA_LOCAL;
	spin_unlock_irqrestore(&il->sta_lock, flags);
118 119

	/* Set up default rate scaling table in device's station table */
S
Stanislaw Gruszka 已提交
120
	link_cmd = il4965_sta_alloc_lq(il, sta_id);
121
	if (!link_cmd) {
122
		IL_ERR(
123 124 125 126 127
			"Unable to initialize rate scaling for station %pM.\n",
			addr);
		return -ENOMEM;
	}

S
Stanislaw Gruszka 已提交
128
	ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true);
129
	if (ret)
130
		IL_ERR("Link quality command failed (%d)\n", ret);
131

S
Stanislaw Gruszka 已提交
132 133 134
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].lq = link_cmd;
	spin_unlock_irqrestore(&il->sta_lock, flags);
135 136 137 138

	return 0;
}

S
Stanislaw Gruszka 已提交
139
static int il4965_static_wepkey_cmd(struct il_priv *il,
S
Stanislaw Gruszka 已提交
140
				      struct il_rxon_context *ctx,
141 142 143
				      bool send_if_empty)
{
	int i, not_empty = 0;
S
Stanislaw Gruszka 已提交
144 145 146 147 148
	u8 buff[sizeof(struct il_wep_cmd) +
		sizeof(struct il_wep_key) * WEP_KEYS_MAX];
	struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff;
	size_t cmd_size  = sizeof(struct il_wep_cmd);
	struct il_host_cmd cmd = {
149 150 151 152 153 154 155 156
		.id = ctx->wep_key_cmd,
		.data = wep_cmd,
		.flags = CMD_SYNC,
	};

	might_sleep();

	memset(wep_cmd, 0, cmd_size +
S
Stanislaw Gruszka 已提交
157
			(sizeof(struct il_wep_key) * WEP_KEYS_MAX));
158 159

	for (i = 0; i < WEP_KEYS_MAX ; i++) {
S
Stanislaw Gruszka 已提交
160
		wep_cmd->key[i].key_idx = i;
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
		if (ctx->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 = ctx->wep_keys[i].key_size;
		memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
				ctx->wep_keys[i].key_size);
	}

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

S
Stanislaw Gruszka 已提交
176
	cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX;
177 178 179 180

	cmd.len = cmd_size;

	if (not_empty || send_if_empty)
S
Stanislaw Gruszka 已提交
181
		return il_send_cmd(il, &cmd);
182 183 184 185
	else
		return 0;
}

S
Stanislaw Gruszka 已提交
186
int il4965_restore_default_wep_keys(struct il_priv *il,
S
Stanislaw Gruszka 已提交
187
				 struct il_rxon_context *ctx)
188
{
S
Stanislaw Gruszka 已提交
189
	lockdep_assert_held(&il->mutex);
190

S
Stanislaw Gruszka 已提交
191
	return il4965_static_wepkey_cmd(il, ctx, false);
192 193
}

S
Stanislaw Gruszka 已提交
194
int il4965_remove_default_wep_key(struct il_priv *il,
S
Stanislaw Gruszka 已提交
195
			       struct il_rxon_context *ctx,
196 197 198 199
			       struct ieee80211_key_conf *keyconf)
{
	int ret;

S
Stanislaw Gruszka 已提交
200
	lockdep_assert_held(&il->mutex);
201

202
	D_WEP("Removing default WEP key: idx=%d\n",
203 204 205
		      keyconf->keyidx);

	memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
S
Stanislaw Gruszka 已提交
206
	if (il_is_rfkill(il)) {
207
		D_WEP(
208 209 210 211
		"Not sending REPLY_WEPKEY command due to RFKILL.\n");
		/* but keys in device are clear anyway so return success */
		return 0;
	}
S
Stanislaw Gruszka 已提交
212
	ret = il4965_static_wepkey_cmd(il, ctx, 1);
213
	D_WEP("Remove default WEP key: idx=%d ret=%d\n",
214 215 216 217 218
		      keyconf->keyidx, ret);

	return ret;
}

S
Stanislaw Gruszka 已提交
219
int il4965_set_default_wep_key(struct il_priv *il,
S
Stanislaw Gruszka 已提交
220
			    struct il_rxon_context *ctx,
221 222 223 224
			    struct ieee80211_key_conf *keyconf)
{
	int ret;

S
Stanislaw Gruszka 已提交
225
	lockdep_assert_held(&il->mutex);
226 227 228

	if (keyconf->keylen != WEP_KEY_LEN_128 &&
	    keyconf->keylen != WEP_KEY_LEN_64) {
229
		D_WEP("Bad WEP key length %d\n", keyconf->keylen);
230 231 232 233 234
		return -EINVAL;
	}

	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
	keyconf->hw_key_idx = HW_KEY_DEFAULT;
S
Stanislaw Gruszka 已提交
235
	il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
236 237 238 239 240

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

S
Stanislaw Gruszka 已提交
241
	ret = il4965_static_wepkey_cmd(il, ctx, false);
242
	D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n",
243 244 245 246 247
		keyconf->keylen, keyconf->keyidx, ret);

	return ret;
}

S
Stanislaw Gruszka 已提交
248
static int il4965_set_wep_dynamic_key_info(struct il_priv *il,
S
Stanislaw Gruszka 已提交
249
					struct il_rxon_context *ctx,
250 251 252 253 254
					struct ieee80211_key_conf *keyconf,
					u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
S
Stanislaw Gruszka 已提交
255
	struct il_addsta_cmd sta_cmd;
256

S
Stanislaw Gruszka 已提交
257
	lockdep_assert_held(&il->mutex);
258 259 260 261 262 263 264 265 266 267 268 269 270

	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;

	if (sta_id == ctx->bcast_sta_id)
		key_flags |= STA_KEY_MULTICAST_MSK;

S
Stanislaw Gruszka 已提交
271
	spin_lock_irqsave(&il->sta_lock, flags);
272

S
Stanislaw Gruszka 已提交
273 274 275
	il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
	il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
	il->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
276

S
Stanislaw Gruszka 已提交
277
	memcpy(il->stations[sta_id].keyinfo.key,
278 279
				keyconf->key, keyconf->keylen);

S
Stanislaw Gruszka 已提交
280
	memcpy(&il->stations[sta_id].sta.key.key[3],
281 282
				keyconf->key, keyconf->keylen);

S
Stanislaw Gruszka 已提交
283
	if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
284
			== STA_KEY_FLG_NO_ENC)
S
Stanislaw Gruszka 已提交
285
		il->stations[sta_id].sta.key.key_offset =
S
Stanislaw Gruszka 已提交
286
				 il_get_free_ucode_key_idx(il);
287 288 289
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */

S
Stanislaw Gruszka 已提交
290
	WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
291 292
		"no space for a new key");

S
Stanislaw Gruszka 已提交
293 294 295
	il->stations[sta_id].sta.key.key_flags = key_flags;
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
296

S
Stanislaw Gruszka 已提交
297
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
298
			sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
299
	spin_unlock_irqrestore(&il->sta_lock, flags);
300

S
Stanislaw Gruszka 已提交
301
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
302 303
}

S
Stanislaw Gruszka 已提交
304
static int il4965_set_ccmp_dynamic_key_info(struct il_priv *il,
S
Stanislaw Gruszka 已提交
305
					 struct il_rxon_context *ctx,
306 307 308 309 310
					 struct ieee80211_key_conf *keyconf,
					 u8 sta_id)
{
	unsigned long flags;
	__le16 key_flags = 0;
S
Stanislaw Gruszka 已提交
311
	struct il_addsta_cmd sta_cmd;
312

S
Stanislaw Gruszka 已提交
313
	lockdep_assert_held(&il->mutex);
314 315 316 317 318 319 320 321 322 323

	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;

	if (sta_id == ctx->bcast_sta_id)
		key_flags |= STA_KEY_MULTICAST_MSK;

	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;

S
Stanislaw Gruszka 已提交
324 325 326
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
	il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
327

S
Stanislaw Gruszka 已提交
328
	memcpy(il->stations[sta_id].keyinfo.key, keyconf->key,
329 330
	       keyconf->keylen);

S
Stanislaw Gruszka 已提交
331
	memcpy(il->stations[sta_id].sta.key.key, keyconf->key,
332 333
	       keyconf->keylen);

S
Stanislaw Gruszka 已提交
334
	if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
335
			== STA_KEY_FLG_NO_ENC)
S
Stanislaw Gruszka 已提交
336
		il->stations[sta_id].sta.key.key_offset =
S
Stanislaw Gruszka 已提交
337
				 il_get_free_ucode_key_idx(il);
338 339 340
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */

S
Stanislaw Gruszka 已提交
341
	WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
342 343
		"no space for a new key");

S
Stanislaw Gruszka 已提交
344 345 346
	il->stations[sta_id].sta.key.key_flags = key_flags;
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
347

S
Stanislaw Gruszka 已提交
348
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
349
			 sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
350
	spin_unlock_irqrestore(&il->sta_lock, flags);
351

S
Stanislaw Gruszka 已提交
352
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
353 354
}

S
Stanislaw Gruszka 已提交
355
static int il4965_set_tkip_dynamic_key_info(struct il_priv *il,
S
Stanislaw Gruszka 已提交
356
					 struct il_rxon_context *ctx,
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
					 struct ieee80211_key_conf *keyconf,
					 u8 sta_id)
{
	unsigned long flags;
	int ret = 0;
	__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 == ctx->bcast_sta_id)
		key_flags |= STA_KEY_MULTICAST_MSK;

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

S
Stanislaw Gruszka 已提交
374
	spin_lock_irqsave(&il->sta_lock, flags);
375

S
Stanislaw Gruszka 已提交
376 377
	il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
	il->stations[sta_id].keyinfo.keylen = 16;
378

S
Stanislaw Gruszka 已提交
379
	if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
380
			== STA_KEY_FLG_NO_ENC)
S
Stanislaw Gruszka 已提交
381
		il->stations[sta_id].sta.key.key_offset =
S
Stanislaw Gruszka 已提交
382
				 il_get_free_ucode_key_idx(il);
383 384 385
	/* else, we are overriding an existing key => no need to allocated room
	 * in uCode. */

S
Stanislaw Gruszka 已提交
386
	WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
387 388
		"no space for a new key");

S
Stanislaw Gruszka 已提交
389
	il->stations[sta_id].sta.key.key_flags = key_flags;
390 391 392


	/* This copy is acutally not needed: we get the key with each TX */
S
Stanislaw Gruszka 已提交
393
	memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, 16);
394

S
Stanislaw Gruszka 已提交
395
	memcpy(il->stations[sta_id].sta.key.key, keyconf->key, 16);
396

S
Stanislaw Gruszka 已提交
397
	spin_unlock_irqrestore(&il->sta_lock, flags);
398 399 400 401

	return ret;
}

S
Stanislaw Gruszka 已提交
402
void il4965_update_tkip_key(struct il_priv *il,
S
Stanislaw Gruszka 已提交
403
			 struct il_rxon_context *ctx,
404 405 406 407 408 409 410
			 struct ieee80211_key_conf *keyconf,
			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
{
	u8 sta_id;
	unsigned long flags;
	int i;

S
Stanislaw Gruszka 已提交
411
	if (il_scan_cancel(il)) {
412 413 414 415 416
		/* cancel scan failed, just live w/ bad key and rely
		   briefly on SW decryption */
		return;
	}

S
Stanislaw Gruszka 已提交
417
	sta_id = il_sta_id_or_broadcast(il, ctx, sta);
S
Stanislaw Gruszka 已提交
418
	if (sta_id == IL_INVALID_STATION)
419 420
		return;

S
Stanislaw Gruszka 已提交
421
	spin_lock_irqsave(&il->sta_lock, flags);
422

S
Stanislaw Gruszka 已提交
423
	il->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
424 425

	for (i = 0; i < 5; i++)
S
Stanislaw Gruszka 已提交
426
		il->stations[sta_id].sta.key.tkip_rx_ttak[i] =
427 428
			cpu_to_le16(phase1key[i]);

S
Stanislaw Gruszka 已提交
429 430
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
431

S
Stanislaw Gruszka 已提交
432
	il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
433

S
Stanislaw Gruszka 已提交
434
	spin_unlock_irqrestore(&il->sta_lock, flags);
435 436 437

}

S
Stanislaw Gruszka 已提交
438
int il4965_remove_dynamic_key(struct il_priv *il,
S
Stanislaw Gruszka 已提交
439
			   struct il_rxon_context *ctx,
440 441 442 443 444 445
			   struct ieee80211_key_conf *keyconf,
			   u8 sta_id)
{
	unsigned long flags;
	u16 key_flags;
	u8 keyidx;
S
Stanislaw Gruszka 已提交
446
	struct il_addsta_cmd sta_cmd;
447

S
Stanislaw Gruszka 已提交
448
	lockdep_assert_held(&il->mutex);
449 450 451

	ctx->key_mapping_keys--;

S
Stanislaw Gruszka 已提交
452 453
	spin_lock_irqsave(&il->sta_lock, flags);
	key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags);
454 455
	keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;

456
	D_WEP("Remove dynamic key: idx=%d sta=%d\n",
457 458 459
		      keyconf->keyidx, sta_id);

	if (keyconf->keyidx != keyidx) {
S
Stanislaw Gruszka 已提交
460
		/* We need to remove a key with idx different that the one
461
		 * in the uCode. This means that the key we need to remove has
S
Stanislaw Gruszka 已提交
462
		 * been replaced by another one with different idx.
463 464
		 * Don't do anything and return ok
		 */
S
Stanislaw Gruszka 已提交
465
		spin_unlock_irqrestore(&il->sta_lock, flags);
466 467 468
		return 0;
	}

S
Stanislaw Gruszka 已提交
469
	if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
470
		IL_WARN("Removing wrong key %d 0x%x\n",
471
			    keyconf->keyidx, key_flags);
S
Stanislaw Gruszka 已提交
472
		spin_unlock_irqrestore(&il->sta_lock, flags);
473 474 475
		return 0;
	}

S
Stanislaw Gruszka 已提交
476 477
	if (!test_and_clear_bit(il->stations[sta_id].sta.key.key_offset,
		&il->ucode_key_table))
S
Stanislaw Gruszka 已提交
478
		IL_ERR("idx %d not used in uCode key table.\n",
S
Stanislaw Gruszka 已提交
479 480
			il->stations[sta_id].sta.key.key_offset);
	memset(&il->stations[sta_id].keyinfo, 0,
S
Stanislaw Gruszka 已提交
481
					sizeof(struct il_hw_key));
S
Stanislaw Gruszka 已提交
482
	memset(&il->stations[sta_id].sta.key, 0,
S
Stanislaw Gruszka 已提交
483
					sizeof(struct il4965_keyinfo));
S
Stanislaw Gruszka 已提交
484
	il->stations[sta_id].sta.key.key_flags =
485
			STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
S
Stanislaw Gruszka 已提交
486 487 488
	il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
489

S
Stanislaw Gruszka 已提交
490
	if (il_is_rfkill(il)) {
491
		D_WEP(
492
		 "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
S
Stanislaw Gruszka 已提交
493
		spin_unlock_irqrestore(&il->sta_lock, flags);
494 495
		return 0;
	}
S
Stanislaw Gruszka 已提交
496
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
497
			sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
498
	spin_unlock_irqrestore(&il->sta_lock, flags);
499

S
Stanislaw Gruszka 已提交
500
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
501 502
}

S
Stanislaw Gruszka 已提交
503
int il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
504 505 506 507
			struct ieee80211_key_conf *keyconf, u8 sta_id)
{
	int ret;

S
Stanislaw Gruszka 已提交
508
	lockdep_assert_held(&il->mutex);
509 510 511 512 513 514

	ctx->key_mapping_keys++;
	keyconf->hw_key_idx = HW_KEY_DYNAMIC;

	switch (keyconf->cipher) {
	case WLAN_CIPHER_SUITE_CCMP:
S
Stanislaw Gruszka 已提交
515
		ret = il4965_set_ccmp_dynamic_key_info(il, ctx,
516 517 518
							keyconf, sta_id);
		break;
	case WLAN_CIPHER_SUITE_TKIP:
S
Stanislaw Gruszka 已提交
519
		ret = il4965_set_tkip_dynamic_key_info(il, ctx,
520 521 522 523
							keyconf, sta_id);
		break;
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
S
Stanislaw Gruszka 已提交
524
		ret = il4965_set_wep_dynamic_key_info(il, ctx,
525 526 527
							keyconf, sta_id);
		break;
	default:
528
		IL_ERR(
529 530 531 532 533
			"Unknown alg: %s cipher = %x\n", __func__,
			keyconf->cipher);
		ret = -EINVAL;
	}

534
	D_WEP(
535 536 537 538 539 540 541 542
		"Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
		      sta_id, ret);

	return ret;
}

/**
S
Stanislaw Gruszka 已提交
543
 * il4965_alloc_bcast_station - add broadcast station into driver's station table.
544 545 546 547 548
 *
 * 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.
 */
S
Stanislaw Gruszka 已提交
549
int il4965_alloc_bcast_station(struct il_priv *il,
S
Stanislaw Gruszka 已提交
550
			       struct il_rxon_context *ctx)
551
{
S
Stanislaw Gruszka 已提交
552
	struct il_link_quality_cmd *link_cmd;
553 554 555
	unsigned long flags;
	u8 sta_id;

S
Stanislaw Gruszka 已提交
556
	spin_lock_irqsave(&il->sta_lock, flags);
557
	sta_id = il_prep_station(il, ctx, il_bcast_addr,
558
								false, NULL);
S
Stanislaw Gruszka 已提交
559
	if (sta_id == IL_INVALID_STATION) {
560
		IL_ERR("Unable to prepare broadcast station\n");
S
Stanislaw Gruszka 已提交
561
		spin_unlock_irqrestore(&il->sta_lock, flags);
562 563 564 565

		return -EINVAL;
	}

S
Stanislaw Gruszka 已提交
566 567 568
	il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
	il->stations[sta_id].used |= IL_STA_BCAST;
	spin_unlock_irqrestore(&il->sta_lock, flags);
569

S
Stanislaw Gruszka 已提交
570
	link_cmd = il4965_sta_alloc_lq(il, sta_id);
571
	if (!link_cmd) {
572
		IL_ERR(
573 574 575 576
			"Unable to initialize rate scaling for bcast station.\n");
		return -ENOMEM;
	}

S
Stanislaw Gruszka 已提交
577 578 579
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].lq = link_cmd;
	spin_unlock_irqrestore(&il->sta_lock, flags);
580 581 582 583 584

	return 0;
}

/**
S
Stanislaw Gruszka 已提交
585
 * il4965_update_bcast_station - update broadcast station's LQ command
586 587 588 589
 *
 * Only used by iwl4965. Placed here to have all bcast station management
 * code together.
 */
S
Stanislaw Gruszka 已提交
590
static int il4965_update_bcast_station(struct il_priv *il,
S
Stanislaw Gruszka 已提交
591
				    struct il_rxon_context *ctx)
592 593
{
	unsigned long flags;
S
Stanislaw Gruszka 已提交
594
	struct il_link_quality_cmd *link_cmd;
595 596
	u8 sta_id = ctx->bcast_sta_id;

S
Stanislaw Gruszka 已提交
597
	link_cmd = il4965_sta_alloc_lq(il, sta_id);
598
	if (!link_cmd) {
599
		IL_ERR(
600 601 602 603
		"Unable to initialize rate scaling for bcast station.\n");
		return -ENOMEM;
	}

S
Stanislaw Gruszka 已提交
604 605 606
	spin_lock_irqsave(&il->sta_lock, flags);
	if (il->stations[sta_id].lq)
		kfree(il->stations[sta_id].lq);
607
	else
608
		D_INFO(
609
		"Bcast station rate scaling has not been initialized yet.\n");
S
Stanislaw Gruszka 已提交
610 611
	il->stations[sta_id].lq = link_cmd;
	spin_unlock_irqrestore(&il->sta_lock, flags);
612 613 614 615

	return 0;
}

S
Stanislaw Gruszka 已提交
616
int il4965_update_bcast_stations(struct il_priv *il)
617
{
S
Stanislaw Gruszka 已提交
618
	struct il_rxon_context *ctx;
619 620
	int ret = 0;

S
Stanislaw Gruszka 已提交
621 622
	for_each_context(il, ctx) {
		ret = il4965_update_bcast_station(il, ctx);
623 624 625 626 627 628 629 630
		if (ret)
			break;
	}

	return ret;
}

/**
S
Stanislaw Gruszka 已提交
631
 * il4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
632
 */
S
Stanislaw Gruszka 已提交
633
int il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
634 635
{
	unsigned long flags;
S
Stanislaw Gruszka 已提交
636
	struct il_addsta_cmd sta_cmd;
637

S
Stanislaw Gruszka 已提交
638
	lockdep_assert_held(&il->mutex);
639 640

	/* Remove "disable" flag, to enable Tx for this TID */
S
Stanislaw Gruszka 已提交
641 642 643 644 645
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
	il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
646
					sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
647
	spin_unlock_irqrestore(&il->sta_lock, flags);
648

S
Stanislaw Gruszka 已提交
649
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
650 651
}

S
Stanislaw Gruszka 已提交
652
int il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta,
653 654 655 656
			 int tid, u16 ssn)
{
	unsigned long flags;
	int sta_id;
S
Stanislaw Gruszka 已提交
657
	struct il_addsta_cmd sta_cmd;
658

S
Stanislaw Gruszka 已提交
659
	lockdep_assert_held(&il->mutex);
660

S
Stanislaw Gruszka 已提交
661 662
	sta_id = il_sta_id(sta);
	if (sta_id == IL_INVALID_STATION)
663 664
		return -ENXIO;

S
Stanislaw Gruszka 已提交
665 666 667 668 669 670 671
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].sta.station_flags_msk = 0;
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
	il->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
	il->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
672
					sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
673
	spin_unlock_irqrestore(&il->sta_lock, flags);
674

S
Stanislaw Gruszka 已提交
675
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
676 677
}

S
Stanislaw Gruszka 已提交
678
int il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta,
679 680 681 682
			int tid)
{
	unsigned long flags;
	int sta_id;
S
Stanislaw Gruszka 已提交
683
	struct il_addsta_cmd sta_cmd;
684

S
Stanislaw Gruszka 已提交
685
	lockdep_assert_held(&il->mutex);
686

S
Stanislaw Gruszka 已提交
687 688
	sta_id = il_sta_id(sta);
	if (sta_id == IL_INVALID_STATION) {
689
		IL_ERR("Invalid station for AGG tid %d\n", tid);
690 691 692
		return -ENXIO;
	}

S
Stanislaw Gruszka 已提交
693 694 695 696 697 698
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].sta.station_flags_msk = 0;
	il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
	il->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	memcpy(&sta_cmd, &il->stations[sta_id].sta,
S
Stanislaw Gruszka 已提交
699
				sizeof(struct il_addsta_cmd));
S
Stanislaw Gruszka 已提交
700
	spin_unlock_irqrestore(&il->sta_lock, flags);
701

S
Stanislaw Gruszka 已提交
702
	return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
703 704 705
}

void
S
Stanislaw Gruszka 已提交
706
il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt)
707 708 709
{
	unsigned long flags;

S
Stanislaw Gruszka 已提交
710 711 712 713
	spin_lock_irqsave(&il->sta_lock, flags);
	il->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
	il->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
	il->stations[sta_id].sta.sta.modify_mask =
714
					STA_MODIFY_SLEEP_TX_COUNT_MSK;
S
Stanislaw Gruszka 已提交
715 716 717 718 719
	il->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
	il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
	il_send_add_sta(il,
				&il->stations[sta_id].sta, CMD_ASYNC);
	spin_unlock_irqrestore(&il->sta_lock, flags);
720 721

}