aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r--drivers/net/wireless/p54/eeprom.c208
-rw-r--r--drivers/net/wireless/p54/eeprom.h7
-rw-r--r--drivers/net/wireless/p54/fwio.c12
-rw-r--r--drivers/net/wireless/p54/lmac.h1
-rw-r--r--drivers/net/wireless/p54/main.c47
-rw-r--r--drivers/net/wireless/p54/p54.h6
-rw-r--r--drivers/net/wireless/p54/p54spi_eeprom.h9
-rw-r--r--drivers/net/wireless/p54/txrx.c6
8 files changed, 238 insertions, 58 deletions
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 35b09aa0529..f54e15fcd62 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -55,6 +55,17 @@ static struct ieee80211_rate p54_arates[] = {
55 { .bitrate = 540, .hw_value = 11, }, 55 { .bitrate = 540, .hw_value = 11, },
56}; 56};
57 57
58static 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
58#define CHAN_HAS_CAL BIT(0) 69#define CHAN_HAS_CAL BIT(0)
59#define CHAN_HAS_LIMIT BIT(1) 70#define CHAN_HAS_LIMIT BIT(1)
60#define CHAN_HAS_CURVE BIT(2) 71#define CHAN_HAS_CURVE BIT(2)
@@ -87,13 +98,27 @@ static int p54_get_band_from_freq(u16 freq)
87 return -1; 98 return -1;
88} 99}
89 100
101static int same_band(u16 freq, u16 freq2)
102{
103 return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
104}
105
90static int p54_compare_channels(const void *_a, 106static int p54_compare_channels(const void *_a,
91 const void *_b) 107 const void *_b)
92{ 108{
93 const struct p54_channel_entry *a = _a; 109 const struct p54_channel_entry *a = _a;
94 const struct p54_channel_entry *b = _b; 110 const struct p54_channel_entry *b = _b;
95 111
96 return a->index - b->index; 112 return a->freq - b->freq;
113}
114
115static 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;
97} 122}
98 123
99static int p54_fill_band_bitrates(struct ieee80211_hw *dev, 124static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
@@ -145,25 +170,26 @@ static int p54_generate_band(struct ieee80211_hw *dev,
145 170
146 for (i = 0, j = 0; (j < list->band_channel_num[band]) && 171 for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
147 (i < list->entries); i++) { 172 (i < list->entries); i++) {
173 struct p54_channel_entry *chan = &list->channels[i];
148 174
149 if (list->channels[i].band != band) 175 if (chan->band != band)
150 continue; 176 continue;
151 177
152 if (list->channels[i].data != CHAN_HAS_ALL) { 178 if (chan->data != CHAN_HAS_ALL) {
153 wiphy_err(dev->wiphy, 179 wiphy_err(dev->wiphy, "%s%s%s is/are missing for "
154 "%s%s%s is/are missing for channel:%d [%d MHz].\n", 180 "channel:%d [%d MHz].\n",
155 (list->channels[i].data & CHAN_HAS_CAL ? "" : 181 (chan->data & CHAN_HAS_CAL ? "" :
156 " [iqauto calibration data]"), 182 " [iqauto calibration data]"),
157 (list->channels[i].data & CHAN_HAS_LIMIT ? "" : 183 (chan->data & CHAN_HAS_LIMIT ? "" :
158 " [output power limits]"), 184 " [output power limits]"),
159 (list->channels[i].data & CHAN_HAS_CURVE ? "" : 185 (chan->data & CHAN_HAS_CURVE ? "" :
160 " [curve data]"), 186 " [curve data]"),
161 list->channels[i].index, list->channels[i].freq); 187 chan->index, chan->freq);
162 continue; 188 continue;
163 } 189 }
164 190
165 tmp->channels[j].band = list->channels[i].band; 191 tmp->channels[j].band = chan->band;
166 tmp->channels[j].center_freq = list->channels[i].freq; 192 tmp->channels[j].center_freq = chan->freq;
167 j++; 193 j++;
168 } 194 }
169 195
@@ -291,7 +317,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
291 } 317 }
292 } 318 }
293 319
294 /* sort the list by the channel index */ 320 /* sort the channel list by frequency */
295 sort(list->channels, list->entries, sizeof(struct p54_channel_entry), 321 sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
296 p54_compare_channels, NULL); 322 p54_compare_channels, NULL);
297 323
@@ -410,33 +436,118 @@ static int p54_convert_rev1(struct ieee80211_hw *dev,
410static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2", 436static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
411 "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" }; 437 "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
412 438
413static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, 439static int p54_parse_rssical(struct ieee80211_hw *dev,
414 u16 type) 440 u8 *data, int len, u16 type)
415{ 441{
416 struct p54_common *priv = dev->priv; 442 struct p54_common *priv = dev->priv;
417 int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0; 443 struct p54_rssi_db_entry *entry;
418 int entry_size = sizeof(struct pda_rssi_cal_entry) + offset; 444 size_t db_len, entries;
419 int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2; 445 int offset = 0, i;
420 int i; 446
447 if (type != PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
448 entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
449 if (len != sizeof(struct pda_rssi_cal_entry) * entries) {
450 wiphy_err(dev->wiphy, "rssical size mismatch.\n");
451 goto err_data;
452 }
453 } else {
454 /*
455 * Some devices (Dell 1450 USB, Xbow 5GHz card, etc...)
456 * have an empty two byte header.
457 */
458 if (*((__le16 *)&data[offset]) == cpu_to_le16(0))
459 offset += 2;
421 460
422 if (len != (entry_size * num_entries)) { 461 entries = (len - offset) /
423 wiphy_err(dev->wiphy, 462 sizeof(struct pda_rssi_cal_ext_entry);
424 "unknown rssi calibration data packing type:(%x) len:%d.\n",
425 type, len);
426 463
427 print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, 464 if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
428 data, len); 465 entries <= 0) {
466 wiphy_err(dev->wiphy, "invalid rssi database.\n");
467 goto err_data;
468 }
469 }
429 470
430 wiphy_err(dev->wiphy, "please report this issue.\n"); 471 db_len = sizeof(*entry) * entries;
431 return; 472 priv->rssi_db = kzalloc(db_len + sizeof(*priv->rssi_db), GFP_KERNEL);
473 if (!priv->rssi_db)
474 return -ENOMEM;
475
476 priv->rssi_db->offset = 0;
477 priv->rssi_db->entries = entries;
478 priv->rssi_db->entry_size = sizeof(*entry);
479 priv->rssi_db->len = db_len;
480
481 entry = (void *)((unsigned long)priv->rssi_db->data + priv->rssi_db->offset);
482 if (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
483 struct pda_rssi_cal_ext_entry *cal = (void *) &data[offset];
484
485 for (i = 0; i < entries; i++) {
486 entry[i].freq = le16_to_cpu(cal[i].freq);
487 entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
488 entry[i].add = (s16) le16_to_cpu(cal[i].add);
489 }
490 } else {
491 struct pda_rssi_cal_entry *cal = (void *) &data[offset];
492
493 for (i = 0; i < entries; i++) {
494 u16 freq;
495 switch (i) {
496 case IEEE80211_BAND_2GHZ:
497 freq = 2437;
498 break;
499 case IEEE80211_BAND_5GHZ:
500 freq = 5240;
501 break;
502 }
503
504 entry[i].freq = freq;
505 entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
506 entry[i].add = (s16) le16_to_cpu(cal[i].add);
507 }
432 } 508 }
433 509
434 for (i = 0; i < num_entries; i++) { 510 /* sort the list by channel frequency */
435 struct pda_rssi_cal_entry *cal = data + 511 sort(entry, entries, sizeof(*entry), p54_compare_rssichan, NULL);
436 (offset + i * entry_size); 512 return 0;
437 priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul); 513
438 priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add); 514err_data:
515 wiphy_err(dev->wiphy,
516 "rssi calibration data packing type:(%x) len:%d.\n",
517 type, len);
518
519 print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len);
520
521 wiphy_err(dev->wiphy, "please report this issue.\n");
522 return -EINVAL;
523}
524
525struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
526{
527 struct p54_rssi_db_entry *entry = (void *)(priv->rssi_db->data +
528 priv->rssi_db->offset);
529 int i, found = -1;
530
531 for (i = 0; i < priv->rssi_db->entries; i++) {
532 if (!same_band(freq, entry[i].freq))
533 continue;
534
535 if (found == -1) {
536 found = i;
537 continue;
538 }
539
540 /* nearest match */
541 if (abs(freq - entry[i].freq) <
542 abs(freq - entry[found].freq)) {
543 found = i;
544 continue;
545 } else {
546 break;
547 }
439 } 548 }
549
550 return found < 0 ? &p54_rssi_default : &entry[found];
440} 551}
441 552
442static void p54_parse_default_country(struct ieee80211_hw *dev, 553static void p54_parse_default_country(struct ieee80211_hw *dev,
@@ -627,21 +738,30 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
627 case PDR_RSSI_LINEAR_APPROXIMATION: 738 case PDR_RSSI_LINEAR_APPROXIMATION:
628 case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: 739 case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
629 case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: 740 case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
630 p54_parse_rssical(dev, entry->data, data_len, 741 err = p54_parse_rssical(dev, entry->data, data_len,
631 le16_to_cpu(entry->code)); 742 le16_to_cpu(entry->code));
743 if (err)
744 goto err;
632 break; 745 break;
633 case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: { 746 case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: {
634 __le16 *src = (void *) entry->data; 747 struct pda_custom_wrapper *pda = (void *) entry->data;
635 s16 *dst = (void *) &priv->rssical_db; 748 __le16 *src;
749 u16 *dst;
636 int i; 750 int i;
637 751
638 if (data_len != sizeof(priv->rssical_db)) { 752 if (priv->rssi_db || data_len < sizeof(*pda))
639 err = -EINVAL; 753 break;
640 goto err; 754
641 } 755 priv->rssi_db = p54_convert_db(pda, data_len);
642 for (i = 0; i < sizeof(priv->rssical_db) / 756 if (!priv->rssi_db)
643 sizeof(*src); i++) 757 break;
758
759 src = (void *) priv->rssi_db->data;
760 dst = (void *) priv->rssi_db->data;
761
762 for (i = 0; i < priv->rssi_db->entries; i++)
644 *(dst++) = (s16) le16_to_cpu(*(src++)); 763 *(dst++) = (s16) le16_to_cpu(*(src++));
764
645 } 765 }
646 break; 766 break;
647 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: { 767 case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
@@ -717,6 +837,8 @@ good_eeprom:
717 SET_IEEE80211_PERM_ADDR(dev, perm_addr); 837 SET_IEEE80211_PERM_ADDR(dev, perm_addr);
718 } 838 }
719 839
840 priv->cur_rssi = &p54_rssi_default;
841
720 wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n", 842 wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
721 dev->wiphy->perm_addr, priv->version, 843 dev->wiphy->perm_addr, priv->version,
722 p54_rf_chips[priv->rxhw]); 844 p54_rf_chips[priv->rxhw]);
@@ -727,9 +849,11 @@ err:
727 kfree(priv->iq_autocal); 849 kfree(priv->iq_autocal);
728 kfree(priv->output_limit); 850 kfree(priv->output_limit);
729 kfree(priv->curve_data); 851 kfree(priv->curve_data);
852 kfree(priv->rssi_db);
730 priv->iq_autocal = NULL; 853 priv->iq_autocal = NULL;
731 priv->output_limit = NULL; 854 priv->output_limit = NULL;
732 priv->curve_data = NULL; 855 priv->curve_data = NULL;
856 priv->rssi_db = NULL;
733 857
734 wiphy_err(dev->wiphy, "eeprom parse failed!\n"); 858 wiphy_err(dev->wiphy, "eeprom parse failed!\n");
735 return err; 859 return err;
diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h
index 9051aef1124..afde72b8460 100644
--- a/drivers/net/wireless/p54/eeprom.h
+++ b/drivers/net/wireless/p54/eeprom.h
@@ -81,6 +81,12 @@ struct pda_pa_curve_data {
81 u8 data[0]; 81 u8 data[0];
82} __packed; 82} __packed;
83 83
84struct pda_rssi_cal_ext_entry {
85 __le16 freq;
86 __le16 mul;
87 __le16 add;
88} __packed;
89
84struct pda_rssi_cal_entry { 90struct pda_rssi_cal_entry {
85 __le16 mul; 91 __le16 mul;
86 __le16 add; 92 __le16 add;
@@ -179,6 +185,7 @@ struct pda_custom_wrapper {
179 185
180/* used by our modificated eeprom image */ 186/* used by our modificated eeprom image */
181#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD 187#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD
188#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2 0xCAFF
182#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF 189#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF
183#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D 190#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D
184 191
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 92b9b1f05fd..0d3d108f6fe 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -397,9 +397,9 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
397 union p54_scan_body_union *body; 397 union p54_scan_body_union *body;
398 struct p54_scan_tail_rate *rate; 398 struct p54_scan_tail_rate *rate;
399 struct pda_rssi_cal_entry *rssi; 399 struct pda_rssi_cal_entry *rssi;
400 struct p54_rssi_db_entry *rssi_data;
400 unsigned int i; 401 unsigned int i;
401 void *entry; 402 void *entry;
402 int band = priv->hw->conf.channel->band;
403 __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq); 403 __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
404 404
405 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + 405 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
@@ -503,13 +503,14 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
503 } 503 }
504 504
505 rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); 505 rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
506 rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); 506 rssi_data = p54_rssi_find(priv, le16_to_cpu(freq));
507 rssi->add = cpu_to_le16(priv->rssical_db[band].add); 507 rssi->mul = cpu_to_le16(rssi_data->mul);
508 rssi->add = cpu_to_le16(rssi_data->add);
508 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 509 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
509 /* Longbow frontend needs ever more */ 510 /* Longbow frontend needs ever more */
510 rssi = (void *) skb_put(skb, sizeof(*rssi)); 511 rssi = (void *) skb_put(skb, sizeof(*rssi));
511 rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); 512 rssi->mul = cpu_to_le16(rssi_data->longbow_unkn);
512 rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); 513 rssi->add = cpu_to_le16(rssi_data->longbow_unk2);
513 } 514 }
514 515
515 if (priv->fw_var >= 0x509) { 516 if (priv->fw_var >= 0x509) {
@@ -523,6 +524,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
523 hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); 524 hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
524 525
525 p54_tx(priv, skb); 526 p54_tx(priv, skb);
527 priv->cur_rssi = rssi_data;
526 return 0; 528 return 0;
527 529
528err: 530err:
diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h
index 04b63ec80fa..5ca117e6f95 100644
--- a/drivers/net/wireless/p54/lmac.h
+++ b/drivers/net/wireless/p54/lmac.h
@@ -551,6 +551,7 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot,
551/* eeprom */ 551/* eeprom */
552int p54_download_eeprom(struct p54_common *priv, void *buf, 552int p54_download_eeprom(struct p54_common *priv, void *buf,
553 u16 offset, u16 len); 553 u16 offset, u16 len);
554struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *p, const u16 freq);
554 555
555/* utility */ 556/* utility */
556u8 *p54_find_ie(struct sk_buff *skb, u8 ie); 557u8 *p54_find_ie(struct sk_buff *skb, u8 ie);
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 622d27b6d8f..e14a05bbc48 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -524,6 +524,48 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
524 return 0; 524 return 0;
525} 525}
526 526
527static unsigned int p54_flush_count(struct p54_common *priv)
528{
529 unsigned int total = 0, i;
530
531 BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats));
532
533 /*
534 * Because the firmware has the sole control over any frames
535 * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they
536 * don't really count as pending or active.
537 */
538 for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)
539 total += priv->tx_stats[i].len;
540 return total;
541}
542
543static void p54_flush(struct ieee80211_hw *dev, bool drop)
544{
545 struct p54_common *priv = dev->priv;
546 unsigned int total, i;
547
548 /*
549 * Currently, it wouldn't really matter if we wait for one second
550 * or 15 minutes. But once someone gets around and completes the
551 * TODOs [ancel stuck frames / reset device] in p54_work, it will
552 * suddenly make sense to wait that long.
553 */
554 i = P54_STATISTICS_UPDATE * 2 / 20;
555
556 /*
557 * In this case no locking is required because as we speak the
558 * queues have already been stopped and no new frames can sneak
559 * up from behind.
560 */
561 while ((total = p54_flush_count(priv) && i--)) {
562 /* waste time */
563 msleep(20);
564 }
565
566 WARN(total, "tx flush timeout, unresponsive firmware");
567}
568
527static const struct ieee80211_ops p54_ops = { 569static const struct ieee80211_ops p54_ops = {
528 .tx = p54_tx_80211, 570 .tx = p54_tx_80211,
529 .start = p54_start, 571 .start = p54_start,
@@ -536,6 +578,7 @@ static const struct ieee80211_ops p54_ops = {
536 .sta_remove = p54_sta_add_remove, 578 .sta_remove = p54_sta_add_remove,
537 .set_key = p54_set_key, 579 .set_key = p54_set_key,
538 .config = p54_config, 580 .config = p54_config,
581 .flush = p54_flush,
539 .bss_info_changed = p54_bss_info_changed, 582 .bss_info_changed = p54_bss_info_changed,
540 .configure_filter = p54_configure_filter, 583 .configure_filter = p54_configure_filter,
541 .conf_tx = p54_conf_tx, 584 .conf_tx = p54_conf_tx,
@@ -611,7 +654,7 @@ EXPORT_SYMBOL_GPL(p54_init_common);
611 654
612int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) 655int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
613{ 656{
614 struct p54_common *priv = dev->priv; 657 struct p54_common __maybe_unused *priv = dev->priv;
615 int err; 658 int err;
616 659
617 err = ieee80211_register_hw(dev); 660 err = ieee80211_register_hw(dev);
@@ -642,10 +685,12 @@ void p54_free_common(struct ieee80211_hw *dev)
642 kfree(priv->iq_autocal); 685 kfree(priv->iq_autocal);
643 kfree(priv->output_limit); 686 kfree(priv->output_limit);
644 kfree(priv->curve_data); 687 kfree(priv->curve_data);
688 kfree(priv->rssi_db);
645 kfree(priv->used_rxkeys); 689 kfree(priv->used_rxkeys);
646 priv->iq_autocal = NULL; 690 priv->iq_autocal = NULL;
647 priv->output_limit = NULL; 691 priv->output_limit = NULL;
648 priv->curve_data = NULL; 692 priv->curve_data = NULL;
693 priv->rssi_db = NULL;
649 priv->used_rxkeys = NULL; 694 priv->used_rxkeys = NULL;
650 ieee80211_free_hw(dev); 695 ieee80211_free_hw(dev);
651} 696}
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 43a3b2ead81..f951c8f3186 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -116,7 +116,8 @@ struct p54_edcf_queue_param {
116 __le16 txop; 116 __le16 txop;
117} __packed; 117} __packed;
118 118
119struct p54_rssi_linear_approximation { 119struct p54_rssi_db_entry {
120 u16 freq;
120 s16 mul; 121 s16 mul;
121 s16 add; 122 s16 add;
122 s16 longbow_unkn; 123 s16 longbow_unkn;
@@ -197,13 +198,14 @@ struct p54_common {
197 u8 rx_diversity_mask; 198 u8 rx_diversity_mask;
198 u8 tx_diversity_mask; 199 u8 tx_diversity_mask;
199 unsigned int output_power; 200 unsigned int output_power;
201 struct p54_rssi_db_entry *cur_rssi;
200 int noise; 202 int noise;
201 /* calibration, output power limit and rssi<->dBm conversation data */ 203 /* calibration, output power limit and rssi<->dBm conversation data */
202 struct pda_iq_autocal_entry *iq_autocal; 204 struct pda_iq_autocal_entry *iq_autocal;
203 unsigned int iq_autocal_len; 205 unsigned int iq_autocal_len;
204 struct p54_cal_database *curve_data; 206 struct p54_cal_database *curve_data;
205 struct p54_cal_database *output_limit; 207 struct p54_cal_database *output_limit;
206 struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; 208 struct p54_cal_database *rssi_db;
207 struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; 209 struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS];
208 210
209 /* BBP/MAC state */ 211 /* BBP/MAC state */
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h
index d592cbd34d7..0b7bfb0adcf 100644
--- a/drivers/net/wireless/p54/p54spi_eeprom.h
+++ b/drivers/net/wireless/p54/p54spi_eeprom.h
@@ -65,9 +65,10 @@ static unsigned char p54spi_eeprom[] = {
650x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */ 650x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */
66 0x08, 0x08, 0x08, 0x08, 66 0x08, 0x08, 0x08, 0x08,
67 67
680x09, 0x00, 0xad, 0xde, /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */ 680x0a, 0x00, 0xff, 0xca, /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2 */
69 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 69 0x01, 0x00, 0x0a, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0x00, 0x00, 0x0a, 0x00,
71 0x85, 0x09, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
71 72
72/* struct pda_custom_wrapper */ 73/* struct pda_custom_wrapper */
730x10, 0x06, 0x5d, 0xb0, /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */ 740x10, 0x06, 0x5d, 0xb0, /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */
@@ -671,7 +672,7 @@ static unsigned char p54spi_eeprom[] = {
671 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, 672 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
672 673
6730x02, 0x00, 0x00, 0x00, /* PDR_END */ 6740x02, 0x00, 0x00, 0x00, /* PDR_END */
674 0x67, 0x99, 675 0xb6, 0x04,
675}; 676};
676 677
677#endif /* P54SPI_EEPROM_H */ 678#endif /* P54SPI_EEPROM_H */
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index f618b9623e5..917d5d948e3 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -273,11 +273,9 @@ void p54_tx(struct p54_common *priv, struct sk_buff *skb)
273 273
274static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) 274static int p54_rssi_to_dbm(struct p54_common *priv, int rssi)
275{ 275{
276 int band = priv->hw->conf.channel->band;
277
278 if (priv->rxhw != 5) { 276 if (priv->rxhw != 5) {
279 return ((rssi * priv->rssical_db[band].mul) / 64 + 277 return ((rssi * priv->cur_rssi->mul) / 64 +
280 priv->rssical_db[band].add) / 4; 278 priv->cur_rssi->add) / 4;
281 } else { 279 } else {
282 /* 280 /*
283 * TODO: find the correct formula 281 * TODO: find the correct formula