Merge branch 'next/devel2' of git://git.linaro.org/people/arnd/arm-soc
[pandora-kernel.git] / drivers / net / wireless / p54 / eeprom.c
1 /*
2  * EEPROM parser code for mac80211 Prism54 drivers
3  *
4  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
5  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
6  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7  *
8  * Based on:
9  * - the islsm (softmac prism54) driver, which is:
10  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
11  * - stlc45xx driver
12  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18
19 #include <linux/init.h>
20 #include <linux/firmware.h>
21 #include <linux/etherdevice.h>
22 #include <linux/sort.h>
23 #include <linux/slab.h>
24
25 #include <net/mac80211.h>
26 #include <linux/crc-ccitt.h>
27
28 #include "p54.h"
29 #include "eeprom.h"
30 #include "lmac.h"
31
32 static struct ieee80211_rate p54_bgrates[] = {
33         { .bitrate = 10, .hw_value = 0, },
34         { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
35         { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
36         { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
37         { .bitrate = 60, .hw_value = 4, },
38         { .bitrate = 90, .hw_value = 5, },
39         { .bitrate = 120, .hw_value = 6, },
40         { .bitrate = 180, .hw_value = 7, },
41         { .bitrate = 240, .hw_value = 8, },
42         { .bitrate = 360, .hw_value = 9, },
43         { .bitrate = 480, .hw_value = 10, },
44         { .bitrate = 540, .hw_value = 11, },
45 };
46
47 static struct ieee80211_rate p54_arates[] = {
48         { .bitrate = 60, .hw_value = 4, },
49         { .bitrate = 90, .hw_value = 5, },
50         { .bitrate = 120, .hw_value = 6, },
51         { .bitrate = 180, .hw_value = 7, },
52         { .bitrate = 240, .hw_value = 8, },
53         { .bitrate = 360, .hw_value = 9, },
54         { .bitrate = 480, .hw_value = 10, },
55         { .bitrate = 540, .hw_value = 11, },
56 };
57
58 static struct p54_rssi_db_entry p54_rssi_default = {
59         /*
60          * The defaults are taken from usb-logs of the
61          * vendor driver. So, they should be safe to
62          * use in case we can't get a match from the
63          * rssi <-> dBm conversion database.
64          */
65         .mul = 130,
66         .add = -398,
67 };
68
69 #define CHAN_HAS_CAL            BIT(0)
70 #define CHAN_HAS_LIMIT          BIT(1)
71 #define CHAN_HAS_CURVE          BIT(2)
72 #define CHAN_HAS_ALL            (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE)
73
74 struct p54_channel_entry {
75         u16 freq;
76         u16 data;
77         int index;
78         enum ieee80211_band band;
79 };
80
81 struct p54_channel_list {
82         struct p54_channel_entry *channels;
83         size_t entries;
84         size_t max_entries;
85         size_t band_channel_num[IEEE80211_NUM_BANDS];
86 };
87
88 static int p54_get_band_from_freq(u16 freq)
89 {
90         /* FIXME: sync these values with the 802.11 spec */
91
92         if ((freq >= 2412) && (freq <= 2484))
93                 return IEEE80211_BAND_2GHZ;
94
95         if ((freq >= 4920) && (freq <= 5825))
96                 return IEEE80211_BAND_5GHZ;
97
98         return -1;
99 }
100
101 static int same_band(u16 freq, u16 freq2)
102 {
103         return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
104 }
105
106 static int p54_compare_channels(const void *_a,
107                                 const void *_b)
108 {
109         const struct p54_channel_entry *a = _a;
110         const struct p54_channel_entry *b = _b;
111
112         return a->freq - b->freq;
113 }
114
115 static int p54_compare_rssichan(const void *_a,
116                                 const void *_b)
117 {
118         const struct p54_rssi_db_entry *a = _a;
119         const struct p54_rssi_db_entry *b = _b;
120
121         return a->freq - b->freq;
122 }
123
124 static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
125                                   struct ieee80211_supported_band *band_entry,
126                                   enum ieee80211_band band)
127 {
128         /* TODO: generate rate array dynamically */
129
130         switch (band) {
131         case IEEE80211_BAND_2GHZ:
132                 band_entry->bitrates = p54_bgrates;
133                 band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates);
134                 break;
135         case IEEE80211_BAND_5GHZ:
136                 band_entry->bitrates = p54_arates;
137                 band_entry->n_bitrates = ARRAY_SIZE(p54_arates);
138                 break;
139         default:
140                 return -EINVAL;
141         }
142
143         return 0;
144 }
145
146 static int p54_generate_band(struct ieee80211_hw *dev,
147                              struct p54_channel_list *list,
148                              unsigned int *chan_num,
149                              enum ieee80211_band band)
150 {
151         struct p54_common *priv = dev->priv;
152         struct ieee80211_supported_band *tmp, *old;
153         unsigned int i, j;
154         int ret = -ENOMEM;
155
156         if ((!list->entries) || (!list->band_channel_num[band]))
157                 return -EINVAL;
158
159         tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
160         if (!tmp)
161                 goto err_out;
162
163         tmp->channels = kzalloc(sizeof(struct ieee80211_channel) *
164                                 list->band_channel_num[band], GFP_KERNEL);
165         if (!tmp->channels)
166                 goto err_out;
167
168         ret = p54_fill_band_bitrates(dev, tmp, band);
169         if (ret)
170                 goto err_out;
171
172         for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
173                            (i < list->entries); i++) {
174                 struct p54_channel_entry *chan = &list->channels[i];
175
176                 if (chan->band != band)
177                         continue;
178
179                 if (chan->data != CHAN_HAS_ALL) {
180                         wiphy_err(dev->wiphy, "%s%s%s is/are missing for "
181                                   "channel:%d [%d MHz].\n",
182                                   (chan->data & CHAN_HAS_CAL ? "" :
183                                    " [iqauto calibration data]"),
184                                   (chan->data & CHAN_HAS_LIMIT ? "" :
185                                    " [output power limits]"),
186                                   (chan->data & CHAN_HAS_CURVE ? "" :
187                                    " [curve data]"),
188                                   chan->index, chan->freq);
189                         continue;
190                 }
191
192                 tmp->channels[j].band = chan->band;
193                 tmp->channels[j].center_freq = chan->freq;
194                 priv->survey[*chan_num].channel = &tmp->channels[j];
195                 priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
196                         SURVEY_INFO_CHANNEL_TIME |
197                         SURVEY_INFO_CHANNEL_TIME_BUSY |
198                         SURVEY_INFO_CHANNEL_TIME_TX;
199                 tmp->channels[j].hw_value = (*chan_num);
200                 j++;
201                 (*chan_num)++;
202         }
203
204         if (j == 0) {
205                 wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n",
206                           (band == IEEE80211_BAND_2GHZ) ? 2 : 5);
207
208                 ret = -ENODATA;
209                 goto err_out;
210         }
211
212         tmp->n_channels = j;
213         old = priv->band_table[band];
214         priv->band_table[band] = tmp;
215         if (old) {
216                 kfree(old->channels);
217                 kfree(old);
218         }
219
220         return 0;
221
222 err_out:
223         if (tmp) {
224                 kfree(tmp->channels);
225                 kfree(tmp);
226         }
227
228         return ret;
229 }
230
231 static void p54_update_channel_param(struct p54_channel_list *list,
232                                      u16 freq, u16 data)
233 {
234         int band, i;
235
236         /*
237          * usually all lists in the eeprom are mostly sorted.
238          * so it's very likely that the entry we are looking for
239          * is right at the end of the list
240          */
241         for (i = list->entries; i >= 0; i--) {
242                 if (freq == list->channels[i].freq) {
243                         list->channels[i].data |= data;
244                         break;
245                 }
246         }
247
248         if ((i < 0) && (list->entries < list->max_entries)) {
249                 /* entry does not exist yet. Initialize a new one. */
250                 band = p54_get_band_from_freq(freq);
251
252                 /*
253                  * filter out frequencies which don't belong into
254                  * any supported band.
255                  */
256                 if (band < 0)
257                         return ;
258
259                 i = list->entries++;
260                 list->band_channel_num[band]++;
261
262                 list->channels[i].freq = freq;
263                 list->channels[i].data = data;
264                 list->channels[i].band = band;
265                 list->channels[i].index = ieee80211_frequency_to_channel(freq);
266                 /* TODO: parse output_limit and fill max_power */
267         }
268 }
269
270 static int p54_generate_channel_lists(struct ieee80211_hw *dev)
271 {
272         struct p54_common *priv = dev->priv;
273         struct p54_channel_list *list;
274         unsigned int i, j, k, max_channel_num;
275         int ret = 0;
276         u16 freq;
277
278         if ((priv->iq_autocal_len != priv->curve_data->entries) ||
279             (priv->iq_autocal_len != priv->output_limit->entries))
280                 wiphy_err(dev->wiphy,
281                           "Unsupported or damaged EEPROM detected. "
282                           "You may not be able to use all channels.\n");
283
284         max_channel_num = max_t(unsigned int, priv->output_limit->entries,
285                                 priv->iq_autocal_len);
286         max_channel_num = max_t(unsigned int, max_channel_num,
287                                 priv->curve_data->entries);
288
289         list = kzalloc(sizeof(*list), GFP_KERNEL);
290         if (!list) {
291                 ret = -ENOMEM;
292                 goto free;
293         }
294         priv->chan_num = max_channel_num;
295         priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num,
296                                GFP_KERNEL);
297         if (!priv->survey) {
298                 ret = -ENOMEM;
299                 goto free;
300         }
301
302         list->max_entries = max_channel_num;
303         list->channels = kzalloc(sizeof(struct p54_channel_entry) *
304                                  max_channel_num, GFP_KERNEL);
305         if (!list->channels) {
306                 ret = -ENOMEM;
307                 goto free;
308         }
309
310         for (i = 0; i < max_channel_num; i++) {
311                 if (i < priv->iq_autocal_len) {
312                         freq = le16_to_cpu(priv->iq_autocal[i].freq);
313                         p54_update_channel_param(list, freq, CHAN_HAS_CAL);
314                 }
315
316                 if (i < priv->output_limit->entries) {
317                         freq = le16_to_cpup((__le16 *) (i *
318                                             priv->output_limit->entry_size +
319                                             priv->output_limit->offset +
320                                             priv->output_limit->data));
321
322                         p54_update_channel_param(list, freq, CHAN_HAS_LIMIT);
323                 }
324
325                 if (i < priv->curve_data->entries) {
326                         freq = le16_to_cpup((__le16 *) (i *
327                                             priv->curve_data->entry_size +
328                                             priv->curve_data->offset +
329                                             priv->curve_data->data));
330
331                         p54_update_channel_param(list, freq, CHAN_HAS_CURVE);
332                 }
333         }
334
335         /* sort the channel list by frequency */
336         sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
337              p54_compare_channels, NULL);
338
339         k = 0;
340         for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
341                 if (p54_generate_band(dev, list, &k, i) == 0)
342                         j++;
343         }
344         if (j == 0) {
345                 /* no useable band available. */
346                 ret = -EINVAL;
347         }
348
349 free:
350         if (list) {
351                 kfree(list->channels);
352                 kfree(list);
353         }
354         if (ret) {
355                 kfree(priv->survey);
356                 priv->survey = NULL;
357         }
358
359         return ret;
360 }
361
362 static int p54_convert_rev0(struct ieee80211_hw *dev,
363                             struct pda_pa_curve_data *curve_data)
364 {
365         struct p54_common *priv = dev->priv;
366         struct p54_pa_curve_data_sample *dst;
367         struct pda_pa_curve_data_sample_rev0 *src;
368         size_t cd_len = sizeof(*curve_data) +
369                 (curve_data->points_per_channel*sizeof(*dst) + 2) *
370                  curve_data->channels;
371         unsigned int i, j;
372         void *source, *target;
373
374         priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
375                                    GFP_KERNEL);
376         if (!priv->curve_data)
377                 return -ENOMEM;
378
379         priv->curve_data->entries = curve_data->channels;
380         priv->curve_data->entry_size = sizeof(__le16) +
381                 sizeof(*dst) * curve_data->points_per_channel;
382         priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
383         priv->curve_data->len = cd_len;
384         memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
385         source = curve_data->data;
386         target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
387         for (i = 0; i < curve_data->channels; i++) {
388                 __le16 *freq = source;
389                 source += sizeof(__le16);
390                 *((__le16 *)target) = *freq;
391                 target += sizeof(__le16);
392                 for (j = 0; j < curve_data->points_per_channel; j++) {
393                         dst = target;
394                         src = source;
395
396                         dst->rf_power = src->rf_power;
397                         dst->pa_detector = src->pa_detector;
398                         dst->data_64qam = src->pcv;
399                         /* "invent" the points for the other modulations */
400 #define SUB(x, y) (u8)(((x) - (y)) > (x) ? 0 : (x) - (y))
401                         dst->data_16qam = SUB(src->pcv, 12);
402                         dst->data_qpsk = SUB(dst->data_16qam, 12);
403                         dst->data_bpsk = SUB(dst->data_qpsk, 12);
404                         dst->data_barker = SUB(dst->data_bpsk, 14);
405 #undef SUB
406                         target += sizeof(*dst);
407                         source += sizeof(*src);
408                 }
409         }
410
411         return 0;
412 }
413
414 static int p54_convert_rev1(struct ieee80211_hw *dev,
415                             struct pda_pa_curve_data *curve_data)
416 {
417         struct p54_common *priv = dev->priv;
418         struct p54_pa_curve_data_sample *dst;
419         struct pda_pa_curve_data_sample_rev1 *src;
420         size_t cd_len = sizeof(*curve_data) +
421                 (curve_data->points_per_channel*sizeof(*dst) + 2) *
422                  curve_data->channels;
423         unsigned int i, j;
424         void *source, *target;
425
426         priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
427                                    GFP_KERNEL);
428         if (!priv->curve_data)
429                 return -ENOMEM;
430
431         priv->curve_data->entries = curve_data->channels;
432         priv->curve_data->entry_size = sizeof(__le16) +
433                 sizeof(*dst) * curve_data->points_per_channel;
434         priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
435         priv->curve_data->len = cd_len;
436         memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
437         source = curve_data->data;
438         target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
439         for (i = 0; i < curve_data->channels; i++) {
440                 __le16 *freq = source;
441                 source += sizeof(__le16);
442                 *((__le16 *)target) = *freq;
443                 target += sizeof(__le16);
444                 for (j = 0; j < curve_data->points_per_channel; j++) {
445                         memcpy(target, source, sizeof(*src));
446
447                         target += sizeof(*dst);
448                         source += sizeof(*src);
449                 }
450                 source++;
451         }
452
453         return 0;
454 }
455
456 static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
457         "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
458
459 static int p54_parse_rssical(struct ieee80211_hw *dev,
460                              u8 *data, int len, u16 type)
461 {
462         struct p54_common *priv = dev->priv;
463         struct p54_rssi_db_entry *entry;
464         size_t db_len, entries;
465         int offset = 0, i;
466
467         if (type != PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
468                 entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
469                 if (len != sizeof(struct pda_rssi_cal_entry) * entries) {
470                         wiphy_err(dev->wiphy, "rssical size mismatch.\n");
471                         goto err_data;
472                 }
473         } else {
474                 /*
475                  * Some devices (Dell 1450 USB, Xbow 5GHz card, etc...)
476                  * have an empty two byte header.
477                  */
478                 if (*((__le16 *)&data[offset]) == cpu_to_le16(0))
479                         offset += 2;
480
481                 entries = (len - offset) /
482                         sizeof(struct pda_rssi_cal_ext_entry);
483
484                 if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
485                     entries <= 0) {
486                         wiphy_err(dev->wiphy, "invalid rssi database.\n");
487                         goto err_data;
488                 }
489         }
490
491         db_len = sizeof(*entry) * entries;
492         priv->rssi_db = kzalloc(db_len + sizeof(*priv->rssi_db), GFP_KERNEL);
493         if (!priv->rssi_db)
494                 return -ENOMEM;
495
496         priv->rssi_db->offset = 0;
497         priv->rssi_db->entries = entries;
498         priv->rssi_db->entry_size = sizeof(*entry);
499         priv->rssi_db->len = db_len;
500
501         entry = (void *)((unsigned long)priv->rssi_db->data + priv->rssi_db->offset);
502         if (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
503                 struct pda_rssi_cal_ext_entry *cal = (void *) &data[offset];
504
505                 for (i = 0; i < entries; i++) {
506                         entry[i].freq = le16_to_cpu(cal[i].freq);
507                         entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
508                         entry[i].add = (s16) le16_to_cpu(cal[i].add);
509                 }
510         } else {
511                 struct pda_rssi_cal_entry *cal = (void *) &data[offset];
512
513                 for (i = 0; i < entries; i++) {
514                         u16 freq = 0;
515                         switch (i) {
516                         case IEEE80211_BAND_2GHZ:
517                                 freq = 2437;
518                                 break;
519                         case IEEE80211_BAND_5GHZ:
520                                 freq = 5240;
521                                 break;
522                         }
523
524                         entry[i].freq = freq;
525                         entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
526                         entry[i].add = (s16) le16_to_cpu(cal[i].add);
527                 }
528         }
529
530         /* sort the list by channel frequency */
531         sort(entry, entries, sizeof(*entry), p54_compare_rssichan, NULL);
532         return 0;
533
534 err_data:
535         wiphy_err(dev->wiphy,
536                   "rssi calibration data packing type:(%x) len:%d.\n",
537                   type, len);
538
539         print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len);
540
541         wiphy_err(dev->wiphy, "please report this issue.\n");
542         return -EINVAL;
543 }
544
545 struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
546 {
547         struct p54_rssi_db_entry *entry;
548         int i, found = -1;
549
550         if (!priv->rssi_db)
551                 return &p54_rssi_default;
552
553         entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
554         for (i = 0; i < priv->rssi_db->entries; i++) {
555                 if (!same_band(freq, entry[i].freq))
556                         continue;
557
558                 if (found == -1) {
559                         found = i;
560                         continue;
561                 }
562
563                 /* nearest match */
564                 if (abs(freq - entry[i].freq) <
565                     abs(freq - entry[found].freq)) {
566                         found = i;
567                         continue;
568                 } else {
569                         break;
570                 }
571         }
572
573         return found < 0 ? &p54_rssi_default : &entry[found];
574 }
575
576 static void p54_parse_default_country(struct ieee80211_hw *dev,
577                                       void *data, int len)
578 {
579         struct pda_country *country;
580
581         if (len != sizeof(*country)) {
582                 wiphy_err(dev->wiphy,
583                           "found possible invalid default country eeprom entry. (entry size: %d)\n",
584                           len);
585
586                 print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
587                                      data, len);
588
589                 wiphy_err(dev->wiphy, "please report this issue.\n");
590                 return;
591         }
592
593         country = (struct pda_country *) data;
594         if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
595                 regulatory_hint(dev->wiphy, country->alpha2);
596         else {
597                 /* TODO:
598                  * write a shared/common function that converts
599                  * "Regulatory domain codes" (802.11-2007 14.8.2.2)
600                  * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
601                  */
602         }
603 }
604
605 static int p54_convert_output_limits(struct ieee80211_hw *dev,
606                                      u8 *data, size_t len)
607 {
608         struct p54_common *priv = dev->priv;
609
610         if (len < 2)
611                 return -EINVAL;
612
613         if (data[0] != 0) {
614                 wiphy_err(dev->wiphy, "unknown output power db revision:%x\n",
615                           data[0]);
616                 return -EINVAL;
617         }
618
619         if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
620                 return -EINVAL;
621
622         priv->output_limit = kmalloc(data[1] *
623                 sizeof(struct pda_channel_output_limit) +
624                 sizeof(*priv->output_limit), GFP_KERNEL);
625
626         if (!priv->output_limit)
627                 return -ENOMEM;
628
629         priv->output_limit->offset = 0;
630         priv->output_limit->entries = data[1];
631         priv->output_limit->entry_size =
632                 sizeof(struct pda_channel_output_limit);
633         priv->output_limit->len = priv->output_limit->entry_size *
634                                   priv->output_limit->entries +
635                                   priv->output_limit->offset;
636
637         memcpy(priv->output_limit->data, &data[2],
638                data[1] * sizeof(struct pda_channel_output_limit));
639
640         return 0;
641 }
642
643 static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
644                                                size_t total_len)
645 {
646         struct p54_cal_database *dst;
647         size_t payload_len, entries, entry_size, offset;
648
649         payload_len = le16_to_cpu(src->len);
650         entries = le16_to_cpu(src->entries);
651         entry_size = le16_to_cpu(src->entry_size);
652         offset = le16_to_cpu(src->offset);
653         if (((entries * entry_size + offset) != payload_len) ||
654              (payload_len + sizeof(*src) != total_len))
655                 return NULL;
656
657         dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
658         if (!dst)
659                 return NULL;
660
661         dst->entries = entries;
662         dst->entry_size = entry_size;
663         dst->offset = offset;
664         dst->len = payload_len;
665
666         memcpy(dst->data, src->data, payload_len);
667         return dst;
668 }
669
670 int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
671 {
672         struct p54_common *priv = dev->priv;
673         struct eeprom_pda_wrap *wrap;
674         struct pda_entry *entry;
675         unsigned int data_len, entry_len;
676         void *tmp;
677         int err;
678         u8 *end = (u8 *)eeprom + len;
679         u16 synth = 0;
680         u16 crc16 = ~0;
681
682         wrap = (struct eeprom_pda_wrap *) eeprom;
683         entry = (void *)wrap->data + le16_to_cpu(wrap->len);
684
685         /* verify that at least the entry length/code fits */
686         while ((u8 *)entry <= end - sizeof(*entry)) {
687                 entry_len = le16_to_cpu(entry->len);
688                 data_len = ((entry_len - 1) << 1);
689
690                 /* abort if entry exceeds whole structure */
691                 if ((u8 *)entry + sizeof(*entry) + data_len > end)
692                         break;
693
694                 switch (le16_to_cpu(entry->code)) {
695                 case PDR_MAC_ADDRESS:
696                         if (data_len != ETH_ALEN)
697                                 break;
698                         SET_IEEE80211_PERM_ADDR(dev, entry->data);
699                         break;
700                 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
701                         if (priv->output_limit)
702                                 break;
703                         err = p54_convert_output_limits(dev, entry->data,
704                                                         data_len);
705                         if (err)
706                                 goto err;
707                         break;
708                 case PDR_PRISM_PA_CAL_CURVE_DATA: {
709                         struct pda_pa_curve_data *curve_data =
710                                 (struct pda_pa_curve_data *)entry->data;
711                         if (data_len < sizeof(*curve_data)) {
712                                 err = -EINVAL;
713                                 goto err;
714                         }
715
716                         switch (curve_data->cal_method_rev) {
717                         case 0:
718                                 err = p54_convert_rev0(dev, curve_data);
719                                 break;
720                         case 1:
721                                 err = p54_convert_rev1(dev, curve_data);
722                                 break;
723                         default:
724                                 wiphy_err(dev->wiphy,
725                                           "unknown curve data revision %d\n",
726                                           curve_data->cal_method_rev);
727                                 err = -ENODEV;
728                                 break;
729                         }
730                         if (err)
731                                 goto err;
732                         }
733                         break;
734                 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
735                         priv->iq_autocal = kmemdup(entry->data, data_len,
736                                                    GFP_KERNEL);
737                         if (!priv->iq_autocal) {
738                                 err = -ENOMEM;
739                                 goto err;
740                         }
741
742                         priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
743                         break;
744                 case PDR_DEFAULT_COUNTRY:
745                         p54_parse_default_country(dev, entry->data, data_len);
746                         break;
747                 case PDR_INTERFACE_LIST:
748                         tmp = entry->data;
749                         while ((u8 *)tmp < entry->data + data_len) {
750                                 struct exp_if *exp_if = tmp;
751                                 if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000))
752                                         synth = le16_to_cpu(exp_if->variant);
753                                 tmp += sizeof(*exp_if);
754                         }
755                         break;
756                 case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
757                         if (data_len < 2)
758                                 break;
759                         priv->version = *(u8 *)(entry->data + 1);
760                         break;
761                 case PDR_RSSI_LINEAR_APPROXIMATION:
762                 case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
763                 case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
764                         err = p54_parse_rssical(dev, entry->data, data_len,
765                                                 le16_to_cpu(entry->code));
766                         if (err)
767                                 goto err;
768                         break;
769                 case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: {
770                         struct pda_custom_wrapper *pda = (void *) entry->data;
771                         __le16 *src;
772                         u16 *dst;
773                         int i;
774
775                         if (priv->rssi_db || data_len < sizeof(*pda))
776                                 break;
777
778                         priv->rssi_db = p54_convert_db(pda, data_len);
779                         if (!priv->rssi_db)
780                                 break;
781
782                         src = (void *) priv->rssi_db->data;
783                         dst = (void *) priv->rssi_db->data;
784
785                         for (i = 0; i < priv->rssi_db->entries; i++)
786                                 *(dst++) = (s16) le16_to_cpu(*(src++));
787
788                         }
789                         break;
790                 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
791                         struct pda_custom_wrapper *pda = (void *) entry->data;
792                         if (priv->output_limit || data_len < sizeof(*pda))
793                                 break;
794                         priv->output_limit = p54_convert_db(pda, data_len);
795                         }
796                         break;
797                 case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
798                         struct pda_custom_wrapper *pda = (void *) entry->data;
799                         if (priv->curve_data || data_len < sizeof(*pda))
800                                 break;
801                         priv->curve_data = p54_convert_db(pda, data_len);
802                         }
803                         break;
804                 case PDR_END:
805                         crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry));
806                         if (crc16 != le16_to_cpup((__le16 *)entry->data)) {
807                                 wiphy_err(dev->wiphy, "eeprom failed checksum "
808                                          "test!\n");
809                                 err = -ENOMSG;
810                                 goto err;
811                         } else {
812                                 goto good_eeprom;
813                         }
814                         break;
815                 default:
816                         break;
817                 }
818
819                 crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2);
820                 entry = (void *)entry + (entry_len + 1) * 2;
821         }
822
823         wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n");
824         err = -ENODATA;
825         goto err;
826
827 good_eeprom:
828         if (!synth || !priv->iq_autocal || !priv->output_limit ||
829             !priv->curve_data) {
830                 wiphy_err(dev->wiphy,
831                           "not all required entries found in eeprom!\n");
832                 err = -EINVAL;
833                 goto err;
834         }
835
836         err = p54_generate_channel_lists(dev);
837         if (err)
838                 goto err;
839
840         priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
841         if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
842                 p54_init_xbow_synth(priv);
843         if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
844                 dev->wiphy->bands[IEEE80211_BAND_2GHZ] =
845                         priv->band_table[IEEE80211_BAND_2GHZ];
846         if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
847                 dev->wiphy->bands[IEEE80211_BAND_5GHZ] =
848                         priv->band_table[IEEE80211_BAND_5GHZ];
849         if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
850                 priv->rx_diversity_mask = 3;
851         if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
852                 priv->tx_diversity_mask = 3;
853
854         if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
855                 u8 perm_addr[ETH_ALEN];
856
857                 wiphy_warn(dev->wiphy,
858                            "Invalid hwaddr! Using randomly generated MAC addr\n");
859                 random_ether_addr(perm_addr);
860                 SET_IEEE80211_PERM_ADDR(dev, perm_addr);
861         }
862
863         priv->cur_rssi = &p54_rssi_default;
864
865         wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
866                    dev->wiphy->perm_addr, priv->version,
867                    p54_rf_chips[priv->rxhw]);
868
869         return 0;
870
871 err:
872         kfree(priv->iq_autocal);
873         kfree(priv->output_limit);
874         kfree(priv->curve_data);
875         kfree(priv->rssi_db);
876         kfree(priv->survey);
877         priv->iq_autocal = NULL;
878         priv->output_limit = NULL;
879         priv->curve_data = NULL;
880         priv->rssi_db = NULL;
881         priv->survey = NULL;
882
883         wiphy_err(dev->wiphy, "eeprom parse failed!\n");
884         return err;
885 }
886 EXPORT_SYMBOL_GPL(p54_parse_eeprom);
887
888 int p54_read_eeprom(struct ieee80211_hw *dev)
889 {
890         struct p54_common *priv = dev->priv;
891         size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
892         int ret = -ENOMEM;
893         void *eeprom;
894
895         maxblocksize = EEPROM_READBACK_LEN;
896         if (priv->fw_var >= 0x509)
897                 maxblocksize -= 0xc;
898         else
899                 maxblocksize -= 0x4;
900
901         eeprom = kzalloc(eeprom_size, GFP_KERNEL);
902         if (unlikely(!eeprom))
903                 goto free;
904
905         while (eeprom_size) {
906                 blocksize = min(eeprom_size, maxblocksize);
907                 ret = p54_download_eeprom(priv, (void *) (eeprom + offset),
908                                           offset, blocksize);
909                 if (unlikely(ret))
910                         goto free;
911
912                 offset += blocksize;
913                 eeprom_size -= blocksize;
914         }
915
916         ret = p54_parse_eeprom(dev, eeprom, offset);
917 free:
918         kfree(eeprom);
919         return ret;
920 }
921 EXPORT_SYMBOL_GPL(p54_read_eeprom);