p54common.c 67.9 KB
Newer Older
1 2 3 4 5
/*
 * Common code for mac80211 Prism54 drivers
 *
 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
 * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
J
Johannes Berg 已提交
6
 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7
 *
8 9 10 11
 * Based on:
 * - the islsm (softmac prism54) driver, which is:
 *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
 * - stlc45xx driver
C
Chr 已提交
12
 *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>

#include <net/mac80211.h>

#include "p54.h"
#include "p54common.h"

28 29 30
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
31 32 33 34 35
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");

36
static struct ieee80211_rate p54_bgrates[] = {
37 38 39 40 41 42 43 44 45 46 47 48 49 50
	{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 60, .hw_value = 4, },
	{ .bitrate = 90, .hw_value = 5, },
	{ .bitrate = 120, .hw_value = 6, },
	{ .bitrate = 180, .hw_value = 7, },
	{ .bitrate = 240, .hw_value = 8, },
	{ .bitrate = 360, .hw_value = 9, },
	{ .bitrate = 480, .hw_value = 10, },
	{ .bitrate = 540, .hw_value = 11, },
};

51
static struct ieee80211_channel p54_bgchannels[] = {
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
	{ .center_freq = 2412, .hw_value = 1, },
	{ .center_freq = 2417, .hw_value = 2, },
	{ .center_freq = 2422, .hw_value = 3, },
	{ .center_freq = 2427, .hw_value = 4, },
	{ .center_freq = 2432, .hw_value = 5, },
	{ .center_freq = 2437, .hw_value = 6, },
	{ .center_freq = 2442, .hw_value = 7, },
	{ .center_freq = 2447, .hw_value = 8, },
	{ .center_freq = 2452, .hw_value = 9, },
	{ .center_freq = 2457, .hw_value = 10, },
	{ .center_freq = 2462, .hw_value = 11, },
	{ .center_freq = 2467, .hw_value = 12, },
	{ .center_freq = 2472, .hw_value = 13, },
	{ .center_freq = 2484, .hw_value = 14, },
};

J
Johannes Berg 已提交
68
static struct ieee80211_supported_band band_2GHz = {
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 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 128
	.channels = p54_bgchannels,
	.n_channels = ARRAY_SIZE(p54_bgchannels),
	.bitrates = p54_bgrates,
	.n_bitrates = ARRAY_SIZE(p54_bgrates),
};

static struct ieee80211_rate p54_arates[] = {
	{ .bitrate = 60, .hw_value = 4, },
	{ .bitrate = 90, .hw_value = 5, },
	{ .bitrate = 120, .hw_value = 6, },
	{ .bitrate = 180, .hw_value = 7, },
	{ .bitrate = 240, .hw_value = 8, },
	{ .bitrate = 360, .hw_value = 9, },
	{ .bitrate = 480, .hw_value = 10, },
	{ .bitrate = 540, .hw_value = 11, },
};

static struct ieee80211_channel p54_achannels[] = {
	{ .center_freq = 4920 },
	{ .center_freq = 4940 },
	{ .center_freq = 4960 },
	{ .center_freq = 4980 },
	{ .center_freq = 5040 },
	{ .center_freq = 5060 },
	{ .center_freq = 5080 },
	{ .center_freq = 5170 },
	{ .center_freq = 5180 },
	{ .center_freq = 5190 },
	{ .center_freq = 5200 },
	{ .center_freq = 5210 },
	{ .center_freq = 5220 },
	{ .center_freq = 5230 },
	{ .center_freq = 5240 },
	{ .center_freq = 5260 },
	{ .center_freq = 5280 },
	{ .center_freq = 5300 },
	{ .center_freq = 5320 },
	{ .center_freq = 5500 },
	{ .center_freq = 5520 },
	{ .center_freq = 5540 },
	{ .center_freq = 5560 },
	{ .center_freq = 5580 },
	{ .center_freq = 5600 },
	{ .center_freq = 5620 },
	{ .center_freq = 5640 },
	{ .center_freq = 5660 },
	{ .center_freq = 5680 },
	{ .center_freq = 5700 },
	{ .center_freq = 5745 },
	{ .center_freq = 5765 },
	{ .center_freq = 5785 },
	{ .center_freq = 5805 },
	{ .center_freq = 5825 },
};

static struct ieee80211_supported_band band_5GHz = {
	.channels = p54_achannels,
	.n_channels = ARRAY_SIZE(p54_achannels),
	.bitrates = p54_arates,
	.n_bitrates = ARRAY_SIZE(p54_arates),
129 130
};

131
int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
132 133 134 135 136 137 138 139 140
{
	struct p54_common *priv = dev->priv;
	struct bootrec_exp_if *exp_if;
	struct bootrec *bootrec;
	u32 *data = (u32 *)fw->data;
	u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
	u8 *fw_version = NULL;
	size_t len;
	int i;
141
	int maxlen;
142 143

	if (priv->rx_start)
144
		return 0;
145 146 147 148 149 150 151 152 153 154 155 156 157 158

	while (data < end_data && *data)
		data++;

	while (data < end_data && !*data)
		data++;

	bootrec = (struct bootrec *) data;

	while (bootrec->data <= end_data &&
	       (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
		u32 code = le32_to_cpu(bootrec->code);
		switch (code) {
		case BR_CODE_COMPONENT_ID:
L
Larry Finger 已提交
159 160
			priv->fw_interface = be32_to_cpup((__be32 *)
					     bootrec->data);
161
			switch (priv->fw_interface) {
162
			case FW_LM86:
C
Christian Lamparter 已提交
163 164 165 166 167 168 169
			case FW_LM20:
			case FW_LM87: {
				char *iftype = (char *)bootrec->data;
				printk(KERN_INFO "%s: p54 detected a LM%c%c "
						 "firmware\n",
					wiphy_name(dev->wiphy),
					iftype[2], iftype[3]);
170
				break;
C
Christian Lamparter 已提交
171 172
				}
			case FW_FMAC:
173
			default:
C
Christian Lamparter 已提交
174 175 176
				printk(KERN_ERR "%s: unsupported firmware\n",
					wiphy_name(dev->wiphy));
				return -ENODEV;
177 178 179 180 181 182 183
			}
			break;
		case BR_CODE_COMPONENT_VERSION:
			/* 24 bytes should be enough for all firmwares */
			if (strnlen((unsigned char*)bootrec->data, 24) < 24)
				fw_version = (unsigned char*)bootrec->data;
			break;
184 185 186 187
		case BR_CODE_DESCR: {
			struct bootrec_desc *desc =
				(struct bootrec_desc *)bootrec->data;
			priv->rx_start = le32_to_cpu(desc->rx_start);
188
			/* FIXME add sanity checking */
189 190 191
			priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
			priv->headroom = desc->headroom;
			priv->tailroom = desc->tailroom;
192 193
			priv->privacy_caps = desc->privacy_caps;
			priv->rx_keycache_size = desc->rx_keycache_size;
L
Larry Finger 已提交
194
			if (le32_to_cpu(bootrec->len) == 11)
195
				priv->rx_mtu = le16_to_cpu(desc->rx_mtu);
196 197 198
			else
				priv->rx_mtu = (size_t)
					0x620 - priv->tx_hdr_len;
199 200 201 202 203 204 205 206 207 208
			maxlen = priv->tx_hdr_len + /* USB devices */
				 sizeof(struct p54_rx_data) +
				 4 + /* rx alignment */
				 IEEE80211_MAX_FRAG_THRESHOLD;
			if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
				printk(KERN_INFO "p54: rx_mtu reduced from %d "
					         "to %d\n", priv->rx_mtu,
						 maxlen);
				priv->rx_mtu = maxlen;
			}
209
			break;
210
			}
211 212 213
		case BR_CODE_EXPOSED_IF:
			exp_if = (struct bootrec_exp_if *) bootrec->data;
			for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
A
Al Viro 已提交
214
				if (exp_if[i].if_id == cpu_to_le16(0x1a))
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
					priv->fw_var = le16_to_cpu(exp_if[i].variant);
			break;
		case BR_CODE_DEPENDENT_IF:
			break;
		case BR_CODE_END_OF_BRA:
		case LEGACY_BR_CODE_END_OF_BRA:
			end_data = NULL;
			break;
		default:
			break;
		}
		bootrec = (struct bootrec *)&bootrec->data[len];
	}

	if (fw_version)
C
Christian Lamparter 已提交
230 231 232
		printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
			wiphy_name(dev->wiphy), fw_version,
			priv->fw_var >> 8, priv->fw_var & 0xff);
233

234
	if (priv->fw_var < 0x500)
C
Christian Lamparter 已提交
235
		printk(KERN_INFO "%s: you are using an obsolete firmware. "
236
		       "visit http://wireless.kernel.org/en/users/Drivers/p54 "
C
Christian Lamparter 已提交
237 238
		       "and grab one for \"kernel >= 2.6.28\"!\n",
			wiphy_name(dev->wiphy));
239

240 241
	if (priv->fw_var >= 0x300) {
		/* Firmware supports QoS, use it! */
242 243 244 245 246
		priv->tx_stats[P54_QUEUE_AC_VO].limit = 3;
		priv->tx_stats[P54_QUEUE_AC_VI].limit = 4;
		priv->tx_stats[P54_QUEUE_AC_BE].limit = 3;
		priv->tx_stats[P54_QUEUE_AC_BK].limit = 2;
		dev->queues = P54_QUEUE_AC_NUM;
247
	}
248

249 250 251 252 253 254 255 256 257 258
	if (!modparam_nohwcrypt)
		printk(KERN_INFO "%s: cryptographic accelerator "
				 "WEP:%s, TKIP:%s, CCMP:%s\n",
			wiphy_name(dev->wiphy),
			(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
			"no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
			 BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
			(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
			"YES" : "no");

259
	return 0;
260 261 262
}
EXPORT_SYMBOL_GPL(p54_parse_firmware);

263 264
static int p54_convert_rev0(struct ieee80211_hw *dev,
			    struct pda_pa_curve_data *curve_data)
265 266
{
	struct p54_common *priv = dev->priv;
267 268
	struct p54_pa_curve_data_sample *dst;
	struct pda_pa_curve_data_sample_rev0 *src;
269
	size_t cd_len = sizeof(*curve_data) +
270
		(curve_data->points_per_channel*sizeof(*dst) + 2) *
271 272 273 274
		 curve_data->channels;
	unsigned int i, j;
	void *source, *target;

275 276
	priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
				   GFP_KERNEL);
277 278 279
	if (!priv->curve_data)
		return -ENOMEM;

280 281 282 283 284 285
	priv->curve_data->entries = curve_data->channels;
	priv->curve_data->entry_size = sizeof(__le16) +
		sizeof(*dst) * curve_data->points_per_channel;
	priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
	priv->curve_data->len = cd_len;
	memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
286
	source = curve_data->data;
287
	target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
288 289 290 291 292 293
	for (i = 0; i < curve_data->channels; i++) {
		__le16 *freq = source;
		source += sizeof(__le16);
		*((__le16 *)target) = *freq;
		target += sizeof(__le16);
		for (j = 0; j < curve_data->points_per_channel; j++) {
294 295
			dst = target;
			src = source;
296

297 298 299
			dst->rf_power = src->rf_power;
			dst->pa_detector = src->pa_detector;
			dst->data_64qam = src->pcv;
300 301
			/* "invent" the points for the other modulations */
#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
302 303 304 305
			dst->data_16qam = SUB(src->pcv, 12);
			dst->data_qpsk = SUB(dst->data_16qam, 12);
			dst->data_bpsk = SUB(dst->data_qpsk, 12);
			dst->data_barker = SUB(dst->data_bpsk, 14);
306
#undef SUB
307 308
			target += sizeof(*dst);
			source += sizeof(*src);
309 310 311 312 313 314
		}
	}

	return 0;
}

315 316 317 318 319 320 321 322 323 324 325 326
static int p54_convert_rev1(struct ieee80211_hw *dev,
			    struct pda_pa_curve_data *curve_data)
{
	struct p54_common *priv = dev->priv;
	struct p54_pa_curve_data_sample *dst;
	struct pda_pa_curve_data_sample_rev1 *src;
	size_t cd_len = sizeof(*curve_data) +
		(curve_data->points_per_channel*sizeof(*dst) + 2) *
		 curve_data->channels;
	unsigned int i, j;
	void *source, *target;

327 328
	priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
				   GFP_KERNEL);
329 330 331
	if (!priv->curve_data)
		return -ENOMEM;

332 333 334 335 336 337
	priv->curve_data->entries = curve_data->channels;
	priv->curve_data->entry_size = sizeof(__le16) +
		sizeof(*dst) * curve_data->points_per_channel;
	priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
	priv->curve_data->len = cd_len;
	memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
338
	source = curve_data->data;
339
	target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
	for (i = 0; i < curve_data->channels; i++) {
		__le16 *freq = source;
		source += sizeof(__le16);
		*((__le16 *)target) = *freq;
		target += sizeof(__le16);
		for (j = 0; j < curve_data->points_per_channel; j++) {
			memcpy(target, source, sizeof(*src));

			target += sizeof(*dst);
			source += sizeof(*src);
		}
		source++;
	}

	return 0;
}

357 358
static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
                              "Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
359
static int p54_init_xbow_synth(struct ieee80211_hw *dev);
360

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
			     u16 type)
{
	struct p54_common *priv = dev->priv;
	int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
	int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
	int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
	int i;

	if (len != (entry_size * num_entries)) {
		printk(KERN_ERR "%s: unknown rssi calibration data packing "
				 " type:(%x) len:%d.\n",
		       wiphy_name(dev->wiphy), type, len);

		print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
				     data, len);

		printk(KERN_ERR "%s: please report this issue.\n",
			wiphy_name(dev->wiphy));
		return;
	}

	for (i = 0; i < num_entries; i++) {
		struct pda_rssi_cal_entry *cal = data +
						 (offset + i * entry_size);
		priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
		priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
	}
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
static void p54_parse_default_country(struct ieee80211_hw *dev,
				      void *data, int len)
{
	struct pda_country *country;

	if (len != sizeof(*country)) {
		printk(KERN_ERR "%s: found possible invalid default country "
				"eeprom entry. (entry size: %d)\n",
		       wiphy_name(dev->wiphy), len);

		print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
				     data, len);

		printk(KERN_ERR "%s: please report this issue.\n",
			wiphy_name(dev->wiphy));
		return;
	}

	country = (struct pda_country *) data;
	if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
		regulatory_hint(dev->wiphy, country->alpha2);
	else {
		/* TODO:
		 * write a shared/common function that converts
		 * "Regulatory domain codes" (802.11-2007 14.8.2.2)
		 * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
		 */
	}
}

421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
static int p54_convert_output_limits(struct ieee80211_hw *dev,
				     u8 *data, size_t len)
{
	struct p54_common *priv = dev->priv;

	if (len < 2)
		return -EINVAL;

	if (data[0] != 0) {
		printk(KERN_ERR "%s: unknown output power db revision:%x\n",
		       wiphy_name(dev->wiphy), data[0]);
		return -EINVAL;
	}

	if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
		return -EINVAL;

	priv->output_limit = kmalloc(data[1] *
		sizeof(struct pda_channel_output_limit) +
		sizeof(*priv->output_limit), GFP_KERNEL);

	if (!priv->output_limit)
		return -ENOMEM;

	priv->output_limit->offset = 0;
	priv->output_limit->entries = data[1];
	priv->output_limit->entry_size =
		sizeof(struct pda_channel_output_limit);
	priv->output_limit->len = priv->output_limit->entry_size *
				  priv->output_limit->entries +
				  priv->output_limit->offset;

	memcpy(priv->output_limit->data, &data[2],
	       data[1] * sizeof(struct pda_channel_output_limit));

	return 0;
}

static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
					       size_t total_len)
{
	struct p54_cal_database *dst;
	size_t payload_len, entries, entry_size, offset;

	payload_len = le16_to_cpu(src->len);
	entries = le16_to_cpu(src->entries);
	entry_size = le16_to_cpu(src->entry_size);
	offset = le16_to_cpu(src->offset);
	if (((entries * entry_size + offset) != payload_len) ||
	     (payload_len + sizeof(*src) != total_len))
		return NULL;

	dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
	if (!dst)
		return NULL;

	dst->entries = entries;
	dst->entry_size = entry_size;
	dst->offset = offset;
	dst->len = payload_len;

	memcpy(dst->data, src->data, payload_len);
	return dst;
}

C
Christian Lamparter 已提交
486
int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
487 488 489 490 491 492 493
{
	struct p54_common *priv = dev->priv;
	struct eeprom_pda_wrap *wrap = NULL;
	struct pda_entry *entry;
	unsigned int data_len, entry_len;
	void *tmp;
	int err;
494
	u8 *end = (u8 *)eeprom + len;
C
Christian Lamparter 已提交
495
	u16 synth = 0;
496 497

	wrap = (struct eeprom_pda_wrap *) eeprom;
498
	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
499 500 501

	/* verify that at least the entry length/code fits */
	while ((u8 *)entry <= end - sizeof(*entry)) {
502 503
		entry_len = le16_to_cpu(entry->len);
		data_len = ((entry_len - 1) << 1);
504 505 506 507 508

		/* abort if entry exceeds whole structure */
		if ((u8 *)entry + sizeof(*entry) + data_len > end)
			break;

509 510
		switch (le16_to_cpu(entry->code)) {
		case PDR_MAC_ADDRESS:
511 512
			if (data_len != ETH_ALEN)
				break;
513 514 515
			SET_IEEE80211_PERM_ADDR(dev, entry->data);
			break;
		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
516 517 518 519 520
			if (priv->output_limit)
				break;
			err = p54_convert_output_limits(dev, entry->data,
							data_len);
			if (err)
521 522
				goto err;
			break;
523 524 525 526
		case PDR_PRISM_PA_CAL_CURVE_DATA: {
			struct pda_pa_curve_data *curve_data =
				(struct pda_pa_curve_data *)entry->data;
			if (data_len < sizeof(*curve_data)) {
527 528 529 530
				err = -EINVAL;
				goto err;
			}

531 532 533 534 535 536 537 538
			switch (curve_data->cal_method_rev) {
			case 0:
				err = p54_convert_rev0(dev, curve_data);
				break;
			case 1:
				err = p54_convert_rev1(dev, curve_data);
				break;
			default:
C
Christian Lamparter 已提交
539
				printk(KERN_ERR "%s: unknown curve data "
540
						"revision %d\n",
C
Christian Lamparter 已提交
541
						wiphy_name(dev->wiphy),
542 543 544
						curve_data->cal_method_rev);
				err = -ENODEV;
				break;
545
			}
546 547
			if (err)
				goto err;
C
Chr 已提交
548 549
			}
			break;
550 551 552 553 554 555 556 557 558 559
		case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
			priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
			if (!priv->iq_autocal) {
				err = -ENOMEM;
				goto err;
			}

			memcpy(priv->iq_autocal, entry->data, data_len);
			priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
			break;
560 561 562
		case PDR_DEFAULT_COUNTRY:
			p54_parse_default_country(dev, entry->data, data_len);
			break;
563 564 565 566
		case PDR_INTERFACE_LIST:
			tmp = entry->data;
			while ((u8 *)tmp < entry->data + data_len) {
				struct bootrec_exp_if *exp_if = tmp;
567 568
				if (le16_to_cpu(exp_if->if_id) == 0xf)
					synth = le16_to_cpu(exp_if->variant);
569 570 571 572
				tmp += sizeof(struct bootrec_exp_if);
			}
			break;
		case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
573 574
			if (data_len < 2)
				break;
575 576
			priv->version = *(u8 *)(entry->data + 1);
			break;
577 578 579 580 581 582
		case PDR_RSSI_LINEAR_APPROXIMATION:
		case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
		case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
			p54_parse_rssical(dev, entry->data, data_len,
					  le16_to_cpu(entry->code));
			break;
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
		case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
			__le16 *src = (void *) entry->data;
			s16 *dst = (void *) &priv->rssical_db;
			int i;

			if (data_len != sizeof(priv->rssical_db)) {
				err = -EINVAL;
				goto err;
			}
			for (i = 0; i < sizeof(priv->rssical_db) /
					sizeof(*src); i++)
				*(dst++) = (s16) le16_to_cpu(*(src++));
			}
			break;
		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
			struct pda_custom_wrapper *pda = (void *) entry->data;
			if (priv->output_limit || data_len < sizeof(*pda))
				break;
			priv->output_limit = p54_convert_db(pda, data_len);
			}
			break;
		case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
			struct pda_custom_wrapper *pda = (void *) entry->data;
			if (priv->curve_data || data_len < sizeof(*pda))
				break;
			priv->curve_data = p54_convert_db(pda, data_len);
			}
			break;
611
		case PDR_END:
612 613
			/* make it overrun */
			entry_len = len;
614
			break;
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
		case PDR_MANUFACTURING_PART_NUMBER:
		case PDR_PDA_VERSION:
		case PDR_NIC_SERIAL_NUMBER:
		case PDR_REGULATORY_DOMAIN_LIST:
		case PDR_TEMPERATURE_TYPE:
		case PDR_PRISM_PCI_IDENTIFIER:
		case PDR_COUNTRY_INFORMATION:
		case PDR_OEM_NAME:
		case PDR_PRODUCT_NAME:
		case PDR_UTF8_OEM_NAME:
		case PDR_UTF8_PRODUCT_NAME:
		case PDR_COUNTRY_LIST:
		case PDR_ANTENNA_GAIN:
		case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA:
		case PDR_REGULATORY_POWER_LIMITS:
		case PDR_RADIATED_TRANSMISSION_CORRECTION:
		case PDR_PRISM_TX_IQ_CALIBRATION:
		case PDR_BASEBAND_REGISTERS:
		case PDR_PER_CHANNEL_BASEBAND_REGISTERS:
			break;
635
		default:
C
Christian Lamparter 已提交
636 637
			printk(KERN_INFO "%s: unknown eeprom code : 0x%x\n",
				wiphy_name(dev->wiphy),
638 639
				le16_to_cpu(entry->code));
			break;
640 641 642 643 644
		}

		entry = (void *)entry + (entry_len + 1)*2;
	}

C
Christian Lamparter 已提交
645 646
	if (!synth || !priv->iq_autocal || !priv->output_limit ||
	    !priv->curve_data) {
C
Christian Lamparter 已提交
647 648
		printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
			wiphy_name(dev->wiphy));
649 650 651 652
		err = -EINVAL;
		goto err;
	}

653
	priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
654
	if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
655
		p54_init_xbow_synth(dev);
656
	if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
657
		dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
658
	if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
659
		dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
660 661 662 663
	if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
		priv->rx_diversity_mask = 3;
	if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
		priv->tx_diversity_mask = 3;
664 665 666 667 668 669 670 671 672 673

	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
		u8 perm_addr[ETH_ALEN];

		printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
			wiphy_name(dev->wiphy));
		random_ether_addr(perm_addr);
		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
	}

J
Johannes Berg 已提交
674
	printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
675
		wiphy_name(dev->wiphy),
J
Johannes Berg 已提交
676
		dev->wiphy->perm_addr,
677 678
		priv->version, p54_rf_chips[priv->rxhw]);

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
	return 0;

  err:
	if (priv->iq_autocal) {
		kfree(priv->iq_autocal);
		priv->iq_autocal = NULL;
	}

	if (priv->output_limit) {
		kfree(priv->output_limit);
		priv->output_limit = NULL;
	}

	if (priv->curve_data) {
		kfree(priv->curve_data);
		priv->curve_data = NULL;
	}

C
Christian Lamparter 已提交
697 698
	printk(KERN_ERR "%s: eeprom parse failed!\n",
		wiphy_name(dev->wiphy));
699 700
	return err;
}
C
Christian Lamparter 已提交
701
EXPORT_SYMBOL_GPL(p54_parse_eeprom);
702

703 704
static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
{
705 706 707
	struct p54_common *priv = dev->priv;
	int band = dev->conf.channel->band;

708 709 710 711 712 713 714 715
	if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW)
		return ((rssi * priv->rssical_db[band].mul) / 64 +
			 priv->rssical_db[band].add) / 4;
	else
		/*
		 * TODO: find the correct formula
		 */
		return ((rssi * priv->rssical_db[band].mul) / 64 +
716
			 priv->rssical_db[band].add) / 4;
717 718
}

719
static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
720
{
C
Christian Lamparter 已提交
721
	struct p54_common *priv = dev->priv;
722
	struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
723 724
	struct ieee80211_rx_status rx_status = {0};
	u16 freq = le16_to_cpu(hdr->freq);
725
	size_t header_len = sizeof(*hdr);
C
Christian Lamparter 已提交
726
	u32 tsf32;
727
	u8 rate = hdr->rate & 0xf;
728

729 730 731 732 733 734 735 736
	/*
	 * If the device is in a unspecified state we have to
	 * ignore all data frames. Else we could end up with a
	 * nasty crash.
	 */
	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
		return 0;

737
	if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
C
Christian Lamparter 已提交
738 739 740 741 742 743
		if (priv->filter_flags & FIF_FCSFAIL)
			rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
		else
			return 0;
	}

744 745 746 747 748 749
	if (hdr->decrypt_status == P54_DECRYPT_OK)
		rx_status.flag |= RX_FLAG_DECRYPTED;
	if ((hdr->decrypt_status == P54_DECRYPT_FAIL_MICHAEL) ||
	    (hdr->decrypt_status == P54_DECRYPT_FAIL_TKIP))
		rx_status.flag |= RX_FLAG_MMIC_ERROR;

750 751
	rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
	rx_status.noise = priv->noise;
752
	/* XX correct? */
753
	rx_status.qual = (100 * hdr->rssi) / 127;
C
Christian Lamparter 已提交
754 755
	if (hdr->rate & 0x10)
		rx_status.flag |= RX_FLAG_SHORTPRE;
756 757 758 759 760
	if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
		rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
	else
		rx_status.rate_idx = rate;

761
	rx_status.freq = freq;
762
	rx_status.band =  dev->conf.channel->band;
763
	rx_status.antenna = hdr->antenna;
C
Christian Lamparter 已提交
764 765 766 767 768 769 770

	tsf32 = le32_to_cpu(hdr->tsf32);
	if (tsf32 < priv->tsf_low32)
		priv->tsf_high32++;
	rx_status.mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
	priv->tsf_low32 = tsf32;

771
	rx_status.flag |= RX_FLAG_TSFT;
772

773
	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
774 775 776
		header_len += hdr->align[0];

	skb_pull(skb, header_len);
777 778 779
	skb_trim(skb, le16_to_cpu(hdr->len));

	ieee80211_rx_irqsafe(dev, skb, &rx_status);
780

781 782 783
	queue_delayed_work(dev->workqueue, &priv->work,
			   msecs_to_jiffies(P54_STATISTICS_UPDATE));

784
	return -1;
785 786 787 788 789 790 791
}

static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	int i;

C
Christian Lamparter 已提交
792 793 794
	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
		return ;

795
	for (i = 0; i < dev->queues; i++)
796 797
		if (priv->tx_stats[i + P54_QUEUE_DATA].len <
		    priv->tx_stats[i + P54_QUEUE_DATA].limit)
798 799 800
			ieee80211_wake_queue(dev, i);
}

C
Christian Lamparter 已提交
801 802 803 804
void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
	struct ieee80211_tx_info *info;
805
	struct p54_tx_info *range;
C
Christian Lamparter 已提交
806 807 808
	unsigned long flags;
	u32 freed = 0, last_addr = priv->rx_start;

C
Christian Lamparter 已提交
809
	if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
C
Christian Lamparter 已提交
810 811
		return;

812 813 814 815 816 817
	/*
	 * don't try to free an already unlinked skb
	 */
	if (unlikely((!skb->next) || (!skb->prev)))
		return;

C
Christian Lamparter 已提交
818 819 820 821 822
	spin_lock_irqsave(&priv->tx_queue.lock, flags);
	info = IEEE80211_SKB_CB(skb);
	range = (void *)info->rate_driver_data;
	if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
		struct ieee80211_tx_info *ni;
823
		struct p54_tx_info *mr;
C
Christian Lamparter 已提交
824 825

		ni = IEEE80211_SKB_CB(skb->prev);
826
		mr = (struct p54_tx_info *)ni->rate_driver_data;
C
Christian Lamparter 已提交
827 828 829 830
		last_addr = mr->end_addr;
	}
	if (skb->next != (struct sk_buff *)&priv->tx_queue) {
		struct ieee80211_tx_info *ni;
831
		struct p54_tx_info *mr;
C
Christian Lamparter 已提交
832 833

		ni = IEEE80211_SKB_CB(skb->next);
834
		mr = (struct p54_tx_info *)ni->rate_driver_data;
C
Christian Lamparter 已提交
835 836 837 838 839
		freed = mr->start_addr - last_addr;
	} else
		freed = priv->rx_end - last_addr;
	__skb_unlink(skb, &priv->tx_queue);
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
840
	dev_kfree_skb_any(skb);
C
Christian Lamparter 已提交
841

842
	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
C
Christian Lamparter 已提交
843 844 845 846 847
		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
		p54_wake_free_queues(dev);
}
EXPORT_SYMBOL_GPL(p54_free_skb);

848 849 850 851
static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
					   __le32 req_id)
{
	struct p54_common *priv = dev->priv;
852
	struct sk_buff *entry;
853 854 855
	unsigned long flags;

	spin_lock_irqsave(&priv->tx_queue.lock, flags);
856
	entry = priv->tx_queue.next;
857 858 859 860 861 862 863 864 865 866 867 868 869
	while (entry != (struct sk_buff *)&priv->tx_queue) {
		struct p54_hdr *hdr = (struct p54_hdr *) entry->data;

		if (hdr->req_id == req_id) {
			spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
			return entry;
		}
		entry = entry->next;
	}
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
	return NULL;
}

870 871 872
static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
873 874
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
	struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
875
	struct sk_buff *entry;
876
	u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
877
	struct p54_tx_info *range = NULL;
878 879
	u32 freed = 0;
	u32 last_addr = priv->rx_start;
C
Chr 已提交
880
	unsigned long flags;
J
Johannes Berg 已提交
881
	int count, idx;
882

C
Chr 已提交
883
	spin_lock_irqsave(&priv->tx_queue.lock, flags);
884
	entry = (struct sk_buff *) priv->tx_queue.next;
885
	while (entry != (struct sk_buff *)&priv->tx_queue) {
886
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
887 888
		struct p54_hdr *entry_hdr;
		struct p54_tx_data *entry_data;
889
		unsigned int pad = 0, frame_len;
890

891 892 893 894 895 896
		range = (void *)info->rate_driver_data;
		if (range->start_addr != addr) {
			last_addr = range->end_addr;
			entry = entry->next;
			continue;
		}
897

898 899
		if (entry->next != (struct sk_buff *)&priv->tx_queue) {
			struct ieee80211_tx_info *ni;
900
			struct p54_tx_info *mr;
901

902
			ni = IEEE80211_SKB_CB(entry->next);
903
			mr = (struct p54_tx_info *)ni->rate_driver_data;
904 905 906 907 908 909 910 911
			freed = mr->start_addr - last_addr;
		} else
			freed = priv->rx_end - last_addr;

		last_addr = range->end_addr;
		__skb_unlink(entry, &priv->tx_queue);
		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);

912
		frame_len = entry->len;
913 914 915
		entry_hdr = (struct p54_hdr *) entry->data;
		entry_data = (struct p54_tx_data *) entry_hdr->data;
		priv->tx_stats[entry_data->hw_queue].len--;
916
		priv->stats.dot11ACKFailureCount += payload->tries - 1;
917

918 919 920 921 922 923 924 925 926
		/*
		 * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
		 * generated by the driver. Therefore tx_status is bogus
		 * and we don't want to confuse the mac80211 stack.
		 */
		if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) {
			if (entry_data->hw_queue == P54_QUEUE_BEACON)
				priv->cached_beacon = NULL;

C
Christian Lamparter 已提交
927 928 929 930
			kfree_skb(entry);
			goto out;
		}

931 932 933 934 935 936 937 938 939 940
		/*
		 * Clear manually, ieee80211_tx_info_clear_status would
		 * clear the counts too and we need them.
		 */
		memset(&info->status.ampdu_ack_len, 0,
		       sizeof(struct ieee80211_tx_info) -
		       offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
		BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
				      status.ampdu_ack_len) != 23);

941
		if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
942 943 944
			pad = entry_data->align[0];

		/* walk through the rates array and adjust the counts */
945
		count = payload->tries;
946 947 948 949 950 951 952 953 954
		for (idx = 0; idx < 4; idx++) {
			if (count >= info->status.rates[idx].count) {
				count -= info->status.rates[idx].count;
			} else if (count > 0) {
				info->status.rates[idx].count = count;
				count = 0;
			} else {
				info->status.rates[idx].idx = -1;
				info->status.rates[idx].count = 0;
955
			}
956
		}
J
Johannes Berg 已提交
957

958 959 960
		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
		     (!payload->status))
			info->flags |= IEEE80211_TX_STAT_ACK;
961
		if (payload->status & P54_TX_PSM_CANCELLED)
962 963
			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
		info->status.ack_signal = p54_rssi_to_dbm(dev,
964
				(int)payload->ack_rssi);
C
Christian Lamparter 已提交
965

966 967 968
		/* Undo all changes to the frame. */
		switch (entry_data->key_type) {
		case P54_CRYPTO_TKIPMICHAEL: {
C
Christian Lamparter 已提交
969
			u8 *iv = (u8 *)(entry_data->align + pad +
970
					entry_data->crypt_offset);
C
Christian Lamparter 已提交
971 972 973 974 975

			/* Restore the original TKIP IV. */
			iv[2] = iv[0];
			iv[0] = iv[1];
			iv[1] = (iv[0] | 0x20) & 0x7f;	/* WEPSeed - 8.3.2.2 */
976 977 978 979 980 981 982 983 984 985

			frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */
			break;
			}
		case P54_CRYPTO_AESCCMP:
			frame_len -= 8; /* remove CCMP_MIC */
			break;
		case P54_CRYPTO_WEP:
			frame_len -= 4; /* remove WEP_ICV */
			break;
C
Christian Lamparter 已提交
986
		}
987
		skb_trim(entry, frame_len);
988 989 990
		skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
		ieee80211_tx_status_irqsafe(dev, entry);
		goto out;
991
	}
C
Chr 已提交
992
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
993

C
Chr 已提交
994
out:
995
	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
996
		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
997 998 999
		p54_wake_free_queues(dev);
}

1000 1001 1002
static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
				   struct sk_buff *skb)
{
1003
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
1004 1005 1006 1007 1008 1009
	struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
	struct p54_common *priv = dev->priv;

	if (!priv->eeprom)
		return ;

1010 1011 1012 1013 1014 1015 1016
	if (priv->fw_var >= 0x509) {
		memcpy(priv->eeprom, eeprom->v2.data,
		       le16_to_cpu(eeprom->v2.len));
	} else {
		memcpy(priv->eeprom, eeprom->v1.data,
		       le16_to_cpu(eeprom->v1.len));
	}
1017 1018 1019 1020

	complete(&priv->eeprom_comp);
}

1021 1022 1023
static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
1024
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
1025
	struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
1026 1027 1028 1029
	u32 tsf32;

	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
		return ;
1030

1031
	tsf32 = le32_to_cpu(stats->tsf32);
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	if (tsf32 < priv->tsf_low32)
		priv->tsf_high32++;
	priv->tsf_low32 = tsf32;

	priv->stats.dot11RTSFailureCount = le32_to_cpu(stats->rts_fail);
	priv->stats.dot11RTSSuccessCount = le32_to_cpu(stats->rts_success);
	priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);

	priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise));

1042
	p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id));
1043 1044
}

C
Christian Lamparter 已提交
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
	struct p54_trap *trap = (struct p54_trap *) hdr->data;
	u16 event = le16_to_cpu(trap->event);
	u16 freq = le16_to_cpu(trap->frequency);

	switch (event) {
	case P54_TRAP_BEACON_TX:
		break;
	case P54_TRAP_RADAR:
		printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
			wiphy_name(dev->wiphy), freq);
		break;
	case P54_TRAP_NO_BEACON:
		break;
	case P54_TRAP_SCAN:
		break;
	case P54_TRAP_TBTT:
		break;
	case P54_TRAP_TIMER:
		break;
	default:
		printk(KERN_INFO "%s: received event:%x freq:%d\n",
		       wiphy_name(dev->wiphy), event, freq);
		break;
	}
}

1074
static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
1075
{
1076
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
1077 1078 1079 1080 1081

	switch (le16_to_cpu(hdr->type)) {
	case P54_CONTROL_TYPE_TXDONE:
		p54_rx_frame_sent(dev, skb);
		break;
C
Christian Lamparter 已提交
1082 1083 1084
	case P54_CONTROL_TYPE_TRAP:
		p54_rx_trap(dev, skb);
		break;
1085 1086
	case P54_CONTROL_TYPE_BBP:
		break;
1087 1088 1089
	case P54_CONTROL_TYPE_STAT_READBACK:
		p54_rx_stats(dev, skb);
		break;
1090 1091 1092
	case P54_CONTROL_TYPE_EEPROM_READBACK:
		p54_rx_eeprom_readback(dev, skb);
		break;
1093 1094 1095 1096 1097
	default:
		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
		       wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
		break;
	}
1098 1099

	return 0;
1100 1101 1102 1103 1104
}

/* returns zero if skb can be reused */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
1105
	u16 type = le16_to_cpu(*((__le16 *)skb->data));
1106

1107
	if (type & P54_HDR_FLAG_CONTROL)
1108 1109 1110
		return p54_rx_control(dev, skb);
	else
		return p54_rx_data(dev, skb);
1111 1112 1113 1114 1115 1116 1117 1118 1119
}
EXPORT_SYMBOL_GPL(p54_rx);

/*
 * So, the firmware is somewhat stupid and doesn't know what places in its
 * memory incoming data should go to. By poking around in the firmware, we
 * can find some unused memory to upload our packets to. However, data that we
 * want the card to TX needs to stay intact until the card has told us that
 * it is done with it. This function finds empty places we can upload to and
1120 1121
 * marks allocated areas as reserved if necessary. p54_rx_frame_sent or
 * p54_free_skb frees allocated areas.
1122
 */
C
Christian Lamparter 已提交
1123
static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
1124
			       struct p54_hdr *data, u32 len)
1125 1126
{
	struct p54_common *priv = dev->priv;
1127
	struct sk_buff *entry;
1128
	struct sk_buff *target_skb = NULL;
C
Christian Lamparter 已提交
1129
	struct ieee80211_tx_info *info;
1130
	struct p54_tx_info *range;
1131 1132 1133 1134 1135
	u32 last_addr = priv->rx_start;
	u32 largest_hole = 0;
	u32 target_addr = priv->rx_start;
	unsigned long flags;
	unsigned int left;
1136
	len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
1137

C
Christian Lamparter 已提交
1138 1139 1140
	if (!skb)
		return -EINVAL;

1141
	spin_lock_irqsave(&priv->tx_queue.lock, flags);
1142

1143
	left = skb_queue_len(&priv->tx_queue);
1144 1145 1146 1147 1148 1149 1150
	if (unlikely(left >= 28)) {
		/*
		 * The tx_queue is nearly full!
		 * We have throttle normal data traffic, because we must
		 * have a few spare slots for control frames left.
		 */
		ieee80211_stop_queues(dev);
1151 1152
		queue_delayed_work(dev->workqueue, &priv->work,
				   msecs_to_jiffies(P54_TX_TIMEOUT));
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164

		if (unlikely(left == 32)) {
			/*
			 * The tx_queue is now really full.
			 *
			 * TODO: check if the device has crashed and reset it.
			 */
			spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
			return -ENOSPC;
		}
	}

1165
	entry = priv->tx_queue.next;
1166 1167
	while (left--) {
		u32 hole_size;
C
Christian Lamparter 已提交
1168 1169
		info = IEEE80211_SKB_CB(entry);
		range = (void *)info->rate_driver_data;
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
		hole_size = range->start_addr - last_addr;
		if (!target_skb && hole_size >= len) {
			target_skb = entry->prev;
			hole_size -= len;
			target_addr = last_addr;
		}
		largest_hole = max(largest_hole, hole_size);
		last_addr = range->end_addr;
		entry = entry->next;
	}
	if (!target_skb && priv->rx_end - last_addr >= len) {
		target_skb = priv->tx_queue.prev;
		largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
		if (!skb_queue_empty(&priv->tx_queue)) {
C
Christian Lamparter 已提交
1184 1185
			info = IEEE80211_SKB_CB(target_skb);
			range = (void *)info->rate_driver_data;
1186 1187 1188 1189 1190
			target_addr = range->end_addr;
		}
	} else
		largest_hole = max(largest_hole, priv->rx_end - last_addr);

C
Christian Lamparter 已提交
1191 1192 1193
	if (!target_skb) {
		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
		ieee80211_stop_queues(dev);
1194
		return -ENOSPC;
1195
	}
C
Christian Lamparter 已提交
1196 1197 1198 1199 1200 1201

	info = IEEE80211_SKB_CB(skb);
	range = (void *)info->rate_driver_data;
	range->start_addr = target_addr;
	range->end_addr = target_addr + len;
	__skb_queue_after(&priv->tx_queue, target_skb, skb);
1202 1203
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);

1204
	if (largest_hole < priv->headroom + sizeof(struct p54_hdr) +
C
Christian Lamparter 已提交
1205 1206 1207
			   48 + IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
		ieee80211_stop_queues(dev);

1208
	data->req_id = cpu_to_le32(target_addr + priv->headroom);
C
Christian Lamparter 已提交
1209 1210 1211
	return 0;
}

1212 1213
static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev, u16 hdr_flags,
				     u16 payload_len, u16 type, gfp_t memflags)
C
Christian Lamparter 已提交
1214 1215
{
	struct p54_common *priv = dev->priv;
1216
	struct p54_hdr *hdr;
C
Christian Lamparter 已提交
1217
	struct sk_buff *skb;
1218
	size_t frame_len = sizeof(*hdr) + payload_len;
C
Christian Lamparter 已提交
1219

1220 1221 1222 1223
	if (frame_len > P54_MAX_CTRL_FRAME_LEN)
		return NULL;

	skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags);
C
Christian Lamparter 已提交
1224 1225 1226 1227
	if (!skb)
		return NULL;
	skb_reserve(skb, priv->tx_hdr_len);

1228 1229
	hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
	hdr->flags = cpu_to_le16(hdr_flags);
1230
	hdr->len = cpu_to_le16(payload_len);
C
Christian Lamparter 已提交
1231
	hdr->type = cpu_to_le16(type);
1232
	hdr->tries = hdr->rts_tries = 0;
C
Christian Lamparter 已提交
1233

1234
	if (p54_assign_address(dev, skb, hdr, frame_len)) {
C
Christian Lamparter 已提交
1235 1236 1237 1238
		kfree_skb(skb);
		return NULL;
	}
	return skb;
1239 1240
}

1241 1242 1243 1244
int p54_read_eeprom(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct p54_eeprom_lm86 *eeprom_hdr;
C
Christian Lamparter 已提交
1245
	struct sk_buff *skb;
1246
	size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
1247 1248 1249
	int ret = -ENOMEM;
	void *eeprom = NULL;

1250 1251 1252 1253 1254 1255
	maxblocksize = EEPROM_READBACK_LEN;
	if (priv->fw_var >= 0x509)
		maxblocksize -= 0xc;
	else
		maxblocksize -= 0x4;

1256 1257 1258
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*eeprom_hdr) +
			    maxblocksize, P54_CONTROL_TYPE_EEPROM_READBACK,
			    GFP_KERNEL);
C
Christian Lamparter 已提交
1259
	if (!skb)
1260 1261 1262 1263 1264 1265 1266 1267
		goto free;
	priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
	if (!priv->eeprom)
		goto free;
	eeprom = kzalloc(eeprom_size, GFP_KERNEL);
	if (!eeprom)
		goto free;

C
Christian Lamparter 已提交
1268
	eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
1269
		     sizeof(*eeprom_hdr) + maxblocksize);
1270 1271

	while (eeprom_size) {
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
		blocksize = min(eeprom_size, maxblocksize);
		if (priv->fw_var < 0x509) {
			eeprom_hdr->v1.offset = cpu_to_le16(offset);
			eeprom_hdr->v1.len = cpu_to_le16(blocksize);
		} else {
			eeprom_hdr->v2.offset = cpu_to_le32(offset);
			eeprom_hdr->v2.len = cpu_to_le16(blocksize);
			eeprom_hdr->v2.magic2 = 0xf;
			memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4);
		}
1282
		priv->tx(dev, skb);
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299

		if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
			printk(KERN_ERR "%s: device does not respond!\n",
				wiphy_name(dev->wiphy));
			ret = -EBUSY;
			goto free;
	        }

		memcpy(eeprom + offset, priv->eeprom, blocksize);
		offset += blocksize;
		eeprom_size -= blocksize;
	}

	ret = p54_parse_eeprom(dev, eeprom, offset);
free:
	kfree(priv->eeprom);
	priv->eeprom = NULL;
C
Christian Lamparter 已提交
1300
	p54_free_skb(dev, skb);
1301 1302 1303 1304 1305 1306
	kfree(eeprom);

	return ret;
}
EXPORT_SYMBOL_GPL(p54_read_eeprom);

C
Christian Lamparter 已提交
1307 1308 1309 1310 1311 1312 1313
static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
		bool set)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
	struct p54_tim *tim;

1314 1315
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim),
			    P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
C
Christian Lamparter 已提交
1316 1317 1318 1319 1320 1321
	if (!skb)
		return -ENOMEM;

	tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
	tim->count = 1;
	tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid);
1322
	priv->tx(dev, skb);
C
Christian Lamparter 已提交
1323 1324 1325 1326 1327 1328 1329 1330 1331
	return 0;
}

static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
	struct p54_sta_unlock *sta;

1332 1333
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta),
			    P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
C
Christian Lamparter 已提交
1334 1335 1336 1337 1338
	if (!skb)
		return -ENOMEM;

	sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
	memcpy(sta->addr, addr, ETH_ALEN);
1339
	priv->tx(dev, skb);
C
Christian Lamparter 已提交
1340 1341 1342
	return 0;
}

1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
			      enum sta_notify_cmd notify_cmd,
			      struct ieee80211_sta *sta)
{
	switch (notify_cmd) {
	case STA_NOTIFY_ADD:
	case STA_NOTIFY_REMOVE:
		/*
		 * Notify the firmware that we don't want or we don't
		 * need to buffer frames for this station anymore.
		 */

1355 1356 1357 1358
		p54_sta_unlock(dev, sta->addr);
		break;
	case STA_NOTIFY_AWAKE:
		/* update the firmware's filter table */
1359 1360 1361 1362 1363 1364 1365
		p54_sta_unlock(dev, sta->addr);
		break;
	default:
		break;
	}
}

C
Christian Lamparter 已提交
1366 1367 1368 1369 1370 1371 1372
static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
	struct p54_hdr *hdr;
	struct p54_txcancel *cancel;

1373 1374
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel),
			    P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
C
Christian Lamparter 已提交
1375 1376 1377 1378 1379 1380
	if (!skb)
		return -ENOMEM;

	hdr = (void *)entry->data;
	cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
	cancel->req_id = hdr->req_id;
1381
	priv->tx(dev, skb);
C
Christian Lamparter 已提交
1382 1383 1384
	return 0;
}

1385 1386 1387 1388 1389 1390
static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
		struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len,
		u16 *flags, u16 *aid)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct p54_common *priv = dev->priv;
1391
	int ret = 1;
1392 1393

	switch (priv->mode) {
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
	case NL80211_IFTYPE_MONITOR:
		/*
		 * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for
		 * every frame in promiscuous/monitor mode.
		 * see STSW45x0C LMAC API - page 12.
		 */
		*aid = 0;
		*flags = P54_HDR_FLAG_DATA_OUT_PROMISC;
		*queue += P54_QUEUE_DATA;
		break;
1404 1405
	case NL80211_IFTYPE_STATION:
		*aid = 1;
1406 1407 1408 1409 1410
		if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
			*queue = P54_QUEUE_MGMT;
			ret = 0;
		} else
			*queue += P54_QUEUE_DATA;
1411 1412 1413
		break;
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_ADHOC:
1414
	case NL80211_IFTYPE_MESH_POINT:
1415 1416
		if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
			*aid = 0;
1417
			*queue = P54_QUEUE_CAB;
1418 1419
			return 0;
		}
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452

		if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
			if (ieee80211_is_probe_resp(hdr->frame_control)) {
				*aid = 0;
				*queue = P54_QUEUE_MGMT;
				*flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
					 P54_HDR_FLAG_DATA_OUT_NOCANCEL;
				return 0;
			} else if (ieee80211_is_beacon(hdr->frame_control)) {
				*aid = 0;

				if (info->flags & IEEE80211_TX_CTL_INJECTED) {
					/*
					 * Injecting beacons on top of a AP is
					 * not a good idea... nevertheless,
					 * it should be doable.
					 */

					*queue += P54_QUEUE_DATA;
					return 1;
				}

				*flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
				*queue = P54_QUEUE_BEACON;
				*extra_len = IEEE80211_MAX_TIM_LEN;
				return 0;
			} else {
				*queue = P54_QUEUE_MGMT;
				ret = 0;
			}
		} else
			*queue += P54_QUEUE_DATA;

1453 1454 1455
		if (info->control.sta)
			*aid = info->control.sta->aid;
		else
1456
			*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
1457
		break;
1458 1459 1460 1461
	}
	return ret;
}

1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
static u8 p54_convert_algo(enum ieee80211_key_alg alg)
{
	switch (alg) {
	case ALG_WEP:
		return P54_CRYPTO_WEP;
	case ALG_TKIP:
		return P54_CRYPTO_TKIPMICHAEL;
	case ALG_CCMP:
		return P54_CRYPTO_AESCCMP;
	default:
		return 0;
	}
}

1476
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
1477
{
1478
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1479
	struct ieee80211_tx_queue_stats *current_queue;
1480
	struct p54_common *priv = dev->priv;
1481 1482
	struct p54_hdr *hdr;
	struct p54_tx_data *txhdr;
1483
	size_t padding, len, tim_len = 0;
1484
	int i, j, ridx, ret;
1485
	u16 hdr_flags = 0, aid = 0;
1486
	u8 rate, queue, crypt_offset = 0;
1487
	u8 cts_rate = 0x20;
1488
	u8 rc_flags;
J
Johannes Berg 已提交
1489 1490
	u8 calculated_tries[4];
	u8 nrates = 0, nremaining = 8;
1491

1492 1493
	queue = skb_get_queue_mapping(skb);

1494 1495 1496 1497 1498 1499 1500 1501
	ret = p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid);
	current_queue = &priv->tx_stats[queue];
	if (unlikely((current_queue->len > current_queue->limit) && ret))
		return NETDEV_TX_BUSY;
	current_queue->len++;
	current_queue->count++;
	if ((current_queue->len == current_queue->limit) && ret)
		ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
1502 1503 1504 1505

	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
	len = skb->len;

1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
	if (info->control.hw_key) {
		crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
		if (info->control.hw_key->alg == ALG_TKIP) {
			u8 *iv = (u8 *)(skb->data + crypt_offset);
			/*
			 * The firmware excepts that the IV has to have
			 * this special format
			 */
			iv[1] = iv[0];
			iv[0] = iv[2];
			iv[2] = 0;
		}
	}

1520 1521
	txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
	hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
1522 1523

	if (padding)
1524
		hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
1525
	hdr->type = cpu_to_le16(aid);
1526
	hdr->rts_tries = info->control.rates[0].count;
J
Johannes Berg 已提交
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552

	/*
	 * we register the rates in perfect order, and
	 * RTS/CTS won't happen on 5 GHz
	 */
	cts_rate = info->control.rts_cts_rate_idx;

	memset(&txhdr->rateset, 0, sizeof(txhdr->rateset));

	/* see how many rates got used */
	for (i = 0; i < 4; i++) {
		if (info->control.rates[i].idx < 0)
			break;
		nrates++;
	}

	/* limit tries to 8/nrates per rate */
	for (i = 0; i < nrates; i++) {
		/*
		 * The magic expression here is equivalent to 8/nrates for
		 * all values that matter, but avoids division and jumps.
		 * Note that nrates can only take the values 1 through 4.
		 */
		calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1,
						 info->control.rates[i].count);
		nremaining -= calculated_tries[i];
1553
	}
J
Johannes Berg 已提交
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565

	/* if there are tries left, distribute from back to front */
	for (i = nrates - 1; nremaining > 0 && i >= 0; i--) {
		int tmp = info->control.rates[i].count - calculated_tries[i];

		if (tmp <= 0)
			continue;
		/* RC requested more tries at this rate */

		tmp = min_t(int, tmp, nremaining);
		calculated_tries[i] += tmp;
		nremaining -= tmp;
1566
	}
J
Johannes Berg 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591

	ridx = 0;
	for (i = 0; i < nrates && ridx < 8; i++) {
		/* we register the rates in perfect order */
		rate = info->control.rates[i].idx;
		if (info->band == IEEE80211_BAND_5GHZ)
			rate += 4;

		/* store the count we actually calculated for TX status */
		info->control.rates[i].count = calculated_tries[i];

		rc_flags = info->control.rates[i].flags;
		if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) {
			rate |= 0x10;
			cts_rate |= 0x10;
		}
		if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
			rate |= 0x40;
		else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
			rate |= 0x20;
		for (j = 0; j < calculated_tries[i] && ridx < 8; j++) {
			txhdr->rateset[ridx] = rate;
			ridx++;
		}
	}
1592 1593 1594 1595 1596 1597

	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
		hdr_flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;

	/* TODO: enable bursting */
	hdr->flags = cpu_to_le16(hdr_flags);
1598 1599
	hdr->tries = ridx;
	txhdr->rts_rate_idx = 0;
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
	if (info->control.hw_key) {
		txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
		txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
		memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
		if (info->control.hw_key->alg == ALG_TKIP) {
			if (unlikely(skb_tailroom(skb) < 12))
				goto err;
			/* reserve space for the MIC key */
			len += 8;
			memcpy(skb_put(skb, 8), &(info->control.hw_key->key
				[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8);
		}
		/* reserve some space for ICV */
		len += info->control.hw_key->icv_len;
C
Christian Lamparter 已提交
1614 1615
		memset(skb_put(skb, info->control.hw_key->icv_len), 0,
		       info->control.hw_key->icv_len);
1616 1617 1618 1619 1620
	} else {
		txhdr->key_type = 0;
		txhdr->key_len = 0;
	}
	txhdr->crypt_offset = crypt_offset;
1621
	txhdr->hw_queue = queue;
1622
	txhdr->backlog = current_queue->len;
1623
	memset(txhdr->durations, 0, sizeof(txhdr->durations));
1624 1625
	txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ?
		2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask;
1626 1627 1628 1629 1630 1631 1632
	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
		txhdr->longbow.cts_rate = cts_rate;
		txhdr->longbow.output_power = cpu_to_le16(priv->output_power);
	} else {
		txhdr->normal.output_power = priv->output_power;
		txhdr->normal.cts_rate = cts_rate;
	}
1633 1634 1635
	if (padding)
		txhdr->align[0] = padding;

1636
	hdr->len = cpu_to_le16(len);
1637
	/* modifies skb->cb and with it info, so must be last! */
1638 1639
	if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len)))
		goto err;
1640
	priv->tx(dev, skb);
1641 1642 1643 1644

	queue_delayed_work(dev->workqueue, &priv->work,
			   msecs_to_jiffies(P54_TX_FRAME_LIFETIME));

1645
	return NETDEV_TX_OK;
1646 1647 1648

 err:
	skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
1649 1650
	current_queue->len--;
	current_queue->count--;
1651
	return NETDEV_TX_BUSY;
1652 1653
}

C
Christian Lamparter 已提交
1654
static int p54_setup_mac(struct ieee80211_hw *dev)
1655 1656
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
1657
	struct sk_buff *skb;
1658
	struct p54_setup_mac *setup;
C
Christian Lamparter 已提交
1659
	u16 mode;
1660

1661 1662
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup),
			    P54_CONTROL_TYPE_SETUP, GFP_ATOMIC);
C
Christian Lamparter 已提交
1663 1664
	if (!skb)
		return -ENOMEM;
1665

1666
	setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
C
Christian Lamparter 已提交
1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678
	if (dev->conf.radio_enabled) {
		switch (priv->mode) {
		case NL80211_IFTYPE_STATION:
			mode = P54_FILTER_TYPE_STATION;
			break;
		case NL80211_IFTYPE_AP:
			mode = P54_FILTER_TYPE_AP;
			break;
		case NL80211_IFTYPE_ADHOC:
		case NL80211_IFTYPE_MESH_POINT:
			mode = P54_FILTER_TYPE_IBSS;
			break;
1679 1680 1681
		case NL80211_IFTYPE_MONITOR:
			mode = P54_FILTER_TYPE_PROMISCUOUS;
			break;
C
Christian Lamparter 已提交
1682
		default:
1683
			mode = P54_FILTER_TYPE_HIBERNATE;
C
Christian Lamparter 已提交
1684 1685
			break;
		}
1686 1687 1688 1689 1690

		/*
		 * "TRANSPARENT and PROMISCUOUS are mutually exclusive"
		 * STSW45X0C LMAC API - page 12
		 */
1691 1692
		if (((priv->filter_flags & FIF_PROMISC_IN_BSS) ||
		     (priv->filter_flags & FIF_OTHER_BSS)) &&
1693
		    (mode != P54_FILTER_TYPE_PROMISCUOUS))
C
Christian Lamparter 已提交
1694 1695
			mode |= P54_FILTER_TYPE_TRANSPARENT;
	} else
1696
		mode = P54_FILTER_TYPE_HIBERNATE;
C
Christian Lamparter 已提交
1697

1698 1699
	setup->mac_mode = cpu_to_le16(mode);
	memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
C
Christian Lamparter 已提交
1700
	memcpy(setup->bssid, priv->bssid, ETH_ALEN);
1701
	setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */
C
Chr 已提交
1702
	setup->rx_align = 0;
1703
	if (priv->fw_var < 0x500) {
1704
		setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
C
Chr 已提交
1705
		memset(setup->v1.rts_rates, 0, 8);
1706 1707 1708
		setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
		setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
		setup->v1.rxhw = cpu_to_le16(priv->rxhw);
1709
		setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer);
1710
		setup->v1.unalloc0 = cpu_to_le16(0);
1711
	} else {
1712 1713 1714
		setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
		setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
		setup->v2.rxhw = cpu_to_le16(priv->rxhw);
1715
		setup->v2.timer = cpu_to_le16(priv->wakeup_timer);
1716
		setup->v2.truncate = cpu_to_le16(48896);
1717
		setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
1718 1719 1720 1721 1722 1723 1724
		setup->v2.sbss_offset = 0;
		setup->v2.mcast_window = 0;
		setup->v2.rx_rssi_threshold = 0;
		setup->v2.rx_ed_threshold = 0;
		setup->v2.ref_clock = cpu_to_le32(644245094);
		setup->v2.lpf_bandwidth = cpu_to_le16(65535);
		setup->v2.osc_start_delay = cpu_to_le16(65535);
1725
	}
1726
	priv->tx(dev, skb);
1727 1728 1729
	return 0;
}

1730
static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
1731 1732
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
1733
	struct sk_buff *skb;
1734 1735 1736 1737 1738 1739
	struct p54_hdr *hdr;
	struct p54_scan_head *head;
	struct p54_iq_autocal_entry *iq_autocal;
	union p54_scan_body_union *body;
	struct p54_scan_tail_rate *rate;
	struct pda_rssi_cal_entry *rssi;
1740 1741
	unsigned int i;
	void *entry;
1742
	int band = dev->conf.channel->band;
1743
	__le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
1744

1745 1746 1747
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
			    2 + sizeof(*iq_autocal) + sizeof(*body) +
			    sizeof(*rate) + 2 * sizeof(*rssi),
1748
			    P54_CONTROL_TYPE_SCAN, GFP_ATOMIC);
C
Christian Lamparter 已提交
1749
	if (!skb)
1750 1751
		return -ENOMEM;

1752 1753 1754 1755 1756
	head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
	memset(head->scan_params, 0, sizeof(head->scan_params));
	head->mode = cpu_to_le16(mode);
	head->dwell = cpu_to_le16(dwell);
	head->freq = freq;
1757

1758 1759 1760 1761 1762 1763
	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
		__le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
		*pa_power_points = cpu_to_le16(0x0c);
	}

	iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
1764 1765 1766 1767
	for (i = 0; i < priv->iq_autocal_len; i++) {
		if (priv->iq_autocal[i].freq != freq)
			continue;

1768 1769
		memcpy(iq_autocal, &priv->iq_autocal[i].params,
		       sizeof(struct p54_iq_autocal_entry));
1770 1771 1772 1773 1774
		break;
	}
	if (i == priv->iq_autocal_len)
		goto err;

1775 1776 1777 1778 1779
	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
		body = (void *) skb_put(skb, sizeof(body->longbow));
	else
		body = (void *) skb_put(skb, sizeof(body->normal));

1780 1781
	for (i = 0; i < priv->output_limit->entries; i++) {
		__le16 *entry_freq = (void *) (priv->output_limit->data +
1782
				     priv->output_limit->entry_size * i);
1783 1784

		if (*entry_freq != freq)
1785 1786
			continue;

1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804
		if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
			memcpy(&body->longbow.power_limits,
			       (void *) entry_freq + sizeof(__le16),
			       priv->output_limit->entry_size);
		} else {
			struct pda_channel_output_limit *limits =
			       (void *) entry_freq;

			body->normal.val_barker = 0x38;
			body->normal.val_bpsk = body->normal.dup_bpsk =
				limits->val_bpsk;
			body->normal.val_qpsk = body->normal.dup_qpsk =
				limits->val_qpsk;
			body->normal.val_16qam = body->normal.dup_16qam =
				limits->val_16qam;
			body->normal.val_64qam = body->normal.dup_64qam =
				limits->val_64qam;
		}
1805 1806
		break;
	}
1807
	if (i == priv->output_limit->entries)
1808 1809
		goto err;

1810 1811
	entry = (void *)(priv->curve_data->data + priv->curve_data->offset);
	for (i = 0; i < priv->curve_data->entries; i++) {
1812
		if (*((__le16 *)entry) != freq) {
1813
			entry += priv->curve_data->entry_size;
1814 1815 1816
			continue;
		}

1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
		if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
			memcpy(&body->longbow.curve_data,
				(void *) entry + sizeof(__le16),
				priv->curve_data->entry_size);
		} else {
			struct p54_scan_body *chan = &body->normal;
			struct pda_pa_curve_data *curve_data =
				(void *) priv->curve_data->data;

			entry += sizeof(__le16);
			chan->pa_points_per_curve = 8;
			memset(chan->curve_data, 0, sizeof(*chan->curve_data));
			memcpy(chan->curve_data, entry,
			       sizeof(struct p54_pa_curve_data_sample) *
			       min((u8)8, curve_data->points_per_channel));
		}
1833 1834
		break;
	}
1835 1836
	if (i == priv->curve_data->entries)
		goto err;
1837

1838 1839 1840 1841 1842
	if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
		rate = (void *) skb_put(skb, sizeof(*rate));
		rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
		for (i = 0; i < sizeof(rate->rts_rates); i++)
			rate->rts_rates[i] = i;
1843
	}
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864

	rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
	rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
	rssi->add = cpu_to_le16(priv->rssical_db[band].add);
	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
		/* Longbow frontend needs ever more */
		rssi = (void *) skb_put(skb, sizeof(*rssi));
		rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
		rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
	}

	if (priv->fw_var >= 0x509) {
		rate = (void *) skb_put(skb, sizeof(*rate));
		rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
		for (i = 0; i < sizeof(rate->rts_rates); i++)
			rate->rts_rates[i] = i;
	}

	hdr = (struct p54_hdr *) skb->data;
	hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));

1865
	priv->tx(dev, skb);
1866 1867 1868 1869
	return 0;

 err:
	printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
1870
	p54_free_skb(dev, skb);
1871 1872 1873 1874 1875 1876
	return -EINVAL;
}

static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
1877
	struct sk_buff *skb;
1878
	struct p54_led *led;
1879

1880 1881
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led),
			    P54_CONTROL_TYPE_LED, GFP_ATOMIC);
C
Christian Lamparter 已提交
1882
	if (!skb)
1883 1884
		return -ENOMEM;

1885
	led = (struct p54_led *)skb_put(skb, sizeof(*led));
1886 1887 1888 1889
	led->mode = cpu_to_le16(mode);
	led->led_permanent = cpu_to_le16(link);
	led->led_temporary = cpu_to_le16(act);
	led->duration = cpu_to_le16(1000);
1890
	priv->tx(dev, skb);
1891 1892 1893
	return 0;
}

1894
#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop)	\
1895 1896 1897 1898
do {	 							\
	queue.aifs = cpu_to_le16(ai_fs);			\
	queue.cwmin = cpu_to_le16(cw_min);			\
	queue.cwmax = cpu_to_le16(cw_max);			\
1899
	queue.txop = cpu_to_le16(_txop);			\
1900 1901
} while(0)

C
Christian Lamparter 已提交
1902
static int p54_set_edcf(struct ieee80211_hw *dev)
1903 1904
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
1905
	struct sk_buff *skb;
C
Christian Lamparter 已提交
1906
	struct p54_edcf *edcf;
1907

1908 1909
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
			    P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
C
Christian Lamparter 已提交
1910
	if (!skb)
C
Christian Lamparter 已提交
1911 1912
		return -ENOMEM;

C
Christian Lamparter 已提交
1913
	edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
1914
	if (priv->use_short_slot) {
C
Christian Lamparter 已提交
1915 1916 1917
		edcf->slottime = 9;
		edcf->sifs = 0x10;
		edcf->eofpad = 0x00;
1918
	} else {
C
Christian Lamparter 已提交
1919 1920 1921
		edcf->slottime = 20;
		edcf->sifs = 0x0a;
		edcf->eofpad = 0x06;
1922 1923
	}
	/* (see prism54/isl_oid.h for further details) */
C
Christian Lamparter 已提交
1924 1925
	edcf->frameburst = cpu_to_le16(0);
	edcf->round_trip_delay = cpu_to_le16(0);
C
Chr 已提交
1926
	edcf->flags = 0;
C
Christian Lamparter 已提交
1927 1928
	memset(edcf->mapping, 0, sizeof(edcf->mapping));
	memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
1929
	priv->tx(dev, skb);
C
Christian Lamparter 已提交
1930
	return 0;
1931 1932
}

C
Christian Lamparter 已提交
1933 1934 1935 1936 1937 1938 1939 1940 1941
static int p54_set_ps(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
	struct p54_psm *psm;
	u16 mode;
	int i;

	if (dev->conf.flags & IEEE80211_CONF_PS)
1942
		mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC;
C
Christian Lamparter 已提交
1943 1944 1945
	else
		mode = P54_PSM_CAM;

1946 1947
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm),
			    P54_CONTROL_TYPE_PSM, GFP_ATOMIC);
C
Christian Lamparter 已提交
1948 1949 1950 1951 1952 1953 1954 1955 1956
	if (!skb)
		return -ENOMEM;

	psm = (struct p54_psm *)skb_put(skb, sizeof(*psm));
	psm->mode = cpu_to_le16(mode);
	psm->aid = cpu_to_le16(priv->aid);
	for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) {
		psm->intervals[i].interval =
			cpu_to_le16(dev->conf.listen_interval);
1957
		psm->intervals[i].periods = cpu_to_le16(1);
C
Christian Lamparter 已提交
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968
	}

	psm->beacon_rssi_skip_max = 60;
	psm->rssi_delta_threshold = 0;
	psm->nr = 0;

	priv->tx(dev, skb);

	return 0;
}

C
Christian Lamparter 已提交
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
static int p54_beacon_tim(struct sk_buff *skb)
{
	/*
	 * the good excuse for this mess is ... the firmware.
	 * The dummy TIM MUST be at the end of the beacon frame,
	 * because it'll be overwritten!
	 */

	struct ieee80211_mgmt *mgmt = (void *)skb->data;
	u8 *pos, *end;

C
Christian Lamparter 已提交
1980
	if (skb->len <= sizeof(mgmt))
C
Christian Lamparter 已提交
1981 1982 1983 1984 1985
		return -EINVAL;

	pos = (u8 *)mgmt->u.beacon.variable;
	end = skb->data + skb->len;
	while (pos < end) {
C
Christian Lamparter 已提交
1986
		if (pos + 2 + pos[1] > end)
C
Christian Lamparter 已提交
1987 1988 1989 1990 1991 1992 1993
			return -EINVAL;

		if (pos[0] == WLAN_EID_TIM) {
			u8 dtim_len = pos[1];
			u8 dtim_period = pos[3];
			u8 *next = pos + 2 + dtim_len;

C
Christian Lamparter 已提交
1994
			if (dtim_len < 3)
C
Christian Lamparter 已提交
1995
				return -EINVAL;
C
Christian Lamparter 已提交
1996

C
Christian Lamparter 已提交
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045
			memmove(pos, next, end - next);

			if (dtim_len > 3)
				skb_trim(skb, skb->len - (dtim_len - 3));

			pos = end - (dtim_len + 2);

			/* add the dummy at the end */
			pos[0] = WLAN_EID_TIM;
			pos[1] = 3;
			pos[2] = 0;
			pos[3] = dtim_period;
			pos[4] = 0;
			return 0;
		}
		pos += 2 + pos[1];
	}
	return 0;
}

static int p54_beacon_update(struct ieee80211_hw *dev,
			struct ieee80211_vif *vif)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *beacon;
	int ret;

	if (priv->cached_beacon) {
		p54_tx_cancel(dev, priv->cached_beacon);
		/* wait for the last beacon the be freed */
		msleep(10);
	}

	beacon = ieee80211_beacon_get(dev, vif);
	if (!beacon)
		return -ENOMEM;
	ret = p54_beacon_tim(beacon);
	if (ret)
		return ret;
	ret = p54_tx(dev, beacon);
	if (ret)
		return ret;
	priv->cached_beacon = beacon;
	priv->tsf_high32 = 0;
	priv->tsf_low32 = 0;

	return 0;
}

2046 2047 2048 2049
static int p54_start(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	int err;
2050

2051
	mutex_lock(&priv->conf_mutex);
2052
	err = priv->open(dev);
2053 2054
	if (err)
		goto out;
C
Christian Lamparter 已提交
2055 2056 2057 2058 2059
	P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
	P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
	P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
	P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
	err = p54_set_edcf(dev);
2060 2061
	if (err)
		goto out;
C
Christian Lamparter 已提交
2062 2063

	memset(priv->bssid, ~0, ETH_ALEN);
2064
	priv->mode = NL80211_IFTYPE_MONITOR;
C
Christian Lamparter 已提交
2065 2066 2067 2068 2069
	err = p54_setup_mac(dev);
	if (err) {
		priv->mode = NL80211_IFTYPE_UNSPECIFIED;
		goto out;
	}
2070

2071 2072
	queue_delayed_work(dev->workqueue, &priv->work, 0);

2073
out:
2074
	mutex_unlock(&priv->conf_mutex);
2075 2076 2077 2078 2079 2080 2081
	return err;
}

static void p54_stop(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
2082

2083
	mutex_lock(&priv->conf_mutex);
2084
	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
2085
	cancel_delayed_work_sync(&priv->work);
C
Christian Lamparter 已提交
2086 2087 2088
	if (priv->cached_beacon)
		p54_tx_cancel(dev, priv->cached_beacon);

2089
	priv->stop(dev);
2090
	while ((skb = skb_dequeue(&priv->tx_queue)))
2091
		kfree_skb(skb);
C
Christian Lamparter 已提交
2092
	priv->cached_beacon = NULL;
C
Christian Lamparter 已提交
2093
	priv->tsf_high32 = priv->tsf_low32 = 0;
2094
	mutex_unlock(&priv->conf_mutex);
2095 2096
}

2097 2098 2099 2100 2101
static int p54_add_interface(struct ieee80211_hw *dev,
			     struct ieee80211_if_init_conf *conf)
{
	struct p54_common *priv = dev->priv;

2102 2103 2104
	mutex_lock(&priv->conf_mutex);
	if (priv->mode != NL80211_IFTYPE_MONITOR) {
		mutex_unlock(&priv->conf_mutex);
2105
		return -EOPNOTSUPP;
2106
	}
2107 2108

	switch (conf->type) {
2109
	case NL80211_IFTYPE_STATION:
C
Christian Lamparter 已提交
2110 2111
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_AP:
2112
	case NL80211_IFTYPE_MESH_POINT:
2113 2114 2115
		priv->mode = conf->type;
		break;
	default:
2116
		mutex_unlock(&priv->conf_mutex);
2117 2118 2119
		return -EOPNOTSUPP;
	}

2120
	memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
C
Christian Lamparter 已提交
2121
	p54_setup_mac(dev);
2122
	p54_set_leds(dev, 1, 0, 0);
2123
	mutex_unlock(&priv->conf_mutex);
2124 2125 2126 2127 2128 2129 2130
	return 0;
}

static void p54_remove_interface(struct ieee80211_hw *dev,
				 struct ieee80211_if_init_conf *conf)
{
	struct p54_common *priv = dev->priv;
2131 2132

	mutex_lock(&priv->conf_mutex);
C
Christian Lamparter 已提交
2133 2134
	if (priv->cached_beacon)
		p54_tx_cancel(dev, priv->cached_beacon);
2135
	priv->mode = NL80211_IFTYPE_MONITOR;
2136
	memset(priv->mac_addr, 0, ETH_ALEN);
C
Christian Lamparter 已提交
2137 2138
	memset(priv->bssid, 0, ETH_ALEN);
	p54_setup_mac(dev);
2139
	mutex_unlock(&priv->conf_mutex);
2140 2141
}

2142
static int p54_config(struct ieee80211_hw *dev, u32 changed)
2143
{
2144
	int ret = 0;
2145
	struct p54_common *priv = dev->priv;
2146
	struct ieee80211_conf *conf = &dev->conf;
2147

2148
	mutex_lock(&priv->conf_mutex);
C
Christian Lamparter 已提交
2149 2150 2151 2152 2153 2154 2155 2156
	if (changed & IEEE80211_CONF_CHANGE_POWER)
		priv->output_power = conf->power_level << 2;
	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
		ret = p54_setup_mac(dev);
		if (ret)
			goto out;
	}
	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2157
		ret = p54_scan(dev, P54_SCAN_EXIT, 0);
C
Christian Lamparter 已提交
2158 2159 2160
		if (ret)
			goto out;
	}
C
Christian Lamparter 已提交
2161 2162 2163 2164 2165
	if (changed & IEEE80211_CONF_CHANGE_PS) {
		ret = p54_set_ps(dev);
		if (ret)
			goto out;
	}
C
Christian Lamparter 已提交
2166 2167

out:
2168
	mutex_unlock(&priv->conf_mutex);
2169 2170 2171
	return ret;
}

2172 2173
static int p54_config_interface(struct ieee80211_hw *dev,
				struct ieee80211_vif *vif,
2174 2175 2176
				struct ieee80211_if_conf *conf)
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
2177
	int ret = 0;
2178

2179
	mutex_lock(&priv->conf_mutex);
C
Christian Lamparter 已提交
2180 2181 2182
	if (conf->changed & IEEE80211_IFCC_BSSID) {
		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
		ret = p54_setup_mac(dev);
C
Christian Lamparter 已提交
2183 2184
		if (ret)
			goto out;
C
Christian Lamparter 已提交
2185 2186 2187
	}

	if (conf->changed & IEEE80211_IFCC_BEACON) {
2188
		ret = p54_scan(dev, P54_SCAN_EXIT, 0);
C
Christian Lamparter 已提交
2189 2190
		if (ret)
			goto out;
C
Christian Lamparter 已提交
2191
		ret = p54_setup_mac(dev);
C
Christian Lamparter 已提交
2192 2193
		if (ret)
			goto out;
C
Christian Lamparter 已提交
2194 2195 2196 2197
		ret = p54_beacon_update(dev, vif);
		if (ret)
			goto out;
		ret = p54_set_edcf(dev);
C
Christian Lamparter 已提交
2198 2199 2200
		if (ret)
			goto out;
	}
C
Christian Lamparter 已提交
2201 2202 2203

	ret = p54_set_leds(dev, 1, !is_multicast_ether_addr(priv->bssid), 0);

C
Christian Lamparter 已提交
2204
out:
2205
	mutex_unlock(&priv->conf_mutex);
C
Christian Lamparter 已提交
2206
	return ret;
2207 2208
}

2209 2210 2211 2212 2213 2214 2215
static void p54_configure_filter(struct ieee80211_hw *dev,
				 unsigned int changed_flags,
				 unsigned int *total_flags,
				 int mc_count, struct dev_mc_list *mclist)
{
	struct p54_common *priv = dev->priv;

C
Christian Lamparter 已提交
2216
	*total_flags &= FIF_PROMISC_IN_BSS |
2217
			FIF_OTHER_BSS |
R
Roel Kluin 已提交
2218 2219
			(*total_flags & FIF_PROMISC_IN_BSS ?
				FIF_FCSFAIL : 0);
C
Christian Lamparter 已提交
2220 2221

	priv->filter_flags = *total_flags;
2222

2223
	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
C
Christian Lamparter 已提交
2224
		p54_setup_mac(dev);
2225 2226
}

J
Johannes Berg 已提交
2227
static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
2228 2229 2230
		       const struct ieee80211_tx_queue_params *params)
{
	struct p54_common *priv = dev->priv;
2231
	int ret;
2232

2233
	mutex_lock(&priv->conf_mutex);
2234
	if ((params) && !(queue > 4)) {
C
Christian Lamparter 已提交
2235
		P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
2236
			params->cw_min, params->cw_max, params->txop);
C
Christian Lamparter 已提交
2237
		ret = p54_set_edcf(dev);
2238
	} else
2239 2240 2241
		ret = -EINVAL;
	mutex_unlock(&priv->conf_mutex);
	return ret;
2242 2243
}

2244 2245 2246
static int p54_init_xbow_synth(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
C
Christian Lamparter 已提交
2247
	struct sk_buff *skb;
2248
	struct p54_xbow_synth *xbow;
2249

2250 2251
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow),
			    P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL);
C
Christian Lamparter 已提交
2252
	if (!skb)
2253 2254
		return -ENOMEM;

2255
	xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
2256 2257 2258
	xbow->magic1 = cpu_to_le16(0x1);
	xbow->magic2 = cpu_to_le16(0x2);
	xbow->freq = cpu_to_le16(5390);
C
Christian Lamparter 已提交
2259
	memset(xbow->padding, 0, sizeof(xbow->padding));
2260
	priv->tx(dev, skb);
2261 2262 2263
	return 0;
}

2264
static void p54_work(struct work_struct *work)
2265
{
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
	struct p54_common *priv = container_of(work, struct p54_common,
					       work.work);
	struct ieee80211_hw *dev = priv->hw;
	struct sk_buff *skb;

	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
		return ;

	/*
	 * TODO: walk through tx_queue and do the following tasks
	 * 	1. initiate bursts.
	 *      2. cancel stuck frames / reset the device if necessary.
	 */
2279

2280
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL,
2281 2282 2283 2284
			    sizeof(struct p54_statistics),
			    P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
	if (!skb)
		return ;
2285

2286
	priv->tx(dev, skb);
2287 2288
}

2289 2290 2291
static int p54_get_stats(struct ieee80211_hw *dev,
			 struct ieee80211_low_level_stats *stats)
{
2292 2293 2294
	struct p54_common *priv = dev->priv;

	memcpy(stats, &priv->stats, sizeof(*stats));
2295 2296 2297 2298 2299 2300 2301 2302
	return 0;
}

static int p54_get_tx_stats(struct ieee80211_hw *dev,
			    struct ieee80211_tx_queue_stats *stats)
{
	struct p54_common *priv = dev->priv;

2303 2304
	memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
	       sizeof(stats[0]) * dev->queues);
2305 2306 2307
	return 0;
}

2308 2309 2310 2311 2312 2313 2314 2315 2316
static void p54_bss_info_changed(struct ieee80211_hw *dev,
				 struct ieee80211_vif *vif,
				 struct ieee80211_bss_conf *info,
				 u32 changed)
{
	struct p54_common *priv = dev->priv;

	if (changed & BSS_CHANGED_ERP_SLOT) {
		priv->use_short_slot = info->use_short_slot;
C
Christian Lamparter 已提交
2317
		p54_set_edcf(dev);
2318
	}
2319 2320 2321 2322 2323
	if (changed & BSS_CHANGED_BASIC_RATES) {
		if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
			priv->basic_rate_mask = (info->basic_rates << 4);
		else
			priv->basic_rate_mask = info->basic_rates;
C
Christian Lamparter 已提交
2324
		p54_setup_mac(dev);
2325
		if (priv->fw_var >= 0x500)
2326
			p54_scan(dev, P54_SCAN_EXIT, 0);
2327 2328 2329 2330 2331 2332
	}
	if (changed & BSS_CHANGED_ASSOC) {
		if (info->assoc) {
			priv->aid = info->aid;
			priv->wakeup_timer = info->beacon_int *
					     info->dtim_period * 5;
C
Christian Lamparter 已提交
2333
			p54_setup_mac(dev);
2334 2335 2336
		}
	}

2337 2338
}

2339
static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
2340
		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374
		       struct ieee80211_key_conf *key)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
	struct p54_keycache *rxkey;
	u8 algo = 0;

	if (modparam_nohwcrypt)
		return -EOPNOTSUPP;

	if (cmd == DISABLE_KEY)
		algo = 0;
	else {
		switch (key->alg) {
		case ALG_TKIP:
			if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
			      BR_DESC_PRIV_CAP_TKIP)))
				return -EOPNOTSUPP;
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
			algo = P54_CRYPTO_TKIPMICHAEL;
			break;
		case ALG_WEP:
			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP))
				return -EOPNOTSUPP;
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
			algo = P54_CRYPTO_WEP;
			break;
		case ALG_CCMP:
			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP))
				return -EOPNOTSUPP;
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
			algo = P54_CRYPTO_AESCCMP;
			break;
		default:
2375
			return -EOPNOTSUPP;
2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390
		}
	}

	if (key->keyidx > priv->rx_keycache_size) {
		/*
		 * The device supports the choosen algorithm, but the firmware
		 * does not provide enough key slots to store all of them.
		 * So, incoming frames have to be decoded by the mac80211 stack,
		 * but we can still offload encryption for outgoing frames.
		 */

		return 0;
	}

	mutex_lock(&priv->conf_mutex);
2391 2392
	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey),
			    P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC);
2393 2394 2395 2396 2397 2398 2399 2400 2401 2402
	if (!skb) {
		mutex_unlock(&priv->conf_mutex);
		return -ENOMEM;
	}

	/* TODO: some devices have 4 more free slots for rx keys */
	rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
	rxkey->entry = key->keyidx;
	rxkey->key_id = key->keyidx;
	rxkey->key_type = algo;
2403 2404
	if (sta)
		memcpy(rxkey->mac, sta->addr, ETH_ALEN);
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
	else
		memset(rxkey->mac, ~0, ETH_ALEN);
	if (key->alg != ALG_TKIP) {
		rxkey->key_len = min((u8)16, key->keylen);
		memcpy(rxkey->key, key->key, rxkey->key_len);
	} else {
		rxkey->key_len = 24;
		memcpy(rxkey->key, key->key, 16);
		memcpy(&(rxkey->key[16]), &(key->key
			[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8);
	}

2417
	priv->tx(dev, skb);
2418 2419 2420 2421
	mutex_unlock(&priv->conf_mutex);
	return 0;
}

2422 2423
static const struct ieee80211_ops p54_ops = {
	.tx			= p54_tx,
2424 2425
	.start			= p54_start,
	.stop			= p54_stop,
2426 2427
	.add_interface		= p54_add_interface,
	.remove_interface	= p54_remove_interface,
C
Christian Lamparter 已提交
2428
	.set_tim		= p54_set_tim,
2429
	.sta_notify		= p54_sta_notify,
2430
	.set_key		= p54_set_key,
2431 2432
	.config			= p54_config,
	.config_interface	= p54_config_interface,
2433
	.bss_info_changed	= p54_bss_info_changed,
2434
	.configure_filter	= p54_configure_filter,
2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449
	.conf_tx		= p54_conf_tx,
	.get_stats		= p54_get_stats,
	.get_tx_stats		= p54_get_tx_stats
};

struct ieee80211_hw *p54_init_common(size_t priv_data_len)
{
	struct ieee80211_hw *dev;
	struct p54_common *priv;

	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
	if (!dev)
		return NULL;

	priv = dev->priv;
2450
	priv->hw = dev;
2451
	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
2452
	priv->basic_rate_mask = 0x15f;
2453
	skb_queue_head_init(&priv->tx_queue);
2454
	dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
2455 2456
		     IEEE80211_HW_SIGNAL_DBM |
		     IEEE80211_HW_NOISE_DBM;
2457

2458 2459 2460 2461
	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
				      BIT(NL80211_IFTYPE_ADHOC) |
				      BIT(NL80211_IFTYPE_AP) |
				      BIT(NL80211_IFTYPE_MESH_POINT);
2462

2463
	dev->channel_change_time = 1000;	/* TODO: find actual value */
2464 2465 2466 2467 2468
	priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
	priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
	priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
	priv->tx_stats[P54_QUEUE_CAB].limit = 3;
	priv->tx_stats[P54_QUEUE_DATA].limit = 5;
2469
	dev->queues = 1;
2470
	priv->noise = -94;
J
Johannes Berg 已提交
2471 2472 2473 2474 2475 2476 2477 2478 2479 2480
	/*
	 * We support at most 8 tries no matter which rate they're at,
	 * we cannot support max_rates * max_rate_tries as we set it
	 * here, but setting it correctly to 4/2 or so would limit us
	 * artificially if the RC algorithm wants just two rates, so
	 * let's say 4/7, we'll redistribute it at TX time, see the
	 * comments there.
	 */
	dev->max_rates = 4;
	dev->max_rate_tries = 7;
2481 2482
	dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
				 sizeof(struct p54_tx_data);
2483

2484
	mutex_init(&priv->conf_mutex);
2485
	init_completion(&priv->eeprom_comp);
2486
	INIT_DELAYED_WORK(&priv->work, p54_work);
2487 2488 2489 2490 2491

	return dev;
}
EXPORT_SYMBOL_GPL(p54_init_common);

2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
{
	int err;

	err = ieee80211_register_hw(dev);
	if (err) {
		dev_err(pdev, "Cannot register device (%d).\n", err);
		return err;
	}

	dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy));
	return 0;
}
EXPORT_SYMBOL_GPL(p54_register_common);

2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
void p54_free_common(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	kfree(priv->iq_autocal);
	kfree(priv->output_limit);
	kfree(priv->curve_data);
}
EXPORT_SYMBOL_GPL(p54_free_common);

static int __init p54_init(void)
{
	return 0;
}

static void __exit p54_exit(void)
{
}

module_init(p54_init);
module_exit(p54_exit);