Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * EEPROM parser code for mac80211 Prism54 drivers
0004  *
0005  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
0006  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
0007  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
0008  *
0009  * Based on:
0010  * - the islsm (softmac prism54) driver, which is:
0011  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
0012  * - stlc45xx driver
0013  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
0014  */
0015 
0016 #include <linux/firmware.h>
0017 #include <linux/etherdevice.h>
0018 #include <linux/sort.h>
0019 #include <linux/slab.h>
0020 
0021 #include <net/mac80211.h>
0022 #include <linux/crc-ccitt.h>
0023 #include <linux/export.h>
0024 
0025 #include "p54.h"
0026 #include "eeprom.h"
0027 #include "lmac.h"
0028 
0029 static struct ieee80211_rate p54_bgrates[] = {
0030     { .bitrate = 10, .hw_value = 0, },
0031     { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0032     { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0033     { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0034     { .bitrate = 60, .hw_value = 4, },
0035     { .bitrate = 90, .hw_value = 5, },
0036     { .bitrate = 120, .hw_value = 6, },
0037     { .bitrate = 180, .hw_value = 7, },
0038     { .bitrate = 240, .hw_value = 8, },
0039     { .bitrate = 360, .hw_value = 9, },
0040     { .bitrate = 480, .hw_value = 10, },
0041     { .bitrate = 540, .hw_value = 11, },
0042 };
0043 
0044 static struct ieee80211_rate p54_arates[] = {
0045     { .bitrate = 60, .hw_value = 4, },
0046     { .bitrate = 90, .hw_value = 5, },
0047     { .bitrate = 120, .hw_value = 6, },
0048     { .bitrate = 180, .hw_value = 7, },
0049     { .bitrate = 240, .hw_value = 8, },
0050     { .bitrate = 360, .hw_value = 9, },
0051     { .bitrate = 480, .hw_value = 10, },
0052     { .bitrate = 540, .hw_value = 11, },
0053 };
0054 
0055 static struct p54_rssi_db_entry p54_rssi_default = {
0056     /*
0057      * The defaults are taken from usb-logs of the
0058      * vendor driver. So, they should be safe to
0059      * use in case we can't get a match from the
0060      * rssi <-> dBm conversion database.
0061      */
0062     .mul = 130,
0063     .add = -398,
0064 };
0065 
0066 #define CHAN_HAS_CAL        BIT(0)
0067 #define CHAN_HAS_LIMIT      BIT(1)
0068 #define CHAN_HAS_CURVE      BIT(2)
0069 #define CHAN_HAS_ALL        (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE)
0070 
0071 struct p54_channel_entry {
0072     u16 freq;
0073     u16 data;
0074     int index;
0075     int max_power;
0076     enum nl80211_band band;
0077 };
0078 
0079 struct p54_channel_list {
0080     struct p54_channel_entry *channels;
0081     size_t entries;
0082     size_t max_entries;
0083     size_t band_channel_num[NUM_NL80211_BANDS];
0084 };
0085 
0086 static int p54_get_band_from_freq(u16 freq)
0087 {
0088     /* FIXME: sync these values with the 802.11 spec */
0089 
0090     if ((freq >= 2412) && (freq <= 2484))
0091         return NL80211_BAND_2GHZ;
0092 
0093     if ((freq >= 4920) && (freq <= 5825))
0094         return NL80211_BAND_5GHZ;
0095 
0096     return -1;
0097 }
0098 
0099 static int same_band(u16 freq, u16 freq2)
0100 {
0101     return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
0102 }
0103 
0104 static int p54_compare_channels(const void *_a,
0105                 const void *_b)
0106 {
0107     const struct p54_channel_entry *a = _a;
0108     const struct p54_channel_entry *b = _b;
0109 
0110     return a->freq - b->freq;
0111 }
0112 
0113 static int p54_compare_rssichan(const void *_a,
0114                 const void *_b)
0115 {
0116     const struct p54_rssi_db_entry *a = _a;
0117     const struct p54_rssi_db_entry *b = _b;
0118 
0119     return a->freq - b->freq;
0120 }
0121 
0122 static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
0123                   struct ieee80211_supported_band *band_entry,
0124                   enum nl80211_band band)
0125 {
0126     /* TODO: generate rate array dynamically */
0127 
0128     switch (band) {
0129     case NL80211_BAND_2GHZ:
0130         band_entry->bitrates = p54_bgrates;
0131         band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates);
0132         break;
0133     case NL80211_BAND_5GHZ:
0134         band_entry->bitrates = p54_arates;
0135         band_entry->n_bitrates = ARRAY_SIZE(p54_arates);
0136         break;
0137     default:
0138         return -EINVAL;
0139     }
0140 
0141     return 0;
0142 }
0143 
0144 static int p54_generate_band(struct ieee80211_hw *dev,
0145                  struct p54_channel_list *list,
0146                  unsigned int *chan_num,
0147                  enum nl80211_band band)
0148 {
0149     struct p54_common *priv = dev->priv;
0150     struct ieee80211_supported_band *tmp, *old;
0151     unsigned int i, j;
0152     int ret = -ENOMEM;
0153 
0154     if ((!list->entries) || (!list->band_channel_num[band]))
0155         return -EINVAL;
0156 
0157     tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
0158     if (!tmp)
0159         goto err_out;
0160 
0161     tmp->channels = kcalloc(list->band_channel_num[band],
0162                 sizeof(struct ieee80211_channel),
0163                 GFP_KERNEL);
0164     if (!tmp->channels)
0165         goto err_out;
0166 
0167     ret = p54_fill_band_bitrates(dev, tmp, band);
0168     if (ret)
0169         goto err_out;
0170 
0171     for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
0172                (i < list->entries); i++) {
0173         struct p54_channel_entry *chan = &list->channels[i];
0174         struct ieee80211_channel *dest = &tmp->channels[j];
0175 
0176         if (chan->band != band)
0177             continue;
0178 
0179         if (chan->data != CHAN_HAS_ALL) {
0180             wiphy_err(dev->wiphy, "%s%s%s is/are missing for "
0181                   "channel:%d [%d MHz].\n",
0182                   (chan->data & CHAN_HAS_CAL ? "" :
0183                    " [iqauto calibration data]"),
0184                   (chan->data & CHAN_HAS_LIMIT ? "" :
0185                    " [output power limits]"),
0186                   (chan->data & CHAN_HAS_CURVE ? "" :
0187                    " [curve data]"),
0188                   chan->index, chan->freq);
0189             continue;
0190         }
0191 
0192         dest->band = chan->band;
0193         dest->center_freq = chan->freq;
0194         dest->max_power = chan->max_power;
0195         priv->survey[*chan_num].channel = &tmp->channels[j];
0196         priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
0197             SURVEY_INFO_TIME |
0198             SURVEY_INFO_TIME_BUSY |
0199             SURVEY_INFO_TIME_TX;
0200         dest->hw_value = (*chan_num);
0201         j++;
0202         (*chan_num)++;
0203     }
0204 
0205     if (j == 0) {
0206         wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n",
0207               (band == NL80211_BAND_2GHZ) ? 2 : 5);
0208 
0209         ret = -ENODATA;
0210         goto err_out;
0211     }
0212 
0213     tmp->n_channels = j;
0214     old = priv->band_table[band];
0215     priv->band_table[band] = tmp;
0216     if (old) {
0217         kfree(old->channels);
0218         kfree(old);
0219     }
0220 
0221     return 0;
0222 
0223 err_out:
0224     if (tmp) {
0225         kfree(tmp->channels);
0226         kfree(tmp);
0227     }
0228 
0229     return ret;
0230 }
0231 
0232 static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list,
0233                               u16 freq, u16 data)
0234 {
0235     int i;
0236     struct p54_channel_entry *entry = NULL;
0237 
0238     /*
0239      * usually all lists in the eeprom are mostly sorted.
0240      * so it's very likely that the entry we are looking for
0241      * is right at the end of the list
0242      */
0243     for (i = list->entries; i >= 0; i--) {
0244         if (freq == list->channels[i].freq) {
0245             entry = &list->channels[i];
0246             break;
0247         }
0248     }
0249 
0250     if ((i < 0) && (list->entries < list->max_entries)) {
0251         /* entry does not exist yet. Initialize a new one. */
0252         int band = p54_get_band_from_freq(freq);
0253 
0254         /*
0255          * filter out frequencies which don't belong into
0256          * any supported band.
0257          */
0258         if (band >= 0) {
0259             i = list->entries++;
0260             list->band_channel_num[band]++;
0261 
0262             entry = &list->channels[i];
0263             entry->freq = freq;
0264             entry->band = band;
0265             entry->index = ieee80211_frequency_to_channel(freq);
0266             entry->max_power = 0;
0267             entry->data = 0;
0268         }
0269     }
0270 
0271     if (entry)
0272         entry->data |= data;
0273 
0274     return entry;
0275 }
0276 
0277 static int p54_get_maxpower(struct p54_common *priv, void *data)
0278 {
0279     switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) {
0280     case PDR_SYNTH_FRONTEND_LONGBOW: {
0281         struct pda_channel_output_limit_longbow *pda = data;
0282         int j;
0283         u16 rawpower = 0;
0284         pda = data;
0285         for (j = 0; j < ARRAY_SIZE(pda->point); j++) {
0286             struct pda_channel_output_limit_point_longbow *point =
0287                 &pda->point[j];
0288             rawpower = max_t(u16,
0289                 rawpower, le16_to_cpu(point->val_qpsk));
0290             rawpower = max_t(u16,
0291                 rawpower, le16_to_cpu(point->val_bpsk));
0292             rawpower = max_t(u16,
0293                 rawpower, le16_to_cpu(point->val_16qam));
0294             rawpower = max_t(u16,
0295                 rawpower, le16_to_cpu(point->val_64qam));
0296         }
0297         /* longbow seems to use 1/16 dBm units */
0298         return rawpower / 16;
0299         }
0300 
0301     case PDR_SYNTH_FRONTEND_DUETTE3:
0302     case PDR_SYNTH_FRONTEND_DUETTE2:
0303     case PDR_SYNTH_FRONTEND_FRISBEE:
0304     case PDR_SYNTH_FRONTEND_XBOW: {
0305         struct pda_channel_output_limit *pda = data;
0306         u8 rawpower = 0;
0307         rawpower = max(rawpower, pda->val_qpsk);
0308         rawpower = max(rawpower, pda->val_bpsk);
0309         rawpower = max(rawpower, pda->val_16qam);
0310         rawpower = max(rawpower, pda->val_64qam);
0311         /* raw values are in 1/4 dBm units */
0312         return rawpower / 4;
0313         }
0314 
0315     default:
0316         return 20;
0317     }
0318 }
0319 
0320 static int p54_generate_channel_lists(struct ieee80211_hw *dev)
0321 {
0322     struct p54_common *priv = dev->priv;
0323     struct p54_channel_list *list;
0324     unsigned int i, j, k, max_channel_num;
0325     int ret = 0;
0326     u16 freq;
0327 
0328     if ((priv->iq_autocal_len != priv->curve_data->entries) ||
0329         (priv->iq_autocal_len != priv->output_limit->entries))
0330         wiphy_err(dev->wiphy,
0331               "Unsupported or damaged EEPROM detected. "
0332               "You may not be able to use all channels.\n");
0333 
0334     max_channel_num = max_t(unsigned int, priv->output_limit->entries,
0335                 priv->iq_autocal_len);
0336     max_channel_num = max_t(unsigned int, max_channel_num,
0337                 priv->curve_data->entries);
0338 
0339     list = kzalloc(sizeof(*list), GFP_KERNEL);
0340     if (!list) {
0341         ret = -ENOMEM;
0342         goto free;
0343     }
0344     priv->chan_num = max_channel_num;
0345     priv->survey = kcalloc(max_channel_num, sizeof(struct survey_info),
0346                    GFP_KERNEL);
0347     if (!priv->survey) {
0348         ret = -ENOMEM;
0349         goto free;
0350     }
0351 
0352     list->max_entries = max_channel_num;
0353     list->channels = kcalloc(max_channel_num,
0354                  sizeof(struct p54_channel_entry),
0355                  GFP_KERNEL);
0356     if (!list->channels) {
0357         ret = -ENOMEM;
0358         goto free;
0359     }
0360 
0361     for (i = 0; i < max_channel_num; i++) {
0362         if (i < priv->iq_autocal_len) {
0363             freq = le16_to_cpu(priv->iq_autocal[i].freq);
0364             p54_update_channel_param(list, freq, CHAN_HAS_CAL);
0365         }
0366 
0367         if (i < priv->output_limit->entries) {
0368             struct p54_channel_entry *tmp;
0369 
0370             void *data = (void *) ((unsigned long) i *
0371                 priv->output_limit->entry_size +
0372                 priv->output_limit->offset +
0373                 priv->output_limit->data);
0374 
0375             freq = le16_to_cpup((__le16 *) data);
0376             tmp = p54_update_channel_param(list, freq,
0377                                CHAN_HAS_LIMIT);
0378             if (tmp) {
0379                 tmp->max_power = p54_get_maxpower(priv, data);
0380             }
0381         }
0382 
0383         if (i < priv->curve_data->entries) {
0384             freq = le16_to_cpup((__le16 *) (i *
0385                         priv->curve_data->entry_size +
0386                         priv->curve_data->offset +
0387                         priv->curve_data->data));
0388 
0389             p54_update_channel_param(list, freq, CHAN_HAS_CURVE);
0390         }
0391     }
0392 
0393     /* sort the channel list by frequency */
0394     sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
0395          p54_compare_channels, NULL);
0396 
0397     k = 0;
0398     for (i = 0, j = 0; i < NUM_NL80211_BANDS; i++) {
0399         if (p54_generate_band(dev, list, &k, i) == 0)
0400             j++;
0401     }
0402     if (j == 0) {
0403         /* no useable band available. */
0404         ret = -EINVAL;
0405     }
0406 
0407 free:
0408     if (list) {
0409         kfree(list->channels);
0410         kfree(list);
0411     }
0412     if (ret) {
0413         kfree(priv->survey);
0414         priv->survey = NULL;
0415     }
0416 
0417     return ret;
0418 }
0419 
0420 static int p54_convert_rev0(struct ieee80211_hw *dev,
0421                 struct pda_pa_curve_data *curve_data)
0422 {
0423     struct p54_common *priv = dev->priv;
0424     struct p54_pa_curve_data_sample *dst;
0425     struct pda_pa_curve_data_sample_rev0 *src;
0426     size_t cd_len = sizeof(*curve_data) +
0427         (curve_data->points_per_channel*sizeof(*dst) + 2) *
0428          curve_data->channels;
0429     unsigned int i, j;
0430     void *source, *target;
0431 
0432     priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
0433                    GFP_KERNEL);
0434     if (!priv->curve_data)
0435         return -ENOMEM;
0436 
0437     priv->curve_data->entries = curve_data->channels;
0438     priv->curve_data->entry_size = sizeof(__le16) +
0439         sizeof(*dst) * curve_data->points_per_channel;
0440     priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
0441     priv->curve_data->len = cd_len;
0442     memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
0443     source = curve_data->data;
0444     target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
0445     for (i = 0; i < curve_data->channels; i++) {
0446         __le16 *freq = source;
0447         source += sizeof(__le16);
0448         *((__le16 *)target) = *freq;
0449         target += sizeof(__le16);
0450         for (j = 0; j < curve_data->points_per_channel; j++) {
0451             dst = target;
0452             src = source;
0453 
0454             dst->rf_power = src->rf_power;
0455             dst->pa_detector = src->pa_detector;
0456             dst->data_64qam = src->pcv;
0457             /* "invent" the points for the other modulations */
0458 #define SUB(x, y) (u8)(((x) - (y)) > (x) ? 0 : (x) - (y))
0459             dst->data_16qam = SUB(src->pcv, 12);
0460             dst->data_qpsk = SUB(dst->data_16qam, 12);
0461             dst->data_bpsk = SUB(dst->data_qpsk, 12);
0462             dst->data_barker = SUB(dst->data_bpsk, 14);
0463 #undef SUB
0464             target += sizeof(*dst);
0465             source += sizeof(*src);
0466         }
0467     }
0468 
0469     return 0;
0470 }
0471 
0472 static int p54_convert_rev1(struct ieee80211_hw *dev,
0473                 struct pda_pa_curve_data *curve_data)
0474 {
0475     struct p54_common *priv = dev->priv;
0476     struct p54_pa_curve_data_sample *dst;
0477     struct pda_pa_curve_data_sample_rev1 *src;
0478     size_t cd_len = sizeof(*curve_data) +
0479         (curve_data->points_per_channel*sizeof(*dst) + 2) *
0480          curve_data->channels;
0481     unsigned int i, j;
0482     void *source, *target;
0483 
0484     priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
0485                    GFP_KERNEL);
0486     if (!priv->curve_data)
0487         return -ENOMEM;
0488 
0489     priv->curve_data->entries = curve_data->channels;
0490     priv->curve_data->entry_size = sizeof(__le16) +
0491         sizeof(*dst) * curve_data->points_per_channel;
0492     priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data);
0493     priv->curve_data->len = cd_len;
0494     memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data));
0495     source = curve_data->data;
0496     target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data;
0497     for (i = 0; i < curve_data->channels; i++) {
0498         __le16 *freq = source;
0499         source += sizeof(__le16);
0500         *((__le16 *)target) = *freq;
0501         target += sizeof(__le16);
0502         for (j = 0; j < curve_data->points_per_channel; j++) {
0503             memcpy(target, source, sizeof(*src));
0504 
0505             target += sizeof(*dst);
0506             source += sizeof(*src);
0507         }
0508         source++;
0509     }
0510 
0511     return 0;
0512 }
0513 
0514 static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
0515     "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
0516 
0517 static int p54_parse_rssical(struct ieee80211_hw *dev,
0518                  u8 *data, int len, u16 type)
0519 {
0520     struct p54_common *priv = dev->priv;
0521     struct p54_rssi_db_entry *entry;
0522     size_t db_len, entries;
0523     int offset = 0, i;
0524 
0525     if (type != PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
0526         entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
0527         if (len != sizeof(struct pda_rssi_cal_entry) * entries) {
0528             wiphy_err(dev->wiphy, "rssical size mismatch.\n");
0529             goto err_data;
0530         }
0531     } else {
0532         /*
0533          * Some devices (Dell 1450 USB, Xbow 5GHz card, etc...)
0534          * have an empty two byte header.
0535          */
0536         if (*((__le16 *)&data[offset]) == cpu_to_le16(0))
0537             offset += 2;
0538 
0539         entries = (len - offset) /
0540             sizeof(struct pda_rssi_cal_ext_entry);
0541 
0542         if (len < offset ||
0543             (len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
0544             entries == 0) {
0545             wiphy_err(dev->wiphy, "invalid rssi database.\n");
0546             goto err_data;
0547         }
0548     }
0549 
0550     db_len = sizeof(*entry) * entries;
0551     priv->rssi_db = kzalloc(db_len + sizeof(*priv->rssi_db), GFP_KERNEL);
0552     if (!priv->rssi_db)
0553         return -ENOMEM;
0554 
0555     priv->rssi_db->offset = 0;
0556     priv->rssi_db->entries = entries;
0557     priv->rssi_db->entry_size = sizeof(*entry);
0558     priv->rssi_db->len = db_len;
0559 
0560     entry = (void *)((unsigned long)priv->rssi_db->data + priv->rssi_db->offset);
0561     if (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
0562         struct pda_rssi_cal_ext_entry *cal = (void *) &data[offset];
0563 
0564         for (i = 0; i < entries; i++) {
0565             entry[i].freq = le16_to_cpu(cal[i].freq);
0566             entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
0567             entry[i].add = (s16) le16_to_cpu(cal[i].add);
0568         }
0569     } else {
0570         struct pda_rssi_cal_entry *cal = (void *) &data[offset];
0571 
0572         for (i = 0; i < entries; i++) {
0573             u16 freq = 0;
0574             switch (i) {
0575             case NL80211_BAND_2GHZ:
0576                 freq = 2437;
0577                 break;
0578             case NL80211_BAND_5GHZ:
0579                 freq = 5240;
0580                 break;
0581             }
0582 
0583             entry[i].freq = freq;
0584             entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
0585             entry[i].add = (s16) le16_to_cpu(cal[i].add);
0586         }
0587     }
0588 
0589     /* sort the list by channel frequency */
0590     sort(entry, entries, sizeof(*entry), p54_compare_rssichan, NULL);
0591     return 0;
0592 
0593 err_data:
0594     wiphy_err(dev->wiphy,
0595           "rssi calibration data packing type:(%x) len:%d.\n",
0596           type, len);
0597 
0598     print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len);
0599 
0600     wiphy_err(dev->wiphy, "please report this issue.\n");
0601     return -EINVAL;
0602 }
0603 
0604 struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
0605 {
0606     struct p54_rssi_db_entry *entry;
0607     int i, found = -1;
0608 
0609     if (!priv->rssi_db)
0610         return &p54_rssi_default;
0611 
0612     entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
0613     for (i = 0; i < priv->rssi_db->entries; i++) {
0614         if (!same_band(freq, entry[i].freq))
0615             continue;
0616 
0617         if (found == -1) {
0618             found = i;
0619             continue;
0620         }
0621 
0622         /* nearest match */
0623         if (abs(freq - entry[i].freq) <
0624             abs(freq - entry[found].freq)) {
0625             found = i;
0626             continue;
0627         } else {
0628             break;
0629         }
0630     }
0631 
0632     return found < 0 ? &p54_rssi_default : &entry[found];
0633 }
0634 
0635 static void p54_parse_default_country(struct ieee80211_hw *dev,
0636                       void *data, int len)
0637 {
0638     struct pda_country *country;
0639 
0640     if (len != sizeof(*country)) {
0641         wiphy_err(dev->wiphy,
0642               "found possible invalid default country eeprom entry. (entry size: %d)\n",
0643               len);
0644 
0645         print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
0646                      data, len);
0647 
0648         wiphy_err(dev->wiphy, "please report this issue.\n");
0649         return;
0650     }
0651 
0652     country = (struct pda_country *) data;
0653     if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO)
0654         regulatory_hint(dev->wiphy, country->alpha2);
0655     else {
0656         /* TODO:
0657          * write a shared/common function that converts
0658          * "Regulatory domain codes" (802.11-2007 14.8.2.2)
0659          * into ISO/IEC 3166-1 alpha2 for regulatory_hint.
0660          */
0661     }
0662 }
0663 
0664 static int p54_convert_output_limits(struct ieee80211_hw *dev,
0665                      u8 *data, size_t len)
0666 {
0667     struct p54_common *priv = dev->priv;
0668 
0669     if (len < 2)
0670         return -EINVAL;
0671 
0672     if (data[0] != 0) {
0673         wiphy_err(dev->wiphy, "unknown output power db revision:%x\n",
0674               data[0]);
0675         return -EINVAL;
0676     }
0677 
0678     if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len)
0679         return -EINVAL;
0680 
0681     priv->output_limit = kmalloc(data[1] *
0682         sizeof(struct pda_channel_output_limit) +
0683         sizeof(*priv->output_limit), GFP_KERNEL);
0684 
0685     if (!priv->output_limit)
0686         return -ENOMEM;
0687 
0688     priv->output_limit->offset = 0;
0689     priv->output_limit->entries = data[1];
0690     priv->output_limit->entry_size =
0691         sizeof(struct pda_channel_output_limit);
0692     priv->output_limit->len = priv->output_limit->entry_size *
0693                   priv->output_limit->entries +
0694                   priv->output_limit->offset;
0695 
0696     memcpy(priv->output_limit->data, &data[2],
0697            data[1] * sizeof(struct pda_channel_output_limit));
0698 
0699     return 0;
0700 }
0701 
0702 static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
0703                            size_t total_len)
0704 {
0705     struct p54_cal_database *dst;
0706     size_t payload_len, entries, entry_size, offset;
0707 
0708     payload_len = le16_to_cpu(src->len);
0709     entries = le16_to_cpu(src->entries);
0710     entry_size = le16_to_cpu(src->entry_size);
0711     offset = le16_to_cpu(src->offset);
0712     if (((entries * entry_size + offset) != payload_len) ||
0713          (payload_len + sizeof(*src) != total_len))
0714         return NULL;
0715 
0716     dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
0717     if (!dst)
0718         return NULL;
0719 
0720     dst->entries = entries;
0721     dst->entry_size = entry_size;
0722     dst->offset = offset;
0723     dst->len = payload_len;
0724 
0725     memcpy(dst->data, src->data, payload_len);
0726     return dst;
0727 }
0728 
0729 int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
0730 {
0731     struct p54_common *priv = dev->priv;
0732     struct eeprom_pda_wrap *wrap;
0733     struct pda_entry *entry;
0734     unsigned int data_len, entry_len;
0735     void *tmp;
0736     int err;
0737     u8 *end = (u8 *)eeprom + len;
0738     u16 synth = 0;
0739     u16 crc16 = ~0;
0740 
0741     wrap = (struct eeprom_pda_wrap *) eeprom;
0742     entry = (void *)wrap->data + le16_to_cpu(wrap->len);
0743 
0744     /* verify that at least the entry length/code fits */
0745     while ((u8 *)entry <= end - sizeof(*entry)) {
0746         entry_len = le16_to_cpu(entry->len);
0747         data_len = ((entry_len - 1) << 1);
0748 
0749         /* abort if entry exceeds whole structure */
0750         if ((u8 *)entry + sizeof(*entry) + data_len > end)
0751             break;
0752 
0753         switch (le16_to_cpu(entry->code)) {
0754         case PDR_MAC_ADDRESS:
0755             if (data_len != ETH_ALEN)
0756                 break;
0757             SET_IEEE80211_PERM_ADDR(dev, entry->data);
0758             break;
0759         case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
0760             if (priv->output_limit)
0761                 break;
0762             err = p54_convert_output_limits(dev, entry->data,
0763                             data_len);
0764             if (err)
0765                 goto err;
0766             break;
0767         case PDR_PRISM_PA_CAL_CURVE_DATA: {
0768             struct pda_pa_curve_data *curve_data =
0769                 (struct pda_pa_curve_data *)entry->data;
0770             if (data_len < sizeof(*curve_data)) {
0771                 err = -EINVAL;
0772                 goto err;
0773             }
0774 
0775             switch (curve_data->cal_method_rev) {
0776             case 0:
0777                 err = p54_convert_rev0(dev, curve_data);
0778                 break;
0779             case 1:
0780                 err = p54_convert_rev1(dev, curve_data);
0781                 break;
0782             default:
0783                 wiphy_err(dev->wiphy,
0784                       "unknown curve data revision %d\n",
0785                       curve_data->cal_method_rev);
0786                 err = -ENODEV;
0787                 break;
0788             }
0789             if (err)
0790                 goto err;
0791             }
0792             break;
0793         case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
0794             priv->iq_autocal = kmemdup(entry->data, data_len,
0795                            GFP_KERNEL);
0796             if (!priv->iq_autocal) {
0797                 err = -ENOMEM;
0798                 goto err;
0799             }
0800 
0801             priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
0802             break;
0803         case PDR_DEFAULT_COUNTRY:
0804             p54_parse_default_country(dev, entry->data, data_len);
0805             break;
0806         case PDR_INTERFACE_LIST:
0807             tmp = entry->data;
0808             while ((u8 *)tmp < entry->data + data_len) {
0809                 struct exp_if *exp_if = tmp;
0810                 if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000))
0811                     synth = le16_to_cpu(exp_if->variant);
0812                 tmp += sizeof(*exp_if);
0813             }
0814             break;
0815         case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
0816             if (data_len < 2)
0817                 break;
0818             priv->version = *(u8 *)(entry->data + 1);
0819             break;
0820         case PDR_RSSI_LINEAR_APPROXIMATION:
0821         case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
0822         case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
0823             err = p54_parse_rssical(dev, entry->data, data_len,
0824                         le16_to_cpu(entry->code));
0825             if (err)
0826                 goto err;
0827             break;
0828         case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: {
0829             struct pda_custom_wrapper *pda = (void *) entry->data;
0830             __le16 *src;
0831             u16 *dst;
0832             int i;
0833 
0834             if (priv->rssi_db || data_len < sizeof(*pda))
0835                 break;
0836 
0837             priv->rssi_db = p54_convert_db(pda, data_len);
0838             if (!priv->rssi_db)
0839                 break;
0840 
0841             src = (void *) priv->rssi_db->data;
0842             dst = (void *) priv->rssi_db->data;
0843 
0844             for (i = 0; i < priv->rssi_db->entries; i++)
0845                 *(dst++) = (s16) le16_to_cpu(*(src++));
0846 
0847             }
0848             break;
0849         case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
0850             struct pda_custom_wrapper *pda = (void *) entry->data;
0851             if (priv->output_limit || data_len < sizeof(*pda))
0852                 break;
0853             priv->output_limit = p54_convert_db(pda, data_len);
0854             }
0855             break;
0856         case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: {
0857             struct pda_custom_wrapper *pda = (void *) entry->data;
0858             if (priv->curve_data || data_len < sizeof(*pda))
0859                 break;
0860             priv->curve_data = p54_convert_db(pda, data_len);
0861             }
0862             break;
0863         case PDR_END:
0864             crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry));
0865             if (crc16 != le16_to_cpup((__le16 *)entry->data)) {
0866                 wiphy_err(dev->wiphy, "eeprom failed checksum "
0867                      "test!\n");
0868                 err = -ENOMSG;
0869                 goto err;
0870             } else {
0871                 goto good_eeprom;
0872             }
0873             break;
0874         default:
0875             break;
0876         }
0877 
0878         crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2);
0879         entry = (void *)entry + (entry_len + 1) * 2;
0880     }
0881 
0882     wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n");
0883     err = -ENODATA;
0884     goto err;
0885 
0886 good_eeprom:
0887     if (!synth || !priv->iq_autocal || !priv->output_limit ||
0888         !priv->curve_data) {
0889         wiphy_err(dev->wiphy,
0890               "not all required entries found in eeprom!\n");
0891         err = -EINVAL;
0892         goto err;
0893     }
0894 
0895     priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
0896 
0897     err = p54_generate_channel_lists(dev);
0898     if (err)
0899         goto err;
0900 
0901     if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
0902         p54_init_xbow_synth(priv);
0903     if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
0904         dev->wiphy->bands[NL80211_BAND_2GHZ] =
0905             priv->band_table[NL80211_BAND_2GHZ];
0906     if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
0907         dev->wiphy->bands[NL80211_BAND_5GHZ] =
0908             priv->band_table[NL80211_BAND_5GHZ];
0909     if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED)
0910         priv->rx_diversity_mask = 3;
0911     if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED)
0912         priv->tx_diversity_mask = 3;
0913 
0914     if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
0915         u8 perm_addr[ETH_ALEN];
0916 
0917         wiphy_warn(dev->wiphy,
0918                "Invalid hwaddr! Using randomly generated MAC addr\n");
0919         eth_random_addr(perm_addr);
0920         SET_IEEE80211_PERM_ADDR(dev, perm_addr);
0921     }
0922 
0923     priv->cur_rssi = &p54_rssi_default;
0924 
0925     wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
0926            dev->wiphy->perm_addr, priv->version,
0927            p54_rf_chips[priv->rxhw]);
0928 
0929     return 0;
0930 
0931 err:
0932     kfree(priv->iq_autocal);
0933     kfree(priv->output_limit);
0934     kfree(priv->curve_data);
0935     kfree(priv->rssi_db);
0936     kfree(priv->survey);
0937     priv->iq_autocal = NULL;
0938     priv->output_limit = NULL;
0939     priv->curve_data = NULL;
0940     priv->rssi_db = NULL;
0941     priv->survey = NULL;
0942 
0943     wiphy_err(dev->wiphy, "eeprom parse failed!\n");
0944     return err;
0945 }
0946 EXPORT_SYMBOL_GPL(p54_parse_eeprom);
0947 
0948 int p54_read_eeprom(struct ieee80211_hw *dev)
0949 {
0950     struct p54_common *priv = dev->priv;
0951     size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
0952     int ret = -ENOMEM;
0953     void *eeprom;
0954 
0955     maxblocksize = EEPROM_READBACK_LEN;
0956     if (priv->fw_var >= 0x509)
0957         maxblocksize -= 0xc;
0958     else
0959         maxblocksize -= 0x4;
0960 
0961     eeprom = kzalloc(eeprom_size, GFP_KERNEL);
0962     if (unlikely(!eeprom))
0963         goto free;
0964 
0965     while (eeprom_size) {
0966         blocksize = min(eeprom_size, maxblocksize);
0967         ret = p54_download_eeprom(priv, eeprom + offset,
0968                       offset, blocksize);
0969         if (unlikely(ret))
0970             goto free;
0971 
0972         offset += blocksize;
0973         eeprom_size -= blocksize;
0974     }
0975 
0976     ret = p54_parse_eeprom(dev, eeprom, offset);
0977 free:
0978     kfree(eeprom);
0979     return ret;
0980 }
0981 EXPORT_SYMBOL_GPL(p54_read_eeprom);