summaryrefslogtreecommitdiff
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 8a0709e81a9..3946e5c03f8 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)
}
e = (u16 *)priv->eeprom;
+ if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
+ /* OTP reads require powered-up chip */
+ priv->cfg->ops->lib->apm_ops.init(priv);
+ }
+
ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
if (ret < 0) {
IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
@@ -532,10 +537,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
ret = -ENOENT;
goto err;
}
- if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
- /* OTP reads require powered-up chip */
- priv->cfg->ops->lib->apm_ops.init(priv);
+ if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
ret = iwl_init_otp_access(priv);
if (ret) {
@@ -751,9 +754,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
ch_info->ht40_eeprom = *eeprom_ch;
ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
- ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
- ch_info->ht40_min_power = 0;
- ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
ch_info->ht40_flags = eeprom_ch->flags;
ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
@@ -765,7 +765,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
* find the highest tx power from all chains for the channel
*/
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element)
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int element, s8 *max_txpower_in_half_dbm)
{
s8 max_txpower_avg = 0; /* (dBm) */
@@ -797,10 +798,14 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
max_txpower_avg = enhanced_txpower[element].mimo3_max;
- /* max. tx power in EEPROM is in 1/2 dBm format
- * convert from 1/2 dBm to dBm
+ /*
+ * max. tx power in EEPROM is in 1/2 dBm format
+ * convert from 1/2 dBm to dBm (round-up convert)
+ * but we also do not want to loss 1/2 dBm resolution which
+ * will impact performance
*/
- return max_txpower_avg >> 1;
+ *max_txpower_in_half_dbm = max_txpower_avg;
+ return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
}
/**
@@ -809,7 +814,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
*/
static s8 iwl_update_common_txpower(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int section, int element)
+ int section, int element, s8 *max_txpower_in_half_dbm)
{
struct iwl_channel_info *ch_info;
int ch;
@@ -823,25 +828,25 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
is_ht40 = true;
max_txpower_avg =
- iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
+ iwl_get_max_txpower_avg(priv, enhanced_txpower,
+ element, max_txpower_in_half_dbm);
+
ch_info = priv->channel_info;
for (ch = 0; ch < priv->channel_count; ch++) {
/* find matching band and update tx power if needed */
if ((ch_info->band == enhinfo[section].band) &&
- (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) {
+ (ch_info->max_power_avg < max_txpower_avg) &&
+ (!is_ht40)) {
/* Update regulatory-based run-time data */
ch_info->max_power_avg = ch_info->curr_txpow =
- max_txpower_avg;
+ max_txpower_avg;
ch_info->scan_power = max_txpower_avg;
}
if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
- ch_info->ht40_max_power_avg &&
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
/* Update regulatory-based run-time data */
ch_info->ht40_max_power_avg = max_txpower_avg;
- ch_info->ht40_curr_txpow = max_txpower_avg;
- ch_info->ht40_scan_power = max_txpower_avg;
}
ch_info++;
}
@@ -854,7 +859,7 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv,
*/
static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int section, int element)
+ int section, int element, s8 *max_txpower_in_half_dbm)
{
struct iwl_channel_info *ch_info;
int ch;
@@ -863,7 +868,8 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
channel = enhinfo[section].iwl_eeprom_section_channel[element];
max_txpower_avg =
- iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
+ iwl_get_max_txpower_avg(priv, enhanced_txpower,
+ element, max_txpower_in_half_dbm);
ch_info = priv->channel_info;
for (ch = 0; ch < priv->channel_count; ch++) {
@@ -877,12 +883,9 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
ch_info->scan_power = max_txpower_avg;
}
if ((enhinfo[section].is_ht40) &&
- (ch_info->ht40_max_power_avg) &&
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
/* Update regulatory-based run-time data */
ch_info->ht40_max_power_avg = max_txpower_avg;
- ch_info->ht40_curr_txpow = max_txpower_avg;
- ch_info->ht40_scan_power = max_txpower_avg;
}
break;
}
@@ -901,6 +904,7 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
u32 offset;
s8 max_txpower_avg; /* (dBm) */
+ s8 max_txpower_in_half_dbm; /* (half-dBm) */
/* Loop through all the sections
* adjust bands and channel's max tx power
@@ -913,20 +917,43 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
iwl_eeprom_query_addr(priv, offset);
+ /*
+ * check for valid entry -
+ * different version of EEPROM might contain different set
+ * of enhanced tx power table
+ * always check for valid entry before process
+ * the information
+ */
+ if (!enhanced_txpower->common || enhanced_txpower->reserved)
+ continue;
+
for (element = 0; element < eeprom_section_count; element++) {
if (enhinfo[section].is_common)
max_txpower_avg =
iwl_update_common_txpower(priv,
- enhanced_txpower, section, element);
+ enhanced_txpower, section,
+ element,
+ &max_txpower_in_half_dbm);
else
max_txpower_avg =
iwl_update_channel_txpower(priv,
- enhanced_txpower, section, element);
+ enhanced_txpower, section,
+ element,
+ &max_txpower_in_half_dbm);
/* Update the tx_power_user_lmt to the highest power
* supported by any channel */
if (max_txpower_avg > priv->tx_power_user_lmt)
priv->tx_power_user_lmt = max_txpower_avg;
+
+ /*
+ * Update the tx_power_lmt_in_half_dbm to
+ * the highest power supported by any channel
+ */
+ if (max_txpower_in_half_dbm >
+ priv->tx_power_lmt_in_half_dbm)
+ priv->tx_power_lmt_in_half_dbm =
+ max_txpower_in_half_dbm;
}
}
}