aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-eeprom.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 8a0709e81a9f..3946e5c03f81 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -518,6 +518,11 @@ int iwl_eeprom_init(struct iwl_priv *priv)
518 } 518 }
519 e = (u16 *)priv->eeprom; 519 e = (u16 *)priv->eeprom;
520 520
521 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
522 /* OTP reads require powered-up chip */
523 priv->cfg->ops->lib->apm_ops.init(priv);
524 }
525
521 ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); 526 ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
522 if (ret < 0) { 527 if (ret < 0) {
523 IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); 528 IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
@@ -532,10 +537,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
532 ret = -ENOENT; 537 ret = -ENOENT;
533 goto err; 538 goto err;
534 } 539 }
535 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
536 540
537 /* OTP reads require powered-up chip */ 541 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
538 priv->cfg->ops->lib->apm_ops.init(priv);
539 542
540 ret = iwl_init_otp_access(priv); 543 ret = iwl_init_otp_access(priv);
541 if (ret) { 544 if (ret) {
@@ -751,9 +754,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
751 754
752 ch_info->ht40_eeprom = *eeprom_ch; 755 ch_info->ht40_eeprom = *eeprom_ch;
753 ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; 756 ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
754 ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
755 ch_info->ht40_min_power = 0;
756 ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
757 ch_info->ht40_flags = eeprom_ch->flags; 757 ch_info->ht40_flags = eeprom_ch->flags;
758 ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; 758 ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
759 759
@@ -765,7 +765,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
765 * find the highest tx power from all chains for the channel 765 * find the highest tx power from all chains for the channel
766 */ 766 */
767static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, 767static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
768 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element) 768 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
769 int element, s8 *max_txpower_in_half_dbm)
769{ 770{
770 s8 max_txpower_avg = 0; /* (dBm) */ 771 s8 max_txpower_avg = 0; /* (dBm) */
771 772
@@ -797,10 +798,14 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
797 (enhanced_txpower[element].mimo3_max > max_txpower_avg)) 798 (enhanced_txpower[element].mimo3_max > max_txpower_avg))
798 max_txpower_avg = enhanced_txpower[element].mimo3_max; 799 max_txpower_avg = enhanced_txpower[element].mimo3_max;
799 800
800 /* max. tx power in EEPROM is in 1/2 dBm format 801 /*
801 * convert from 1/2 dBm to dBm 802 * max. tx power in EEPROM is in 1/2 dBm format
803 * convert from 1/2 dBm to dBm (round-up convert)
804 * but we also do not want to loss 1/2 dBm resolution which
805 * will impact performance
802 */ 806 */
803 return max_txpower_avg >> 1; 807 *max_txpower_in_half_dbm = max_txpower_avg;
808 return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
804} 809}
805 810
806/** 811/**
@@ -809,7 +814,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
809 */ 814 */
810static s8 iwl_update_common_txpower(struct iwl_priv *priv, 815static s8 iwl_update_common_txpower(struct iwl_priv *priv,
811 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, 816 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
812 int section, int element) 817 int section, int element, s8 *max_txpower_in_half_dbm)
813{ 818{
814 struct iwl_channel_info *ch_info; 819 struct iwl_channel_info *ch_info;
815 int ch; 820 int ch;
@@ -823,25 +828,25 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
823 if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) 828 if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
824 is_ht40 = true; 829 is_ht40 = true;
825 max_txpower_avg = 830 max_txpower_avg =
826 iwl_get_max_txpower_avg(priv, enhanced_txpower, element); 831 iwl_get_max_txpower_avg(priv, enhanced_txpower,
832 element, max_txpower_in_half_dbm);
833
827 ch_info = priv->channel_info; 834 ch_info = priv->channel_info;
828 835
829 for (ch = 0; ch < priv->channel_count; ch++) { 836 for (ch = 0; ch < priv->channel_count; ch++) {
830 /* find matching band and update tx power if needed */ 837 /* find matching band and update tx power if needed */
831 if ((ch_info->band == enhinfo[section].band) && 838 if ((ch_info->band == enhinfo[section].band) &&
832 (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) { 839 (ch_info->max_power_avg < max_txpower_avg) &&
840 (!is_ht40)) {
833 /* Update regulatory-based run-time data */ 841 /* Update regulatory-based run-time data */
834 ch_info->max_power_avg = ch_info->curr_txpow = 842 ch_info->max_power_avg = ch_info->curr_txpow =
835 max_txpower_avg; 843 max_txpower_avg;
836 ch_info->scan_power = max_txpower_avg; 844 ch_info->scan_power = max_txpower_avg;
837 } 845 }
838 if ((ch_info->band == enhinfo[section].band) && is_ht40 && 846 if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
839 ch_info->ht40_max_power_avg &&
840 (ch_info->ht40_max_power_avg < max_txpower_avg)) { 847 (ch_info->ht40_max_power_avg < max_txpower_avg)) {
841 /* Update regulatory-based run-time data */ 848 /* Update regulatory-based run-time data */
842 ch_info->ht40_max_power_avg = max_txpower_avg; 849 ch_info->ht40_max_power_avg = max_txpower_avg;
843 ch_info->ht40_curr_txpow = max_txpower_avg;
844 ch_info->ht40_scan_power = max_txpower_avg;
845 } 850 }
846 ch_info++; 851 ch_info++;
847 } 852 }
@@ -854,7 +859,7 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
854 */ 859 */
855static s8 iwl_update_channel_txpower(struct iwl_priv *priv, 860static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
856 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, 861 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
857 int section, int element) 862 int section, int element, s8 *max_txpower_in_half_dbm)
858{ 863{
859 struct iwl_channel_info *ch_info; 864 struct iwl_channel_info *ch_info;
860 int ch; 865 int ch;
@@ -863,7 +868,8 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
863 868
864 channel = enhinfo[section].iwl_eeprom_section_channel[element]; 869 channel = enhinfo[section].iwl_eeprom_section_channel[element];
865 max_txpower_avg = 870 max_txpower_avg =
866 iwl_get_max_txpower_avg(priv, enhanced_txpower, element); 871 iwl_get_max_txpower_avg(priv, enhanced_txpower,
872 element, max_txpower_in_half_dbm);
867 873
868 ch_info = priv->channel_info; 874 ch_info = priv->channel_info;
869 for (ch = 0; ch < priv->channel_count; ch++) { 875 for (ch = 0; ch < priv->channel_count; ch++) {
@@ -877,12 +883,9 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
877 ch_info->scan_power = max_txpower_avg; 883 ch_info->scan_power = max_txpower_avg;
878 } 884 }
879 if ((enhinfo[section].is_ht40) && 885 if ((enhinfo[section].is_ht40) &&
880 (ch_info->ht40_max_power_avg) &&
881 (ch_info->ht40_max_power_avg < max_txpower_avg)) { 886 (ch_info->ht40_max_power_avg < max_txpower_avg)) {
882 /* Update regulatory-based run-time data */ 887 /* Update regulatory-based run-time data */
883 ch_info->ht40_max_power_avg = max_txpower_avg; 888 ch_info->ht40_max_power_avg = max_txpower_avg;
884 ch_info->ht40_curr_txpow = max_txpower_avg;
885 ch_info->ht40_scan_power = max_txpower_avg;
886 } 889 }
887 break; 890 break;
888 } 891 }
@@ -901,6 +904,7 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
901 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; 904 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
902 u32 offset; 905 u32 offset;
903 s8 max_txpower_avg; /* (dBm) */ 906 s8 max_txpower_avg; /* (dBm) */
907 s8 max_txpower_in_half_dbm; /* (half-dBm) */
904 908
905 /* Loop through all the sections 909 /* Loop through all the sections
906 * adjust bands and channel's max tx power 910 * adjust bands and channel's max tx power
@@ -913,20 +917,43 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
913 enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) 917 enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
914 iwl_eeprom_query_addr(priv, offset); 918 iwl_eeprom_query_addr(priv, offset);
915 919
920 /*
921 * check for valid entry -
922 * different version of EEPROM might contain different set
923 * of enhanced tx power table
924 * always check for valid entry before process
925 * the information
926 */
927 if (!enhanced_txpower->common || enhanced_txpower->reserved)
928 continue;
929
916 for (element = 0; element < eeprom_section_count; element++) { 930 for (element = 0; element < eeprom_section_count; element++) {
917 if (enhinfo[section].is_common) 931 if (enhinfo[section].is_common)
918 max_txpower_avg = 932 max_txpower_avg =
919 iwl_update_common_txpower(priv, 933 iwl_update_common_txpower(priv,
920 enhanced_txpower, section, element); 934 enhanced_txpower, section,
935 element,
936 &max_txpower_in_half_dbm);
921 else 937 else
922 max_txpower_avg = 938 max_txpower_avg =
923 iwl_update_channel_txpower(priv, 939 iwl_update_channel_txpower(priv,
924 enhanced_txpower, section, element); 940 enhanced_txpower, section,
941 element,
942 &max_txpower_in_half_dbm);
925 943
926 /* Update the tx_power_user_lmt to the highest power 944 /* Update the tx_power_user_lmt to the highest power
927 * supported by any channel */ 945 * supported by any channel */
928 if (max_txpower_avg > priv->tx_power_user_lmt) 946 if (max_txpower_avg > priv->tx_power_user_lmt)
929 priv->tx_power_user_lmt = max_txpower_avg; 947 priv->tx_power_user_lmt = max_txpower_avg;
948
949 /*
950 * Update the tx_power_lmt_in_half_dbm to
951 * the highest power supported by any channel
952 */
953 if (max_txpower_in_half_dbm >
954 priv->tx_power_lmt_in_half_dbm)
955 priv->tx_power_lmt_in_half_dbm =
956 max_txpower_in_half_dbm;
930 } 957 }
931 } 958 }
932} 959}