diff options
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r-- | drivers/net/wireless/p54/eeprom.c | 208 | ||||
-rw-r--r-- | drivers/net/wireless/p54/eeprom.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/p54/fwio.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/p54/lmac.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/p54/main.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54spi_eeprom.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/p54/txrx.c | 6 |
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 | ||
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 | |||
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 | ||
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 | |||
90 | static int p54_compare_channels(const void *_a, | 106 | static 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 | |||
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; | ||
97 | } | 122 | } |
98 | 123 | ||
99 | static int p54_fill_band_bitrates(struct ieee80211_hw *dev, | 124 | static 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, | |||
410 | static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2", | 436 | static 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 | ||
413 | static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, | 439 | static 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); | 514 | err_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 | |||
525 | struct 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 | ||
442 | static void p54_parse_default_country(struct ieee80211_hw *dev, | 553 | static 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 | ||
84 | struct pda_rssi_cal_ext_entry { | ||
85 | __le16 freq; | ||
86 | __le16 mul; | ||
87 | __le16 add; | ||
88 | } __packed; | ||
89 | |||
84 | struct pda_rssi_cal_entry { | 90 | struct 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 | ||
528 | err: | 530 | err: |
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 */ |
552 | int p54_download_eeprom(struct p54_common *priv, void *buf, | 552 | int p54_download_eeprom(struct p54_common *priv, void *buf, |
553 | u16 offset, u16 len); | 553 | u16 offset, u16 len); |
554 | struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *p, const u16 freq); | ||
554 | 555 | ||
555 | /* utility */ | 556 | /* utility */ |
556 | u8 *p54_find_ie(struct sk_buff *skb, u8 ie); | 557 | u8 *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 | ||
527 | static 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 | |||
543 | static 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 | |||
527 | static const struct ieee80211_ops p54_ops = { | 569 | static 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 | ||
612 | int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) | 655 | int 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 | ||
119 | struct p54_rssi_linear_approximation { | 119 | struct 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[] = { | |||
65 | 0x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */ | 65 | 0x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */ |
66 | 0x08, 0x08, 0x08, 0x08, | 66 | 0x08, 0x08, 0x08, 0x08, |
67 | 67 | ||
68 | 0x09, 0x00, 0xad, 0xde, /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */ | 68 | 0x0a, 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 */ |
73 | 0x10, 0x06, 0x5d, 0xb0, /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */ | 74 | 0x10, 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 | ||
673 | 0x02, 0x00, 0x00, 0x00, /* PDR_END */ | 674 | 0x02, 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 | ||
274 | static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) | 274 | static 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 |