aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-12-09 12:30:14 -0500
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2010-12-13 18:52:11 -0500
commit8d6748ca73a0caffed4304a47a9cb4cd0aba361e (patch)
tree33d2a527a6fae850d199cb03d65455d3c8409d68
parente7362a0069f8448bb346d65f07d98b319f243e30 (diff)
iwlagn: implement layout-agnostic EEPROM reading
The current EEPROM reading code has some layout assumptions that now turned out to be false with some newer versions of the EEPROM. Luckily, we can avoid all such assumptions by using data in the EEPROM itself, so implement using that. However, for risk mitigation purposes, keep the old reading code for current hardware for now. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c85
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h15
6 files changed, 120 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 94521d4417a..5100c1065bd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -316,6 +316,7 @@ struct iwl_cfg iwl100_bgn_cfg = {
316 .ht_params = &iwl1000_ht_params, 316 .ht_params = &iwl1000_ht_params,
317 .led_mode = IWL_LED_RF_STATE, 317 .led_mode = IWL_LED_RF_STATE,
318 .rx_with_siso_diversity = true, 318 .rx_with_siso_diversity = true,
319 .use_new_eeprom_reading = true,
319}; 320};
320 321
321struct iwl_cfg iwl100_bg_cfg = { 322struct iwl_cfg iwl100_bg_cfg = {
@@ -330,6 +331,7 @@ struct iwl_cfg iwl100_bg_cfg = {
330 .base_params = &iwl1000_base_params, 331 .base_params = &iwl1000_base_params,
331 .led_mode = IWL_LED_RF_STATE, 332 .led_mode = IWL_LED_RF_STATE,
332 .rx_with_siso_diversity = true, 333 .rx_with_siso_diversity = true,
334 .use_new_eeprom_reading = true,
333}; 335};
334 336
335MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); 337MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 8a789241704..db70a6bfaa5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -568,6 +568,7 @@ struct iwl_cfg iwl6005_2agn_cfg = {
568 .need_dc_calib = true, 568 .need_dc_calib = true,
569 .need_temp_offset_calib = true, 569 .need_temp_offset_calib = true,
570 .led_mode = IWL_LED_RF_STATE, 570 .led_mode = IWL_LED_RF_STATE,
571 .use_new_eeprom_reading = true,
571}; 572};
572 573
573struct iwl_cfg iwl6005_2abg_cfg = { 574struct iwl_cfg iwl6005_2abg_cfg = {
@@ -583,6 +584,7 @@ struct iwl_cfg iwl6005_2abg_cfg = {
583 .need_dc_calib = true, 584 .need_dc_calib = true,
584 .need_temp_offset_calib = true, 585 .need_temp_offset_calib = true,
585 .led_mode = IWL_LED_RF_STATE, 586 .led_mode = IWL_LED_RF_STATE,
587 .use_new_eeprom_reading = true,
586}; 588};
587 589
588struct iwl_cfg iwl6005_2bg_cfg = { 590struct iwl_cfg iwl6005_2bg_cfg = {
@@ -598,6 +600,7 @@ struct iwl_cfg iwl6005_2bg_cfg = {
598 .need_dc_calib = true, 600 .need_dc_calib = true,
599 .need_temp_offset_calib = true, 601 .need_temp_offset_calib = true,
600 .led_mode = IWL_LED_RF_STATE, 602 .led_mode = IWL_LED_RF_STATE,
603 .use_new_eeprom_reading = true,
601}; 604};
602 605
603struct iwl_cfg iwl6030_2agn_cfg = { 606struct iwl_cfg iwl6030_2agn_cfg = {
@@ -618,6 +621,7 @@ struct iwl_cfg iwl6030_2agn_cfg = {
618 .adv_pm = true, 621 .adv_pm = true,
619 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 622 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
620 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 623 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
624 .use_new_eeprom_reading = true,
621}; 625};
622 626
623struct iwl_cfg iwl6030_2abg_cfg = { 627struct iwl_cfg iwl6030_2abg_cfg = {
@@ -637,6 +641,7 @@ struct iwl_cfg iwl6030_2abg_cfg = {
637 .adv_pm = true, 641 .adv_pm = true,
638 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 642 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
639 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 643 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
644 .use_new_eeprom_reading = true,
640}; 645};
641 646
642struct iwl_cfg iwl6030_2bgn_cfg = { 647struct iwl_cfg iwl6030_2bgn_cfg = {
@@ -657,6 +662,7 @@ struct iwl_cfg iwl6030_2bgn_cfg = {
657 .adv_pm = true, 662 .adv_pm = true,
658 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 663 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
659 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 664 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
665 .use_new_eeprom_reading = true,
660}; 666};
661 667
662struct iwl_cfg iwl6030_2bg_cfg = { 668struct iwl_cfg iwl6030_2bg_cfg = {
@@ -676,6 +682,7 @@ struct iwl_cfg iwl6030_2bg_cfg = {
676 .adv_pm = true, 682 .adv_pm = true,
677 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 683 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
678 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 684 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
685 .use_new_eeprom_reading = true,
679}; 686};
680 687
681struct iwl_cfg iwl1030_bgn_cfg = { 688struct iwl_cfg iwl1030_bgn_cfg = {
@@ -696,6 +703,7 @@ struct iwl_cfg iwl1030_bgn_cfg = {
696 .adv_pm = true, 703 .adv_pm = true,
697 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 704 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
698 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 705 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
706 .use_new_eeprom_reading = true,
699}; 707};
700 708
701struct iwl_cfg iwl1030_bg_cfg = { 709struct iwl_cfg iwl1030_bg_cfg = {
@@ -715,6 +723,7 @@ struct iwl_cfg iwl1030_bg_cfg = {
715 .adv_pm = true, 723 .adv_pm = true,
716 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 724 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
717 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 725 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
726 .use_new_eeprom_reading = true,
718}; 727};
719 728
720/* 729/*
@@ -797,6 +806,7 @@ struct iwl_cfg iwl6150_bgn_cfg = {
797 .ht_params = &iwl6000_ht_params, 806 .ht_params = &iwl6000_ht_params,
798 .need_dc_calib = true, 807 .need_dc_calib = true,
799 .led_mode = IWL_LED_RF_STATE, 808 .led_mode = IWL_LED_RF_STATE,
809 .use_new_eeprom_reading = true,
800}; 810};
801 811
802struct iwl_cfg iwl6050_2abg_cfg = { 812struct iwl_cfg iwl6050_2abg_cfg = {
@@ -846,6 +856,7 @@ struct iwl_cfg iwl130_bgn_cfg = {
846 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 856 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
847 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 857 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
848 .rx_with_siso_diversity = true, 858 .rx_with_siso_diversity = true,
859 .use_new_eeprom_reading = true,
849}; 860};
850 861
851struct iwl_cfg iwl130_bg_cfg = { 862struct iwl_cfg iwl130_bg_cfg = {
@@ -865,6 +876,7 @@ struct iwl_cfg iwl130_bg_cfg = {
865 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 876 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
866 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 877 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
867 .rx_with_siso_diversity = true, 878 .rx_with_siso_diversity = true,
879 .use_new_eeprom_reading = true,
868}; 880};
869 881
870MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); 882MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
index 7c1be8cc173..cf9194baada 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -433,7 +433,7 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
433/** 433/**
434 * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info 434 * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
435 */ 435 */
436void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) 436static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv)
437{ 437{
438 int eeprom_section_count = 0; 438 int eeprom_section_count = 0;
439 int section, element; 439 int section, element;
@@ -494,3 +494,86 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
494 } 494 }
495 } 495 }
496} 496}
497
498static void
499iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
500 struct iwl_eeprom_enhanced_txpwr *txp,
501 s8 max_txpower_avg)
502{
503 int ch_idx;
504 bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
505 enum ieee80211_band band;
506
507 band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
508 IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
509
510 for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
511 struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
512
513 /* update matching channel or from common data only */
514 if (txp->channel != 0 && ch_info->channel != txp->channel)
515 continue;
516
517 /* update matching band only */
518 if (band != ch_info->band)
519 continue;
520
521 if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
522 ch_info->max_power_avg = max_txpower_avg;
523 ch_info->curr_txpow = max_txpower_avg;
524 ch_info->scan_power = max_txpower_avg;
525 }
526
527 if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
528 ch_info->ht40_max_power_avg = max_txpower_avg;
529 }
530}
531
532#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
533#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
534#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
535
536static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
537{
538 struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
539 int idx, entries;
540 __le16 *txp_len;
541 s8 max_txp_avg, max_txp_avg_halfdbm;
542
543 BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
544
545 /* the length is in 16-bit words, but we want entries */
546 txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
547 entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
548
549 txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
550 for (idx = 0; idx < entries; idx++) {
551 txp = &txp_array[idx];
552
553 /* skip invalid entries */
554 if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
555 continue;
556
557 max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
558 &max_txp_avg_halfdbm);
559
560 /*
561 * Update the user limit values values to the highest
562 * power supported by any channel
563 */
564 if (max_txp_avg > priv->tx_power_user_lmt)
565 priv->tx_power_user_lmt = max_txp_avg;
566 if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
567 priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
568
569 iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
570 }
571}
572
573void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
574{
575 if (priv->cfg->use_new_eeprom_reading)
576 iwlcore_eeprom_enhanced_txpower_new(priv);
577 else
578 iwlcore_eeprom_enhanced_txpower_old(priv);
579}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index d941910e7ef..7c8010f7ce5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -568,6 +568,12 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
568 case INDIRECT_REGULATORY: 568 case INDIRECT_REGULATORY:
569 offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); 569 offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
570 break; 570 break;
571 case INDIRECT_TXP_LIMIT:
572 offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT);
573 break;
574 case INDIRECT_TXP_LIMIT_SIZE:
575 offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE);
576 break;
571 case INDIRECT_CALIBRATION: 577 case INDIRECT_CALIBRATION:
572 offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); 578 offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
573 break; 579 break;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index d0b86f5e28c..b877cbe12c3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -414,6 +414,7 @@ struct iwl_cfg {
414 enum iwl_led_mode led_mode; 414 enum iwl_led_mode led_mode;
415 const bool adv_pm; 415 const bool adv_pm;
416 const bool rx_with_siso_diversity; 416 const bool rx_with_siso_diversity;
417 const bool use_new_eeprom_reading; /* temporary, remove later */
417}; 418};
418 419
419/*************************** 420/***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index c8566a4f880..8994b5b2359 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -129,6 +129,17 @@ struct iwl_eeprom_channel {
129 s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ 129 s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
130} __packed; 130} __packed;
131 131
132enum iwl_eeprom_enhanced_txpwr_flags {
133 IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0),
134 IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1),
135 IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2),
136 IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3),
137 IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4),
138 IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5),
139 IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6),
140 IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7),
141};
142
132/** 143/**
133 * iwl_eeprom_enhanced_txpwr structure 144 * iwl_eeprom_enhanced_txpwr structure
134 * This structure presents the enhanced regulatory tx power limit layout 145 * This structure presents the enhanced regulatory tx power limit layout
@@ -197,6 +208,8 @@ struct iwl_eeprom_enhanced_txpwr {
197#define EEPROM_LINK_CALIBRATION (2*0x67) 208#define EEPROM_LINK_CALIBRATION (2*0x67)
198#define EEPROM_LINK_PROCESS_ADJST (2*0x68) 209#define EEPROM_LINK_PROCESS_ADJST (2*0x68)
199#define EEPROM_LINK_OTHERS (2*0x69) 210#define EEPROM_LINK_OTHERS (2*0x69)
211#define EEPROM_LINK_TXP_LIMIT (2*0x6a)
212#define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b)
200 213
201/* agn regulatory - indirect access */ 214/* agn regulatory - indirect access */
202#define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ 215#define EEPROM_REG_BAND_1_CHANNELS ((0x08)\
@@ -400,6 +413,8 @@ struct iwl_eeprom_calib_info {
400#define INDIRECT_CALIBRATION 0x00040000 413#define INDIRECT_CALIBRATION 0x00040000
401#define INDIRECT_PROCESS_ADJST 0x00050000 414#define INDIRECT_PROCESS_ADJST 0x00050000
402#define INDIRECT_OTHERS 0x00060000 415#define INDIRECT_OTHERS 0x00060000
416#define INDIRECT_TXP_LIMIT 0x00070000
417#define INDIRECT_TXP_LIMIT_SIZE 0x00080000
403#define INDIRECT_ADDRESS 0x00100000 418#define INDIRECT_ADDRESS 0x00100000
404 419
405/* General */ 420/* General */