p54common.c 62.5 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>
Johannes Berg's avatar
Johannes Berg committed
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
Chr's avatar
Chr committed
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, },
};

Johannes Berg's avatar
Johannes Berg committed
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:
Larry Finger's avatar
Larry Finger committed
159
160
			priv->fw_interface = be32_to_cpup((__be32 *)
					     bootrec->data);
161
			switch (priv->fw_interface) {
162
			case FW_LM86:
Christian Lamparter's avatar
Christian Lamparter committed
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;
Christian Lamparter's avatar
Christian Lamparter committed
171
172
				}
			case FW_FMAC:
173
			default:
Christian Lamparter's avatar
Christian Lamparter committed
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;
Larry Finger's avatar
Larry Finger committed
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++)
Al Viro's avatar
Al Viro committed
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)
Christian Lamparter's avatar
Christian Lamparter committed
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)
Christian Lamparter's avatar
Christian Lamparter committed
235
		printk(KERN_INFO "%s: you are using an obsolete firmware. "
236
		       "visit http://wireless.kernel.org/en/users/Drivers/p54 "
Christian Lamparter's avatar
Christian Lamparter committed
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
275
276
277
278
279
280
281
282
283
284
285
286
287
		 curve_data->channels;
	unsigned int i, j;
	void *source, *target;

	priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
	if (!priv->curve_data)
		return -ENOMEM;

	memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
	source = curve_data->data;
	target = priv->curve_data->data;
	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++) {
288
289
			dst = target;
			src = source;
290

291
292
293
			dst->rf_power = src->rf_power;
			dst->pa_detector = src->pa_detector;
			dst->data_64qam = src->pcv;
294
295
			/* "invent" the points for the other modulations */
#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
296
297
298
299
			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);
300
#undef SUB
301
302
			target += sizeof(*dst);
			source += sizeof(*src);
303
304
305
306
307
308
		}
	}

	return 0;
}

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
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;

	priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
	if (!priv->curve_data)
		return -ENOMEM;

	memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
	source = curve_data->data;
	target = priv->curve_data->data;
	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;
}

345
346
static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
                              "Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
347
static int p54_init_xbow_synth(struct ieee80211_hw *dev);
348

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
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);
	}
}

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
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.
		 */
	}
}

Larry Finger's avatar
Larry Finger committed
409
static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
410
411
412
413
414
415
416
{
	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;
417
	u8 *end = (u8 *)eeprom + len;
Christian Lamparter's avatar
Christian Lamparter committed
418
	u16 synth = 0;
419
420

	wrap = (struct eeprom_pda_wrap *) eeprom;
421
	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
422
423
424

	/* verify that at least the entry length/code fits */
	while ((u8 *)entry <= end - sizeof(*entry)) {
425
426
		entry_len = le16_to_cpu(entry->len);
		data_len = ((entry_len - 1) << 1);
427
428
429
430
431

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

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
		switch (le16_to_cpu(entry->code)) {
		case PDR_MAC_ADDRESS:
			SET_IEEE80211_PERM_ADDR(dev, entry->data);
			break;
		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
			if (data_len < 2) {
				err = -EINVAL;
				goto err;
			}

			if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
				err = -EINVAL;
				goto err;
			}

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

			if (!priv->output_limit) {
				err = -ENOMEM;
				goto err;
			}

			memcpy(priv->output_limit, &entry->data[2],
			       entry->data[1]*sizeof(*priv->output_limit));
			priv->output_limit_len = entry->data[1];
			break;
459
460
461
462
		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)) {
463
464
465
466
				err = -EINVAL;
				goto err;
			}

467
468
469
470
471
472
473
474
			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:
Christian Lamparter's avatar
Christian Lamparter committed
475
				printk(KERN_ERR "%s: unknown curve data "
476
						"revision %d\n",
Christian Lamparter's avatar
Christian Lamparter committed
477
						wiphy_name(dev->wiphy),
478
479
480
						curve_data->cal_method_rev);
				err = -ENODEV;
				break;
481
			}
482
483
			if (err)
				goto err;
Chr's avatar
Chr committed
484
485
			}
			break;
486
487
488
489
490
491
492
493
494
495
		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;
496
497
498
		case PDR_DEFAULT_COUNTRY:
			p54_parse_default_country(dev, entry->data, data_len);
			break;
499
500
501
502
		case PDR_INTERFACE_LIST:
			tmp = entry->data;
			while ((u8 *)tmp < entry->data + data_len) {
				struct bootrec_exp_if *exp_if = tmp;
503
504
				if (le16_to_cpu(exp_if->if_id) == 0xf)
					synth = le16_to_cpu(exp_if->variant);
505
506
507
508
509
510
				tmp += sizeof(struct bootrec_exp_if);
			}
			break;
		case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
			priv->version = *(u8 *)(entry->data + 1);
			break;
511
512
513
514
515
516
		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;
517
		case PDR_END:
518
519
			/* make it overrun */
			entry_len = len;
520
			break;
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
		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;
541
		default:
Christian Lamparter's avatar
Christian Lamparter committed
542
543
			printk(KERN_INFO "%s: unknown eeprom code : 0x%x\n",
				wiphy_name(dev->wiphy),
544
545
				le16_to_cpu(entry->code));
			break;
546
547
548
549
550
		}

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

Christian Lamparter's avatar
Christian Lamparter committed
551
552
	if (!synth || !priv->iq_autocal || !priv->output_limit ||
	    !priv->curve_data) {
Christian Lamparter's avatar
Christian Lamparter committed
553
554
		printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
			wiphy_name(dev->wiphy));
555
556
557
558
		err = -EINVAL;
		goto err;
	}

559
	priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
560
	if (priv->rxhw == 4)
561
		p54_init_xbow_synth(dev);
562
	if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
563
		dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
564
	if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
565
		dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
566
567
568
569
	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;
570
571
572
573
574
575
576
577
578
579

	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);
	}

Johannes Berg's avatar
Johannes Berg committed
580
	printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
581
		wiphy_name(dev->wiphy),
Johannes Berg's avatar
Johannes Berg committed
582
		dev->wiphy->perm_addr,
583
584
		priv->version, p54_rf_chips[priv->rxhw]);

585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
	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;
	}

Christian Lamparter's avatar
Christian Lamparter committed
603
604
	printk(KERN_ERR "%s: eeprom parse failed!\n",
		wiphy_name(dev->wiphy));
605
606
607
	return err;
}

608
609
static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
{
610
611
612
613
614
	struct p54_common *priv = dev->priv;
	int band = dev->conf.channel->band;

	return ((rssi * priv->rssical_db[band].mul) / 64 +
			 priv->rssical_db[band].add) / 4;
615
616
}

617
static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
618
{
619
	struct p54_common *priv = dev->priv;
620
	struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
621
622
	struct ieee80211_rx_status rx_status = {0};
	u16 freq = le16_to_cpu(hdr->freq);
623
	size_t header_len = sizeof(*hdr);
624
	u32 tsf32;
625
	u8 rate = hdr->rate & 0xf;
626

627
628
629
630
631
632
633
634
	/*
	 * 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;

635
	if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
Christian Lamparter's avatar
Christian Lamparter committed
636
637
638
639
640
641
		if (priv->filter_flags & FIF_FCSFAIL)
			rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
		else
			return 0;
	}

642
643
644
645
646
647
	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;

648
649
	rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
	rx_status.noise = priv->noise;
650
	/* XX correct? */
651
	rx_status.qual = (100 * hdr->rssi) / 127;
Christian Lamparter's avatar
Christian Lamparter committed
652
653
	if (hdr->rate & 0x10)
		rx_status.flag |= RX_FLAG_SHORTPRE;
654
655
656
657
658
	if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
		rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
	else
		rx_status.rate_idx = rate;

659
	rx_status.freq = freq;
660
	rx_status.band =  dev->conf.channel->band;
661
	rx_status.antenna = hdr->antenna;
662
663
664
665
666
667
668

	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;

669
	rx_status.flag |= RX_FLAG_TSFT;
670

671
	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
672
673
674
		header_len += hdr->align[0];

	skb_pull(skb, header_len);
675
676
677
	skb_trim(skb, le16_to_cpu(hdr->len));

	ieee80211_rx_irqsafe(dev, skb, &rx_status);
678

679
680
681
	queue_delayed_work(dev->workqueue, &priv->work,
			   msecs_to_jiffies(P54_STATISTICS_UPDATE));

682
	return -1;
683
684
685
686
687
688
689
}

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

690
691
692
	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
		return ;

693
	for (i = 0; i < dev->queues; i++)
694
695
		if (priv->tx_stats[i + P54_QUEUE_DATA].len <
		    priv->tx_stats[i + P54_QUEUE_DATA].limit)
696
697
698
			ieee80211_wake_queue(dev, i);
}

699
700
701
702
703
704
705
706
void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
	struct ieee80211_tx_info *info;
	struct memrecord *range;
	unsigned long flags;
	u32 freed = 0, last_addr = priv->rx_start;

Christian Lamparter's avatar
Christian Lamparter committed
707
	if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
708
709
		return;

710
711
712
713
714
715
	/*
	 * don't try to free an already unlinked skb
	 */
	if (unlikely((!skb->next) || (!skb->prev)))
		return;

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
	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;
		struct memrecord *mr;

		ni = IEEE80211_SKB_CB(skb->prev);
		mr = (struct memrecord *)ni->rate_driver_data;
		last_addr = mr->end_addr;
	}
	if (skb->next != (struct sk_buff *)&priv->tx_queue) {
		struct ieee80211_tx_info *ni;
		struct memrecord *mr;

		ni = IEEE80211_SKB_CB(skb->next);
		mr = (struct memrecord *)ni->rate_driver_data;
		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);
738
	dev_kfree_skb_any(skb);
739

740
	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
741
742
743
744
745
		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
		p54_wake_free_queues(dev);
}
EXPORT_SYMBOL_GPL(p54_free_skb);

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
					   __le32 req_id)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *entry = priv->tx_queue.next;
	unsigned long flags;

	spin_lock_irqsave(&priv->tx_queue.lock, flags);
	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;
}

767
768
769
static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
770
771
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
	struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
772
	struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
773
	u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
774
775
776
	struct memrecord *range = NULL;
	u32 freed = 0;
	u32 last_addr = priv->rx_start;
777
	unsigned long flags;
Johannes Berg's avatar
Johannes Berg committed
778
	int count, idx;
779

780
	spin_lock_irqsave(&priv->tx_queue.lock, flags);
781
	while (entry != (struct sk_buff *)&priv->tx_queue) {
782
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
783
784
		struct p54_hdr *entry_hdr;
		struct p54_tx_data *entry_data;
785
		unsigned int pad = 0, frame_len;
786

787
788
789
790
791
792
		range = (void *)info->rate_driver_data;
		if (range->start_addr != addr) {
			last_addr = range->end_addr;
			entry = entry->next;
			continue;
		}
793

794
795
796
		if (entry->next != (struct sk_buff *)&priv->tx_queue) {
			struct ieee80211_tx_info *ni;
			struct memrecord *mr;
797

798
799
800
801
802
803
804
805
806
807
			ni = IEEE80211_SKB_CB(entry->next);
			mr = (struct memrecord *)ni->rate_driver_data;
			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);

808
		frame_len = entry->len;
809
810
811
		entry_hdr = (struct p54_hdr *) entry->data;
		entry_data = (struct p54_tx_data *) entry_hdr->data;
		priv->tx_stats[entry_data->hw_queue].len--;
812
		priv->stats.dot11ACKFailureCount += payload->tries - 1;
813

814
815
816
817
818
819
820
821
822
		/*
		 * 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;

Christian Lamparter's avatar
Christian Lamparter committed
823
824
825
826
			kfree_skb(entry);
			goto out;
		}

827
828
829
830
831
832
833
834
835
836
		/*
		 * 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);

837
		if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
838
839
840
			pad = entry_data->align[0];

		/* walk through the rates array and adjust the counts */
841
		count = payload->tries;
842
843
844
845
846
847
848
849
850
		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;
851
			}
852
		}
Johannes Berg's avatar
Johannes Berg committed
853

854
855
856
		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
		     (!payload->status))
			info->flags |= IEEE80211_TX_STAT_ACK;
857
		if (payload->status & P54_TX_PSM_CANCELLED)
858
859
			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
		info->status.ack_signal = p54_rssi_to_dbm(dev,
860
				(int)payload->ack_rssi);
861

862
863
864
		/* Undo all changes to the frame. */
		switch (entry_data->key_type) {
		case P54_CRYPTO_TKIPMICHAEL: {
865
			u8 *iv = (u8 *)(entry_data->align + pad +
866
					entry_data->crypt_offset);
867
868
869
870
871

			/* Restore the original TKIP IV. */
			iv[2] = iv[0];
			iv[0] = iv[1];
			iv[1] = (iv[0] | 0x20) & 0x7f;	/* WEPSeed - 8.3.2.2 */
872
873
874
875
876
877
878
879
880
881

			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;
882
		}
883
		skb_trim(entry, frame_len);
884
885
886
		skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
		ieee80211_tx_status_irqsafe(dev, entry);
		goto out;
887
	}
888
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
889

890
out:
891
	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
892
		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
893
894
895
		p54_wake_free_queues(dev);
}

896
897
898
static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
				   struct sk_buff *skb)
{
899
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
900
901
902
903
904
905
	struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
	struct p54_common *priv = dev->priv;

	if (!priv->eeprom)
		return ;

906
907
908
909
910
911
912
	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));
	}
913
914
915
916

	complete(&priv->eeprom_comp);
}

917
918
919
static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
920
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
921
	struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
922
923
924
925
	u32 tsf32;

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

927
	tsf32 = le32_to_cpu(stats->tsf32);
928
929
930
931
932
933
934
935
936
937
	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));

938
	p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id));
939
940
}

Christian Lamparter's avatar
Christian Lamparter committed
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
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;
	}
}

970
static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
971
{
972
	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
973
974
975
976
977

	switch (le16_to_cpu(hdr->type)) {
	case P54_CONTROL_TYPE_TXDONE:
		p54_rx_frame_sent(dev, skb);
		break;
Christian Lamparter's avatar
Christian Lamparter committed
978
979
980
	case P54_CONTROL_TYPE_TRAP:
		p54_rx_trap(dev, skb);
		break;
981
982
	case P54_CONTROL_TYPE_BBP:
		break;
983
984
985
	case P54_CONTROL_TYPE_STAT_READBACK:
		p54_rx_stats(dev, skb);
		break;
986
987
988
	case P54_CONTROL_TYPE_EEPROM_READBACK:
		p54_rx_eeprom_readback(dev, skb);
		break;
989
990
991
992
993
	default:
		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
		       wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
		break;
	}
994
995

	return 0;
996
997
998
999
1000
}

/* returns zero if skb can be reused */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
{