Loading drivers/net/wireless/p54/eeprom.c +256 −67 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/firmware.h> #include <linux/etherdevice.h> #include <linux/sort.h> #include <net/mac80211.h> Loading @@ -41,30 +42,6 @@ static struct ieee80211_rate p54_bgrates[] = { { .bitrate = 540, .hw_value = 11, }, }; static struct ieee80211_channel p54_bgchannels[] = { { .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, }, }; static struct ieee80211_supported_band band_2GHz = { .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, }, Loading @@ -76,51 +53,257 @@ static struct ieee80211_rate p54_arates[] = { { .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 }, #define CHAN_HAS_CAL BIT(0) #define CHAN_HAS_LIMIT BIT(1) #define CHAN_HAS_CURVE BIT(2) #define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE) struct p54_channel_entry { u16 freq; u16 data; int index; enum ieee80211_band band; }; 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), struct p54_channel_list { struct p54_channel_entry *channels; size_t entries; size_t max_entries; size_t band_channel_num[IEEE80211_NUM_BANDS]; }; static int p54_get_band_from_freq(u16 freq) { /* FIXME: sync these values with the 802.11 spec */ if ((freq >= 2412) && (freq <= 2484)) return IEEE80211_BAND_2GHZ; if ((freq >= 4920) && (freq <= 5825)) return IEEE80211_BAND_5GHZ; return -1; } static int p54_compare_channels(const void *_a, const void *_b) { const struct p54_channel_entry *a = _a; const struct p54_channel_entry *b = _b; return a->index - b->index; } static int p54_fill_band_bitrates(struct ieee80211_hw *dev, struct ieee80211_supported_band *band_entry, enum ieee80211_band band) { /* TODO: generate rate array dynamically */ switch (band) { case IEEE80211_BAND_2GHZ: band_entry->bitrates = p54_bgrates; band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); break; case IEEE80211_BAND_5GHZ: band_entry->bitrates = p54_arates; band_entry->n_bitrates = ARRAY_SIZE(p54_arates); break; default: return -EINVAL; } return 0; } static int p54_generate_band(struct ieee80211_hw *dev, struct p54_channel_list *list, enum ieee80211_band band) { struct p54_common *priv = dev->priv; struct ieee80211_supported_band *tmp, *old; unsigned int i, j; int ret = -ENOMEM; if ((!list->entries) || (!list->band_channel_num[band])) return 0; tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) goto err_out; tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * list->band_channel_num[band], GFP_KERNEL); if (!tmp->channels) goto err_out; ret = p54_fill_band_bitrates(dev, tmp, band); if (ret) goto err_out; for (i = 0, j = 0; (j < list->band_channel_num[band]) && (i < list->entries); i++) { if (list->channels[i].band != band) continue; if (list->channels[i].data != CHAN_HAS_ALL) { printk(KERN_ERR "%s:%s%s%s is/are missing for " "channel:%d [%d MHz].\n", wiphy_name(dev->wiphy), (list->channels[i].data & CHAN_HAS_CAL ? "" : " [iqauto calibration data]"), (list->channels[i].data & CHAN_HAS_LIMIT ? "" : " [output power limits]"), (list->channels[i].data & CHAN_HAS_CURVE ? "" : " [curve data]"), list->channels[i].index, list->channels[i].freq); } tmp->channels[j].band = list->channels[i].band; tmp->channels[j].center_freq = list->channels[i].freq; j++; } tmp->n_channels = list->band_channel_num[band]; old = priv->band_table[band]; priv->band_table[band] = tmp; if (old) { kfree(old->channels); kfree(old); } return 0; err_out: if (tmp) { kfree(tmp->channels); kfree(tmp); } return ret; } static void p54_update_channel_param(struct p54_channel_list *list, u16 freq, u16 data) { int band, i; /* * usually all lists in the eeprom are mostly sorted. * so it's very likely that the entry we are looking for * is right at the end of the list */ for (i = list->entries; i >= 0; i--) { if (freq == list->channels[i].freq) { list->channels[i].data |= data; break; } } if ((i < 0) && (list->entries < list->max_entries)) { /* entry does not exist yet. Initialize a new one. */ band = p54_get_band_from_freq(freq); /* * filter out frequencies which don't belong into * any supported band. */ if (band < 0) return ; i = list->entries++; list->band_channel_num[band]++; list->channels[i].freq = freq; list->channels[i].data = data; list->channels[i].band = band; list->channels[i].index = ieee80211_frequency_to_channel(freq); /* TODO: parse output_limit and fill max_power */ } } static int p54_generate_channel_lists(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; struct p54_channel_list *list; unsigned int i, j, max_channel_num; int ret = -ENOMEM; u16 freq; if ((priv->iq_autocal_len != priv->curve_data->entries) || (priv->iq_autocal_len != priv->output_limit->entries)) printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" "to use all channels with this device.\n", wiphy_name(dev->wiphy)); max_channel_num = max_t(unsigned int, priv->output_limit->entries, priv->iq_autocal_len); max_channel_num = max_t(unsigned int, max_channel_num, priv->curve_data->entries); list = kzalloc(sizeof(*list), GFP_KERNEL); if (!list) goto free; list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * max_channel_num, GFP_KERNEL); if (!list->channels) goto free; for (i = 0; i < max_channel_num; i++) { if (i < priv->iq_autocal_len) { freq = le16_to_cpu(priv->iq_autocal[i].freq); p54_update_channel_param(list, freq, CHAN_HAS_CAL); } if (i < priv->output_limit->entries) { freq = le16_to_cpup((__le16 *) (i * priv->output_limit->entry_size + priv->output_limit->offset + priv->output_limit->data)); p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); } if (i < priv->curve_data->entries) { freq = le16_to_cpup((__le16 *) (i * priv->curve_data->entry_size + priv->curve_data->offset + priv->curve_data->data)); p54_update_channel_param(list, freq, CHAN_HAS_CURVE); } } /* sort the list by the channel index */ sort(list->channels, list->entries, sizeof(struct p54_channel_entry), p54_compare_channels, NULL); for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { if (list->band_channel_num[i]) { ret = p54_generate_band(dev, list, i); if (ret) goto free; j++; } } if (j == 0) { /* no useable band available. */ ret = -EINVAL; } free: if (list) { kfree(list->channels); kfree(list); } return ret; } static int p54_convert_rev0(struct ieee80211_hw *dev, struct pda_pa_curve_data *curve_data) { Loading Loading @@ -487,13 +670,19 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) goto err; } err = p54_generate_channel_lists(dev); if (err) goto err; priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; dev->wiphy->bands[IEEE80211_BAND_2GHZ] = priv->band_table[IEEE80211_BAND_2GHZ]; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; dev->wiphy->bands[IEEE80211_BAND_5GHZ] = priv->band_table[IEEE80211_BAND_5GHZ]; 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) Loading drivers/net/wireless/p54/main.c +4 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,10 @@ EXPORT_SYMBOL_GPL(p54_register_common); void p54_free_common(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; unsigned int i; for (i = 0; i < IEEE80211_NUM_BANDS; i++) kfree(priv->band_table[i]); kfree(priv->iq_autocal); kfree(priv->output_limit); Loading drivers/net/wireless/p54/p54.h +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ struct p54_common { struct p54_cal_database *curve_data; struct p54_cal_database *output_limit; struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; Loading Loading
drivers/net/wireless/p54/eeprom.c +256 −67 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/firmware.h> #include <linux/etherdevice.h> #include <linux/sort.h> #include <net/mac80211.h> Loading @@ -41,30 +42,6 @@ static struct ieee80211_rate p54_bgrates[] = { { .bitrate = 540, .hw_value = 11, }, }; static struct ieee80211_channel p54_bgchannels[] = { { .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, }, }; static struct ieee80211_supported_band band_2GHz = { .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, }, Loading @@ -76,51 +53,257 @@ static struct ieee80211_rate p54_arates[] = { { .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 }, #define CHAN_HAS_CAL BIT(0) #define CHAN_HAS_LIMIT BIT(1) #define CHAN_HAS_CURVE BIT(2) #define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE) struct p54_channel_entry { u16 freq; u16 data; int index; enum ieee80211_band band; }; 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), struct p54_channel_list { struct p54_channel_entry *channels; size_t entries; size_t max_entries; size_t band_channel_num[IEEE80211_NUM_BANDS]; }; static int p54_get_band_from_freq(u16 freq) { /* FIXME: sync these values with the 802.11 spec */ if ((freq >= 2412) && (freq <= 2484)) return IEEE80211_BAND_2GHZ; if ((freq >= 4920) && (freq <= 5825)) return IEEE80211_BAND_5GHZ; return -1; } static int p54_compare_channels(const void *_a, const void *_b) { const struct p54_channel_entry *a = _a; const struct p54_channel_entry *b = _b; return a->index - b->index; } static int p54_fill_band_bitrates(struct ieee80211_hw *dev, struct ieee80211_supported_band *band_entry, enum ieee80211_band band) { /* TODO: generate rate array dynamically */ switch (band) { case IEEE80211_BAND_2GHZ: band_entry->bitrates = p54_bgrates; band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); break; case IEEE80211_BAND_5GHZ: band_entry->bitrates = p54_arates; band_entry->n_bitrates = ARRAY_SIZE(p54_arates); break; default: return -EINVAL; } return 0; } static int p54_generate_band(struct ieee80211_hw *dev, struct p54_channel_list *list, enum ieee80211_band band) { struct p54_common *priv = dev->priv; struct ieee80211_supported_band *tmp, *old; unsigned int i, j; int ret = -ENOMEM; if ((!list->entries) || (!list->band_channel_num[band])) return 0; tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) goto err_out; tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * list->band_channel_num[band], GFP_KERNEL); if (!tmp->channels) goto err_out; ret = p54_fill_band_bitrates(dev, tmp, band); if (ret) goto err_out; for (i = 0, j = 0; (j < list->band_channel_num[band]) && (i < list->entries); i++) { if (list->channels[i].band != band) continue; if (list->channels[i].data != CHAN_HAS_ALL) { printk(KERN_ERR "%s:%s%s%s is/are missing for " "channel:%d [%d MHz].\n", wiphy_name(dev->wiphy), (list->channels[i].data & CHAN_HAS_CAL ? "" : " [iqauto calibration data]"), (list->channels[i].data & CHAN_HAS_LIMIT ? "" : " [output power limits]"), (list->channels[i].data & CHAN_HAS_CURVE ? "" : " [curve data]"), list->channels[i].index, list->channels[i].freq); } tmp->channels[j].band = list->channels[i].band; tmp->channels[j].center_freq = list->channels[i].freq; j++; } tmp->n_channels = list->band_channel_num[band]; old = priv->band_table[band]; priv->band_table[band] = tmp; if (old) { kfree(old->channels); kfree(old); } return 0; err_out: if (tmp) { kfree(tmp->channels); kfree(tmp); } return ret; } static void p54_update_channel_param(struct p54_channel_list *list, u16 freq, u16 data) { int band, i; /* * usually all lists in the eeprom are mostly sorted. * so it's very likely that the entry we are looking for * is right at the end of the list */ for (i = list->entries; i >= 0; i--) { if (freq == list->channels[i].freq) { list->channels[i].data |= data; break; } } if ((i < 0) && (list->entries < list->max_entries)) { /* entry does not exist yet. Initialize a new one. */ band = p54_get_band_from_freq(freq); /* * filter out frequencies which don't belong into * any supported band. */ if (band < 0) return ; i = list->entries++; list->band_channel_num[band]++; list->channels[i].freq = freq; list->channels[i].data = data; list->channels[i].band = band; list->channels[i].index = ieee80211_frequency_to_channel(freq); /* TODO: parse output_limit and fill max_power */ } } static int p54_generate_channel_lists(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; struct p54_channel_list *list; unsigned int i, j, max_channel_num; int ret = -ENOMEM; u16 freq; if ((priv->iq_autocal_len != priv->curve_data->entries) || (priv->iq_autocal_len != priv->output_limit->entries)) printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" "to use all channels with this device.\n", wiphy_name(dev->wiphy)); max_channel_num = max_t(unsigned int, priv->output_limit->entries, priv->iq_autocal_len); max_channel_num = max_t(unsigned int, max_channel_num, priv->curve_data->entries); list = kzalloc(sizeof(*list), GFP_KERNEL); if (!list) goto free; list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * max_channel_num, GFP_KERNEL); if (!list->channels) goto free; for (i = 0; i < max_channel_num; i++) { if (i < priv->iq_autocal_len) { freq = le16_to_cpu(priv->iq_autocal[i].freq); p54_update_channel_param(list, freq, CHAN_HAS_CAL); } if (i < priv->output_limit->entries) { freq = le16_to_cpup((__le16 *) (i * priv->output_limit->entry_size + priv->output_limit->offset + priv->output_limit->data)); p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); } if (i < priv->curve_data->entries) { freq = le16_to_cpup((__le16 *) (i * priv->curve_data->entry_size + priv->curve_data->offset + priv->curve_data->data)); p54_update_channel_param(list, freq, CHAN_HAS_CURVE); } } /* sort the list by the channel index */ sort(list->channels, list->entries, sizeof(struct p54_channel_entry), p54_compare_channels, NULL); for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { if (list->band_channel_num[i]) { ret = p54_generate_band(dev, list, i); if (ret) goto free; j++; } } if (j == 0) { /* no useable band available. */ ret = -EINVAL; } free: if (list) { kfree(list->channels); kfree(list); } return ret; } static int p54_convert_rev0(struct ieee80211_hw *dev, struct pda_pa_curve_data *curve_data) { Loading Loading @@ -487,13 +670,19 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) goto err; } err = p54_generate_channel_lists(dev); if (err) goto err; priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; dev->wiphy->bands[IEEE80211_BAND_2GHZ] = priv->band_table[IEEE80211_BAND_2GHZ]; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; dev->wiphy->bands[IEEE80211_BAND_5GHZ] = priv->band_table[IEEE80211_BAND_5GHZ]; 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) Loading
drivers/net/wireless/p54/main.c +4 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,10 @@ EXPORT_SYMBOL_GPL(p54_register_common); void p54_free_common(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; unsigned int i; for (i = 0; i < IEEE80211_NUM_BANDS; i++) kfree(priv->band_table[i]); kfree(priv->iq_autocal); kfree(priv->output_limit); Loading
drivers/net/wireless/p54/p54.h +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ struct p54_common { struct p54_cal_database *curve_data; struct p54_cal_database *output_limit; struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; Loading