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.c153
1 files changed, 111 insertions, 42 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index e14c9952a935..fb5bb487f3bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * GPL LICENSE SUMMARY 6 * GPL LICENSE SUMMARY
7 * 7 *
8 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. 8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as 11 * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
30 * 30 *
31 * BSD LICENSE 31 * BSD LICENSE
32 * 32 *
33 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. 33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
63 63
64#include <linux/kernel.h> 64#include <linux/kernel.h>
65#include <linux/module.h> 65#include <linux/module.h>
66#include <linux/slab.h>
66#include <linux/init.h> 67#include <linux/init.h>
67 68
68#include <net/mac80211.h> 69#include <net/mac80211.h>
@@ -215,12 +216,35 @@ static const struct iwl_txpwr_section enhinfo[] = {
215 216
216int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) 217int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
217{ 218{
218 u32 gp = iwl_read32(priv, CSR_EEPROM_GP); 219 u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
219 if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { 220 int ret = 0;
220 IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); 221
221 return -ENOENT; 222 IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp);
223 switch (gp) {
224 case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
225 if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) {
226 IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n",
227 gp);
228 ret = -ENOENT;
229 }
230 break;
231 case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
232 case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
233 if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) {
234 IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp);
235 ret = -ENOENT;
236 }
237 break;
238 case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP:
239 default:
240 IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, "
241 "EEPROM_GP=0x%08x\n",
242 (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
243 ? "OTP" : "EEPROM", gp);
244 ret = -ENOENT;
245 break;
222 } 246 }
223 return 0; 247 return ret;
224} 248}
225EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); 249EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
226 250
@@ -283,7 +307,8 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
283 CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); 307 CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
284 308
285 /* See if we got it */ 309 /* See if we got it */
286 ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG, 310 ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
311 CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
287 CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, 312 CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
288 EEPROM_SEM_TIMEOUT); 313 EEPROM_SEM_TIMEOUT);
289 if (ret >= 0) { 314 if (ret >= 0) {
@@ -322,7 +347,8 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
322 CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 347 CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
323 348
324 /* wait for clock to be ready */ 349 /* wait for clock to be ready */
325 ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, 350 ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
351 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
326 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 352 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
327 25000); 353 25000);
328 if (ret < 0) 354 if (ret < 0)
@@ -333,11 +359,19 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
333 udelay(5); 359 udelay(5);
334 iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, 360 iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
335 APMG_PS_CTRL_VAL_RESET_REQ); 361 APMG_PS_CTRL_VAL_RESET_REQ);
362
363 /*
364 * CSR auto clock gate disable bit -
365 * this is only applicable for HW with OTP shadow RAM
366 */
367 if (priv->cfg->shadow_ram_support)
368 iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG,
369 CSR_RESET_LINK_PWR_MGMT_DISABLED);
336 } 370 }
337 return ret; 371 return ret;
338} 372}
339 373
340static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) 374static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data)
341{ 375{
342 int ret = 0; 376 int ret = 0;
343 u32 r; 377 u32 r;
@@ -345,7 +379,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
345 379
346 _iwl_write32(priv, CSR_EEPROM_REG, 380 _iwl_write32(priv, CSR_EEPROM_REG,
347 CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); 381 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
348 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, 382 ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
383 CSR_EEPROM_REG_READ_VALID_MSK,
349 CSR_EEPROM_REG_READ_VALID_MSK, 384 CSR_EEPROM_REG_READ_VALID_MSK,
350 IWL_EEPROM_ACCESS_TIMEOUT); 385 IWL_EEPROM_ACCESS_TIMEOUT);
351 if (ret < 0) { 386 if (ret < 0) {
@@ -370,7 +405,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
370 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); 405 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
371 IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); 406 IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
372 } 407 }
373 *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); 408 *eeprom_data = cpu_to_le16(r >> 16);
374 return 0; 409 return 0;
375} 410}
376 411
@@ -379,7 +414,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
379 */ 414 */
380static bool iwl_is_otp_empty(struct iwl_priv *priv) 415static bool iwl_is_otp_empty(struct iwl_priv *priv)
381{ 416{
382 u16 next_link_addr = 0, link_value; 417 u16 next_link_addr = 0;
418 __le16 link_value;
383 bool is_empty = false; 419 bool is_empty = false;
384 420
385 /* locate the beginning of OTP link list */ 421 /* locate the beginning of OTP link list */
@@ -409,7 +445,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv)
409static int iwl_find_otp_image(struct iwl_priv *priv, 445static int iwl_find_otp_image(struct iwl_priv *priv,
410 u16 *validblockaddr) 446 u16 *validblockaddr)
411{ 447{
412 u16 next_link_addr = 0, link_value = 0, valid_addr; 448 u16 next_link_addr = 0, valid_addr;
449 __le16 link_value = 0;
413 int usedblocks = 0; 450 int usedblocks = 0;
414 451
415 /* set addressing mode to absolute to traverse the link list */ 452 /* set addressing mode to absolute to traverse the link list */
@@ -429,7 +466,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
429 * check for more block on the link list 466 * check for more block on the link list
430 */ 467 */
431 valid_addr = next_link_addr; 468 valid_addr = next_link_addr;
432 next_link_addr = link_value * sizeof(u16); 469 next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
433 IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", 470 IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
434 usedblocks, next_link_addr); 471 usedblocks, next_link_addr);
435 if (iwl_read_otp_word(priv, next_link_addr, &link_value)) 472 if (iwl_read_otp_word(priv, next_link_addr, &link_value))
@@ -463,7 +500,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
463 */ 500 */
464int iwl_eeprom_init(struct iwl_priv *priv) 501int iwl_eeprom_init(struct iwl_priv *priv)
465{ 502{
466 u16 *e; 503 __le16 *e;
467 u32 gp = iwl_read32(priv, CSR_EEPROM_GP); 504 u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
468 int sz; 505 int sz;
469 int ret; 506 int ret;
@@ -482,7 +519,9 @@ int iwl_eeprom_init(struct iwl_priv *priv)
482 ret = -ENOMEM; 519 ret = -ENOMEM;
483 goto alloc_err; 520 goto alloc_err;
484 } 521 }
485 e = (u16 *)priv->eeprom; 522 e = (__le16 *)priv->eeprom;
523
524 priv->cfg->ops->lib->apm_ops.init(priv);
486 525
487 ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); 526 ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
488 if (ret < 0) { 527 if (ret < 0) {
@@ -498,7 +537,9 @@ int iwl_eeprom_init(struct iwl_priv *priv)
498 ret = -ENOENT; 537 ret = -ENOENT;
499 goto err; 538 goto err;
500 } 539 }
540
501 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { 541 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
542
502 ret = iwl_init_otp_access(priv); 543 ret = iwl_init_otp_access(priv);
503 if (ret) { 544 if (ret) {
504 IWL_ERR(priv, "Failed to initialize OTP access.\n"); 545 IWL_ERR(priv, "Failed to initialize OTP access.\n");
@@ -521,7 +562,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
521 } 562 }
522 for (addr = validblockaddr; addr < validblockaddr + sz; 563 for (addr = validblockaddr; addr < validblockaddr + sz;
523 addr += sizeof(u16)) { 564 addr += sizeof(u16)) {
524 u16 eeprom_data; 565 __le16 eeprom_data;
525 566
526 ret = iwl_read_otp_word(priv, addr, &eeprom_data); 567 ret = iwl_read_otp_word(priv, addr, &eeprom_data);
527 if (ret) 568 if (ret)
@@ -537,7 +578,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
537 _iwl_write32(priv, CSR_EEPROM_REG, 578 _iwl_write32(priv, CSR_EEPROM_REG,
538 CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); 579 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
539 580
540 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, 581 ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
582 CSR_EEPROM_REG_READ_VALID_MSK,
541 CSR_EEPROM_REG_READ_VALID_MSK, 583 CSR_EEPROM_REG_READ_VALID_MSK,
542 IWL_EEPROM_ACCESS_TIMEOUT); 584 IWL_EEPROM_ACCESS_TIMEOUT);
543 if (ret < 0) { 585 if (ret < 0) {
@@ -545,7 +587,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
545 goto done; 587 goto done;
546 } 588 }
547 r = _iwl_read_direct32(priv, CSR_EEPROM_REG); 589 r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
548 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); 590 e[addr / 2] = cpu_to_le16(r >> 16);
549 } 591 }
550 } 592 }
551 ret = 0; 593 ret = 0;
@@ -554,6 +596,8 @@ done:
554err: 596err:
555 if (ret) 597 if (ret)
556 iwl_eeprom_free(priv); 598 iwl_eeprom_free(priv);
599 /* Reset chip to save power until we load uCode during "up". */
600 priv->cfg->ops->lib->apm_ops.stop(priv);
557alloc_err: 601alloc_err:
558 return ret; 602 return ret;
559} 603}
@@ -705,11 +749,9 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
705 749
706 ch_info->ht40_eeprom = *eeprom_ch; 750 ch_info->ht40_eeprom = *eeprom_ch;
707 ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; 751 ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
708 ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
709 ch_info->ht40_min_power = 0;
710 ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
711 ch_info->ht40_flags = eeprom_ch->flags; 752 ch_info->ht40_flags = eeprom_ch->flags;
712 ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; 753 if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
754 ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
713 755
714 return 0; 756 return 0;
715} 757}
@@ -719,7 +761,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
719 * find the highest tx power from all chains for the channel 761 * find the highest tx power from all chains for the channel
720 */ 762 */
721static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, 763static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
722 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element) 764 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
765 int element, s8 *max_txpower_in_half_dbm)
723{ 766{
724 s8 max_txpower_avg = 0; /* (dBm) */ 767 s8 max_txpower_avg = 0; /* (dBm) */
725 768
@@ -751,10 +794,14 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
751 (enhanced_txpower[element].mimo3_max > max_txpower_avg)) 794 (enhanced_txpower[element].mimo3_max > max_txpower_avg))
752 max_txpower_avg = enhanced_txpower[element].mimo3_max; 795 max_txpower_avg = enhanced_txpower[element].mimo3_max;
753 796
754 /* max. tx power in EEPROM is in 1/2 dBm format 797 /*
755 * convert from 1/2 dBm to dBm 798 * max. tx power in EEPROM is in 1/2 dBm format
799 * convert from 1/2 dBm to dBm (round-up convert)
800 * but we also do not want to loss 1/2 dBm resolution which
801 * will impact performance
756 */ 802 */
757 return max_txpower_avg >> 1; 803 *max_txpower_in_half_dbm = max_txpower_avg;
804 return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
758} 805}
759 806
760/** 807/**
@@ -763,7 +810,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
763 */ 810 */
764static s8 iwl_update_common_txpower(struct iwl_priv *priv, 811static s8 iwl_update_common_txpower(struct iwl_priv *priv,
765 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, 812 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
766 int section, int element) 813 int section, int element, s8 *max_txpower_in_half_dbm)
767{ 814{
768 struct iwl_channel_info *ch_info; 815 struct iwl_channel_info *ch_info;
769 int ch; 816 int ch;
@@ -777,25 +824,25 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
777 if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) 824 if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
778 is_ht40 = true; 825 is_ht40 = true;
779 max_txpower_avg = 826 max_txpower_avg =
780 iwl_get_max_txpower_avg(priv, enhanced_txpower, element); 827 iwl_get_max_txpower_avg(priv, enhanced_txpower,
828 element, max_txpower_in_half_dbm);
829
781 ch_info = priv->channel_info; 830 ch_info = priv->channel_info;
782 831
783 for (ch = 0; ch < priv->channel_count; ch++) { 832 for (ch = 0; ch < priv->channel_count; ch++) {
784 /* find matching band and update tx power if needed */ 833 /* find matching band and update tx power if needed */
785 if ((ch_info->band == enhinfo[section].band) && 834 if ((ch_info->band == enhinfo[section].band) &&
786 (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) { 835 (ch_info->max_power_avg < max_txpower_avg) &&
836 (!is_ht40)) {
787 /* Update regulatory-based run-time data */ 837 /* Update regulatory-based run-time data */
788 ch_info->max_power_avg = ch_info->curr_txpow = 838 ch_info->max_power_avg = ch_info->curr_txpow =
789 max_txpower_avg; 839 max_txpower_avg;
790 ch_info->scan_power = max_txpower_avg; 840 ch_info->scan_power = max_txpower_avg;
791 } 841 }
792 if ((ch_info->band == enhinfo[section].band) && is_ht40 && 842 if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
793 ch_info->ht40_max_power_avg &&
794 (ch_info->ht40_max_power_avg < max_txpower_avg)) { 843 (ch_info->ht40_max_power_avg < max_txpower_avg)) {
795 /* Update regulatory-based run-time data */ 844 /* Update regulatory-based run-time data */
796 ch_info->ht40_max_power_avg = max_txpower_avg; 845 ch_info->ht40_max_power_avg = max_txpower_avg;
797 ch_info->ht40_curr_txpow = max_txpower_avg;
798 ch_info->ht40_scan_power = max_txpower_avg;
799 } 846 }
800 ch_info++; 847 ch_info++;
801 } 848 }
@@ -808,7 +855,7 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
808 */ 855 */
809static s8 iwl_update_channel_txpower(struct iwl_priv *priv, 856static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
810 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, 857 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
811 int section, int element) 858 int section, int element, s8 *max_txpower_in_half_dbm)
812{ 859{
813 struct iwl_channel_info *ch_info; 860 struct iwl_channel_info *ch_info;
814 int ch; 861 int ch;
@@ -817,7 +864,8 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
817 864
818 channel = enhinfo[section].iwl_eeprom_section_channel[element]; 865 channel = enhinfo[section].iwl_eeprom_section_channel[element];
819 max_txpower_avg = 866 max_txpower_avg =
820 iwl_get_max_txpower_avg(priv, enhanced_txpower, element); 867 iwl_get_max_txpower_avg(priv, enhanced_txpower,
868 element, max_txpower_in_half_dbm);
821 869
822 ch_info = priv->channel_info; 870 ch_info = priv->channel_info;
823 for (ch = 0; ch < priv->channel_count; ch++) { 871 for (ch = 0; ch < priv->channel_count; ch++) {
@@ -831,12 +879,9 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
831 ch_info->scan_power = max_txpower_avg; 879 ch_info->scan_power = max_txpower_avg;
832 } 880 }
833 if ((enhinfo[section].is_ht40) && 881 if ((enhinfo[section].is_ht40) &&
834 (ch_info->ht40_max_power_avg) &&
835 (ch_info->ht40_max_power_avg < max_txpower_avg)) { 882 (ch_info->ht40_max_power_avg < max_txpower_avg)) {
836 /* Update regulatory-based run-time data */ 883 /* Update regulatory-based run-time data */
837 ch_info->ht40_max_power_avg = max_txpower_avg; 884 ch_info->ht40_max_power_avg = max_txpower_avg;
838 ch_info->ht40_curr_txpow = max_txpower_avg;
839 ch_info->ht40_scan_power = max_txpower_avg;
840 } 885 }
841 break; 886 break;
842 } 887 }
@@ -855,6 +900,7 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
855 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; 900 struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
856 u32 offset; 901 u32 offset;
857 s8 max_txpower_avg; /* (dBm) */ 902 s8 max_txpower_avg; /* (dBm) */
903 s8 max_txpower_in_half_dbm; /* (half-dBm) */
858 904
859 /* Loop through all the sections 905 /* Loop through all the sections
860 * adjust bands and channel's max tx power 906 * adjust bands and channel's max tx power
@@ -867,20 +913,43 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
867 enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) 913 enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
868 iwl_eeprom_query_addr(priv, offset); 914 iwl_eeprom_query_addr(priv, offset);
869 915
916 /*
917 * check for valid entry -
918 * different version of EEPROM might contain different set
919 * of enhanced tx power table
920 * always check for valid entry before process
921 * the information
922 */
923 if (!enhanced_txpower->common || enhanced_txpower->reserved)
924 continue;
925
870 for (element = 0; element < eeprom_section_count; element++) { 926 for (element = 0; element < eeprom_section_count; element++) {
871 if (enhinfo[section].is_common) 927 if (enhinfo[section].is_common)
872 max_txpower_avg = 928 max_txpower_avg =
873 iwl_update_common_txpower(priv, 929 iwl_update_common_txpower(priv,
874 enhanced_txpower, section, element); 930 enhanced_txpower, section,
931 element,
932 &max_txpower_in_half_dbm);
875 else 933 else
876 max_txpower_avg = 934 max_txpower_avg =
877 iwl_update_channel_txpower(priv, 935 iwl_update_channel_txpower(priv,
878 enhanced_txpower, section, element); 936 enhanced_txpower, section,
937 element,
938 &max_txpower_in_half_dbm);
879 939
880 /* Update the tx_power_user_lmt to the highest power 940 /* Update the tx_power_user_lmt to the highest power
881 * supported by any channel */ 941 * supported by any channel */
882 if (max_txpower_avg > priv->tx_power_user_lmt) 942 if (max_txpower_avg > priv->tx_power_user_lmt)
883 priv->tx_power_user_lmt = max_txpower_avg; 943 priv->tx_power_user_lmt = max_txpower_avg;
944
945 /*
946 * Update the tx_power_lmt_in_half_dbm to
947 * the highest power supported by any channel
948 */
949 if (max_txpower_in_half_dbm >
950 priv->tx_power_lmt_in_half_dbm)
951 priv->tx_power_lmt_in_half_dbm =
952 max_txpower_in_half_dbm;
884 } 953 }
885 } 954 }
886} 955}