summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c115
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c162
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c55
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c109
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c62
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h49
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c47
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c51
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c154
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c139
34 files changed, 743 insertions, 620 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index cf1449df4f0..2f56b343e86 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -125,7 +125,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -172,11 +171,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl1000_nic_config,
- },
+ .nic_config = iwl1000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -187,16 +182,12 @@ static struct iwl_lib_ops iwl1000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
+ .temperature = iwlagn_temperature,
};
static const struct iwl_ops iwl1000_ops = {
.lib = &iwl1000_lib,
- .utils = &iwlagn_hcmd_utils,
};
static struct iwl_base_params iwl1000_base_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index a401113c065..32ac8654b79 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -123,7 +123,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -169,14 +168,31 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
static struct iwl_lib_ops iwl2000_lib = {
.set_hw_params = iwl2000_hw_set_hw_params,
.rx_handler_setup = iwlagn_rx_handler_setup,
+ .setup_deferred_work = iwlagn_setup_deferred_work,
+ .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
+ .nic_config = iwl2000_nic_config,
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_REG_BAND_1_CHANNELS,
+ EEPROM_REG_BAND_2_CHANNELS,
+ EEPROM_REG_BAND_3_CHANNELS,
+ EEPROM_REG_BAND_4_CHANNELS,
+ EEPROM_REG_BAND_5_CHANNELS,
+ EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_REGULATORY_BAND_NO_HT40,
+ },
+ .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ },
+ .temperature = iwlagn_temperature,
+};
+
+static struct iwl_lib_ops iwl2030_lib = {
+ .set_hw_params = iwl2000_hw_set_hw_params,
+ .rx_handler_setup = iwlagn_bt_rx_handler_setup,
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl2000_nic_config,
- },
+ .nic_config = iwl2000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -187,32 +203,25 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
+ .temperature = iwlagn_temperature,
};
static const struct iwl_ops iwl2000_ops = {
.lib = &iwl2000_lib,
- .utils = &iwlagn_hcmd_utils,
};
static const struct iwl_ops iwl2030_ops = {
- .lib = &iwl2000_lib,
- .utils = &iwlagn_hcmd_utils,
+ .lib = &iwl2030_lib,
};
static const struct iwl_ops iwl105_ops = {
.lib = &iwl2000_lib,
- .utils = &iwlagn_hcmd_utils,
};
static const struct iwl_ops iwl135_ops = {
- .lib = &iwl2000_lib,
- .utils = &iwlagn_hcmd_utils,
+ .lib = &iwl2030_lib,
};
static struct iwl_base_params iwl2000_base_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index c55cec853f5..556489302da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -46,6 +46,7 @@
#include "iwl-agn.h"
#include "iwl-agn-hw.h"
#include "iwl-5000-hw.h"
+#include "iwl-trans.h"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5
@@ -156,7 +157,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -200,7 +200,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -316,7 +315,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_send_cmd_sync(priv, &hcmd);
+ return trans_send_cmd(priv, &hcmd);
}
static struct iwl_lib_ops iwl5000_lib = {
@@ -324,12 +323,8 @@ static struct iwl_lib_ops iwl5000_lib = {
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl5000_nic_config,
- },
+ .nic_config = iwl5000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -340,11 +335,8 @@ static struct iwl_lib_ops iwl5000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
+ .temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl5150_lib = {
@@ -352,12 +344,8 @@ static struct iwl_lib_ops iwl5150_lib = {
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl5000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl5000_nic_config,
- },
+ .nic_config = iwl5000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -368,21 +356,16 @@ static struct iwl_lib_ops iwl5150_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
},
- .temp_ops = {
- .temperature = iwl5150_temperature,
- },
+ .temperature = iwl5150_temperature,
};
static const struct iwl_ops iwl5000_ops = {
.lib = &iwl5000_lib,
- .utils = &iwlagn_hcmd_utils,
};
static const struct iwl_ops iwl5150_ops = {
.lib = &iwl5150_lib,
- .utils = &iwlagn_hcmd_utils,
};
static struct iwl_base_params iwl5000_base_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 965d010794b..80f1ef61a3d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -45,6 +45,7 @@
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-6000-hw.h"
+#include "iwl-trans.h"
/* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4
@@ -144,7 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
iwlagn_mod_params.num_of_queues;
priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
- priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
@@ -255,7 +255,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT;
}
- return iwl_send_cmd_sync(priv, &hcmd);
+ return trans_send_cmd(priv, &hcmd);
}
static struct iwl_lib_ops iwl6000_lib = {
@@ -263,12 +263,8 @@ static struct iwl_lib_ops iwl6000_lib = {
.rx_handler_setup = iwlagn_rx_handler_setup,
.setup_deferred_work = iwlagn_setup_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl6000_nic_config,
- },
+ .nic_config = iwl6000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -279,12 +275,9 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
+ .temperature = iwlagn_temperature,
};
static struct iwl_lib_ops iwl6030_lib = {
@@ -293,12 +286,8 @@ static struct iwl_lib_ops iwl6030_lib = {
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
- .update_chain_flags = iwl_update_chain_flags,
.set_channel_switch = iwl6000_hw_channel_switch,
- .apm_ops = {
- .init = iwl_apm_init,
- .config = iwl6000_nic_config,
- },
+ .nic_config = iwl6000_nic_config,
.eeprom_ops = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@@ -309,12 +298,9 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .query_addr = iwlagn_eeprom_query_addr,
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
- .temp_ops = {
- .temperature = iwlagn_temperature,
- },
+ .temperature = iwlagn_temperature,
};
static struct iwl_nic_ops iwl6050_nic_ops = {
@@ -327,24 +313,20 @@ static struct iwl_nic_ops iwl6150_nic_ops = {
static const struct iwl_ops iwl6000_ops = {
.lib = &iwl6000_lib,
- .utils = &iwlagn_hcmd_utils,
};
static const struct iwl_ops iwl6050_ops = {
.lib = &iwl6000_lib,
- .utils = &iwlagn_hcmd_utils,
.nic = &iwl6050_nic_ops,
};
static const struct iwl_ops iwl6150_ops = {
.lib = &iwl6000_lib,
- .utils = &iwlagn_hcmd_utils,
.nic = &iwl6150_nic_ops,
};
static const struct iwl_ops iwl6030_ops = {
.lib = &iwl6030_lib,
- .utils = &iwlagn_hcmd_utils,
};
static struct iwl_base_params iwl6000_base_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c9255def108..02c7c65ee86 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -66,6 +66,8 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-agn-calib.h"
+#include "iwl-trans.h"
+#include "iwl-agn.h"
/*****************************************************************************
* INIT calibrations framework
@@ -87,6 +89,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
+ .flags = CMD_SYNC,
};
for (i = 0; i < IWL_CALIB_MAX; i++) {
@@ -95,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
hcmd.len[0] = priv->calib_results[i].buf_len;
hcmd.data[0] = priv->calib_results[i].buf;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
- ret = iwl_send_cmd_sync(priv, &hcmd);
+ ret = trans_send_cmd(priv, &hcmd);
if (ret) {
IWL_ERR(priv, "Error %d iteration %d\n",
ret, i);
@@ -481,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE);
- return iwl_send_cmd(priv, &cmd_out);
+ return trans_send_cmd(priv, &cmd_out);
}
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -545,7 +548,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
- return iwl_send_cmd(priv, &cmd_out);
+ return trans_send_cmd(priv, &cmd_out);
}
void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -991,16 +994,14 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
min_average_noise, min_average_noise_antenna_i);
- if (priv->cfg->ops->utils->gain_computation)
- priv->cfg->ops->utils->gain_computation(priv, average_noise,
+ iwlagn_gain_computation(priv, average_noise,
min_average_noise_antenna_i, min_average_noise,
find_first_chain(priv->cfg->valid_rx_ant));
/* Some power changes may have been made during the calibration.
* Update and commit the RXON
*/
- if (priv->cfg->ops->lib->update_chain_flags)
- priv->cfg->ops->lib->update_chain_flags(priv);
+ iwl_update_chain_flags(priv);
data->state = IWL_CHAIN_NOISE_DONE;
iwl_power_update_mode(priv, false);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
index 4ef4dd93425..a869fc9205d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
@@ -71,13 +71,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
-static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-{
-
- if (!priv->disable_chain_noise_cal &&
- priv->cfg->ops->utils->chain_noise_reset)
- priv->cfg->ops->utils->chain_noise_reset(priv);
-}
int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
index 7745816eaff..b8347db850e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -150,7 +150,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
{
- const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+ const u8 *addr = iwl_eeprom_query_addr(priv,
EEPROM_MAC_ADDRESS);
memcpy(mac, addr, ETH_ALEN);
}
@@ -245,10 +245,10 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
- txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+ txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
- txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+ txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index ce7d4b56d9b..f0f5f5eada7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -36,6 +36,7 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-agn.h"
+#include "iwl-trans.h"
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
{
@@ -45,7 +46,9 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
if (IWL_UCODE_API(priv->ucode_ver) > 1) {
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
- return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD,
+ return trans_send_cmd_pdu(priv,
+ TX_ANT_CONFIGURATION_CMD,
+ CMD_SYNC,
sizeof(struct iwl_tx_ant_config_cmd),
&tx_ant_cmd);
} else {
@@ -54,17 +57,7 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
}
}
-static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
- u16 size = (u16)sizeof(struct iwl_addsta_cmd);
- struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
- memcpy(addsta, cmd, size);
- /* resrved in 5000 */
- addsta->rate_n_flags = cpu_to_le16(0);
- return size;
-}
-
-static void iwlagn_gain_computation(struct iwl_priv *priv,
+void iwlagn_gain_computation(struct iwl_priv *priv,
u32 average_noise[NUM_RX_CHAINS],
u16 min_average_noise_antenna_i,
u32 min_average_noise,
@@ -115,96 +108,14 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
priv->_agn.phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2];
- iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd, NULL);
+ trans_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ CMD_ASYNC, sizeof(cmd), &cmd);
data->radio_write = 1;
data->state = IWL_CHAIN_NOISE_CALIBRATED;
}
}
-static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
-{
- struct iwl_chain_noise_data *data = &priv->chain_noise_data;
- int ret;
-
- if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
- iwl_is_any_associated(priv)) {
- struct iwl_calib_chain_noise_reset_cmd cmd;
-
- /* clear data for chain noise calibration algorithm */
- data->chain_noise_a = 0;
- data->chain_noise_b = 0;
- data->chain_noise_c = 0;
- data->chain_signal_a = 0;
- data->chain_signal_b = 0;
- data->chain_signal_c = 0;
- data->beacon_count = 0;
-
- memset(&cmd, 0, sizeof(cmd));
- iwl_set_calib_hdr(&cmd.hdr,
- priv->_agn.phy_calib_chain_noise_reset_cmd);
- ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd);
- if (ret)
- IWL_ERR(priv,
- "Could not send REPLY_PHY_CALIBRATION_CMD\n");
- data->state = IWL_CHAIN_NOISE_ACCUMULATE;
- IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
- }
-}
-
-static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- __le16 fc, __le32 *tx_flags)
-{
- if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
- info->flags & IEEE80211_TX_CTL_AMPDU)
- *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
-}
-
-/* Calc max signal level (dBm) among 3 possible receivers */
-static int iwlagn_calc_rssi(struct iwl_priv *priv,
- struct iwl_rx_phy_res *rx_resp)
-{
- /* data from PHY/DSP regarding signal strength, etc.,
- * contents are always there, not configurable by host
- */
- struct iwlagn_non_cfg_phy *ncphy =
- (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
- u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
- u8 agc;
-
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
- agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
-
- /* Find max rssi among 3 possible receivers.
- * These values are measured by the digital signal processor (DSP).
- * They should stay fairly constant even as the signal strength varies,
- * if the radio's automatic gain control (AGC) is working right.
- * AGC value (see below) will provide the "interesting" info.
- */
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
- rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
- IWLAGN_OFDM_RSSI_A_BIT_POS;
- rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
- IWLAGN_OFDM_RSSI_B_BIT_POS;
- val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
- rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
- IWLAGN_OFDM_RSSI_C_BIT_POS;
-
- max_rssi = max_t(u32, rssi_a, rssi_b);
- max_rssi = max_t(u32, max_rssi, rssi_c);
-
- IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
- rssi_a, rssi_b, rssi_c, max_rssi, agc);
-
- /* dBm = max_rssi dB - agc dB - constant.
- * Higher AGC (higher radio gain) means lower signal. */
- return max_rssi - agc - IWLAGN_RSSI_OFFSET;
-}
-
int iwlagn_set_pan_params(struct iwl_priv *priv)
{
struct iwl_wipan_params_cmd cmd;
@@ -290,18 +201,10 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1);
- ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
+ ret = trans_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC,
+ sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
return ret;
}
-
-struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
- .build_addsta_hcmd = iwlagn_build_addsta_hcmd,
- .gain_computation = iwlagn_gain_computation,
- .chain_noise_reset = iwlagn_chain_noise_reset,
- .tx_cmd_protection = iwlagn_tx_cmd_protection,
- .calc_rssi = iwlagn_calc_rssi,
- .request_scan = iwlagn_request_scan,
-};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 90d366e15d2..eb2be0d3048 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -39,6 +39,7 @@
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
#include "iwl-sta.h"
+#include "iwl-trans.h"
static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
{
@@ -540,8 +541,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
- return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
- &tx_power_cmd);
+ return trans_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC,
+ sizeof(tx_power_cmd), &tx_power_cmd);
}
void iwlagn_temperature(struct iwl_priv *priv)
@@ -610,8 +611,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
- size_t offset)
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
BUG_ON(address >= priv->cfg->base_params->eeprom_size);
@@ -702,7 +702,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
/* nic_init */
spin_lock_irqsave(&priv->lock, flags);
- priv->cfg->ops->lib->apm_ops.init(priv);
+ iwl_apm_init(priv);
/* Set interrupt coalescing calibration timer to default (512 usecs) */
iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
@@ -711,10 +711,10 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
iwlagn_set_pwr_vmain(priv);
- priv->cfg->ops->lib->apm_ops.config(priv);
+ priv->cfg->ops->lib->nic_config(priv);
/* Allocate the RX queue, or reset if it is already allocated */
- priv->trans.ops->rx_init(priv);
+ trans_rx_init(priv);
iwlagn_rx_replenish(priv);
@@ -728,7 +728,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
/* Allocate or reset and init all Tx and Command queues */
- if (priv->trans.ops->tx_init(priv))
+ if (trans_tx_init(priv))
return -ENOMEM;
if (priv->cfg->base_params->shadow_reg_enable) {
@@ -905,17 +905,6 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv)
iwlagn_rx_queue_restock(priv);
}
-int iwlagn_rxq_stop(struct iwl_priv *priv)
-{
-
- /* stop Rx DMA */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-
- return 0;
-}
-
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
{
int idx = 0;
@@ -1074,6 +1063,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = { sizeof(struct iwl_scan_cmd), },
+ .flags = CMD_SYNC,
};
struct iwl_scan_cmd *scan;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
@@ -1370,7 +1360,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
if (ret)
return ret;
- ret = iwl_send_cmd_sync(priv, &cmd);
+ ret = trans_send_cmd(priv, &cmd);
if (ret) {
clear_bit(STATUS_SCAN_HW, &priv->status);
iwlagn_set_pan_params(priv);
@@ -1476,7 +1466,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_control);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
@@ -1644,9 +1634,11 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
} else {
basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
- if (priv->cfg->bt_params &&
- priv->cfg->bt_params->bt_sco_disable)
+
+ if (!priv->bt_enable_pspoll)
basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+ else
+ basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
if (priv->bt_ch_announce)
basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
@@ -1668,19 +1660,97 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
if (priv->cfg->bt_params->bt_session_2) {
memcpy(&bt_cmd_2000.basic, &basic,
sizeof(basic));
- ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(bt_cmd_2000), &bt_cmd_2000);
+ ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else {
memcpy(&bt_cmd_6000.basic, &basic,
sizeof(basic));
- ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(bt_cmd_6000), &bt_cmd_6000);
+ ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
}
if (ret)
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
+void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
+{
+ struct iwl_rxon_context *ctx, *found_ctx = NULL;
+ bool found_ap = false;
+
+ lockdep_assert_held(&priv->mutex);
+
+ /* Check whether AP or GO mode is active. */
+ if (rssi_ena) {
+ for_each_context(priv, ctx) {
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP &&
+ iwl_is_associated_ctx(ctx)) {
+ found_ap = true;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If disable was received or If GO/AP mode, disable RSSI
+ * measurements.
+ */
+ if (!rssi_ena || found_ap) {
+ if (priv->cur_rssi_ctx) {
+ ctx = priv->cur_rssi_ctx;
+ ieee80211_disable_rssi_reports(ctx->vif);
+ priv->cur_rssi_ctx = NULL;
+ }
+ return;
+ }
+
+ /*
+ * If rssi measurements need to be enabled, consider all cases now.
+ * Figure out how many contexts are active.
+ */
+ for_each_context(priv, ctx) {
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
+ iwl_is_associated_ctx(ctx)) {
+ found_ctx = ctx;
+ break;
+ }
+ }
+
+ /*
+ * rssi monitor already enabled for the correct interface...nothing
+ * to do.
+ */
+ if (found_ctx == priv->cur_rssi_ctx)
+ return;
+
+ /*
+ * Figure out if rssi monitor is currently enabled, and needs
+ * to be changed. If rssi monitor is already enabled, disable
+ * it first else just enable rssi measurements on the
+ * interface found above.
+ */
+ if (priv->cur_rssi_ctx) {
+ ctx = priv->cur_rssi_ctx;
+ if (ctx->vif)
+ ieee80211_disable_rssi_reports(ctx->vif);
+ }
+
+ priv->cur_rssi_ctx = found_ctx;
+
+ if (!found_ctx)
+ return;
+
+ ieee80211_enable_rssi_reports(found_ctx->vif,
+ IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD,
+ IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD);
+}
+
+static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
+{
+ return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
+ BT_UART_MSG_FRAME3SCOESCO_POS;
+}
+
static void iwlagn_bt_traffic_change_work(struct work_struct *work)
{
struct iwl_priv *priv =
@@ -1733,8 +1803,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
if (test_bit(STATUS_SCAN_HW, &priv->status))
goto out;
- if (priv->cfg->ops->lib->update_chain_flags)
- priv->cfg->ops->lib->update_chain_flags(priv);
+ iwl_update_chain_flags(priv);
if (smps_request != -1) {
priv->current_ht_config.smps = smps_request;
@@ -1743,10 +1812,30 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
ieee80211_request_smps(ctx->vif, smps_request);
}
}
+
+ /*
+ * Dynamic PS poll related functionality. Adjust RSSI measurements if
+ * necessary.
+ */
+ iwlagn_bt_coex_rssi_monitor(priv);
out:
mutex_unlock(&priv->mutex);
}
+/*
+ * If BT sco traffic, and RSSI monitor is enabled, move measurements to the
+ * correct interface or disable it if this is the last interface to be
+ * removed.
+ */
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv)
+{
+ if (priv->bt_is_sco &&
+ priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS)
+ iwlagn_bt_adjust_rssi_monitor(priv, true);
+ else
+ iwlagn_bt_adjust_rssi_monitor(priv, false);
+}
+
static void iwlagn_print_uartmsg(struct iwl_priv *priv,
struct iwl_bt_uart_msg *uart_msg)
{
@@ -1862,6 +1951,8 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
iwlagn_print_uartmsg(priv, uart_msg);
priv->last_bt_traffic_load = priv->bt_traffic_load;
+ priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg);
+
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
if (priv->bt_status != coex->bt_status ||
priv->last_bt_traffic_load != coex->bt_traffic_load) {
@@ -2321,13 +2412,14 @@ void iwlagn_stop_device(struct iwl_priv *priv)
* already dead.
*/
if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) {
- iwlagn_txq_ctx_stop(priv);
- iwlagn_rxq_stop(priv);
+ trans_tx_stop(priv);
+ trans_rx_stop(priv);
- /* Power-down device's busmaster DMA clocks */
- iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
- udelay(5);
- }
+ /* Power-down device's busmaster DMA clocks */
+ iwl_write_prph(priv, APMG_CLK_DIS_REG,
+ APMG_CLK_VAL_DMA_CLK_RQT);
+ udelay(5);
+ }
/* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 85e082830c1..ebcd13bc10d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -336,6 +336,12 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
}
#ifdef CONFIG_MAC80211_DEBUGFS
+/**
+ * Program the device to use fixed rate for frame transmit
+ * This is for debugging/testing only
+ * once the device start use fixed rate, we need to reload the module
+ * to being back the normal operation.
+ */
static void rs_program_fix_rate(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta)
{
@@ -348,13 +354,15 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
- lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate;
+ /* testmode has higher priority to overwirte the fixed rate */
+ if (priv->tm_fixed_rate)
+ lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
- lq_sta->lq.sta_id, priv->dbg_fixed_rate);
+ lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
- if (priv->dbg_fixed_rate) {
- rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate);
+ if (lq_sta->dbg_fixed_rate) {
+ rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
false);
}
@@ -1073,7 +1081,8 @@ done:
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, skb, sta, lq_sta);
#ifdef CONFIG_MAC80211_DEBUGFS
- if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate)
+ if ((priv->tm_fixed_rate) &&
+ (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
rs_program_fix_rate(priv, lq_sta);
#endif
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
@@ -2896,7 +2905,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0;
- priv->dbg_fixed_rate = 0;
+ priv->tm_fixed_rate = 0;
#ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0;
#endif
@@ -3095,7 +3104,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
} else {
lq_sta->dbg_fixed_rate = 0;
- priv->dbg_fixed_rate = 0;
IWL_ERR(priv,
"Invalid antenna selection 0x%X, Valid is 0x%X\n",
ant_sel_tx, valid_tx_ant);
@@ -3123,9 +3131,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%x", &parsed_rate) == 1)
- priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate;
+ lq_sta->dbg_fixed_rate = parsed_rate;
else
- priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0;
+ lq_sta->dbg_fixed_rate = 0;
rs_program_fix_rate(priv, lq_sta);
@@ -3155,7 +3163,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
lq_sta->total_failed, lq_sta->total_success,
lq_sta->active_legacy_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
- priv->dbg_fixed_rate);
+ lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
(priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
(priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index c6bb73a66d9..dc64f251535 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -30,6 +30,7 @@
#include "iwl-core.h"
#include "iwl-agn-calib.h"
#include "iwl-helpers.h"
+#include "iwl-trans.h"
static int iwlagn_disable_bss(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
@@ -39,7 +40,8 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+ ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd,
+ CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -64,7 +66,8 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+ ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd,
+ CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter;
send->dev_type = old_dev_type;
@@ -89,7 +92,8 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+ ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
+ sizeof(*send), send);
send->filter_flags = old_filter;
@@ -117,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
- ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
+ ret = trans_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm);
if (ret)
@@ -176,8 +180,8 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
- ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
- sizeof(rxon_assoc), &rxon_assoc, NULL);
+ ret = trans_send_cmd_pdu(priv, ctx->rxon_assoc_cmd,
+ CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret;
}
@@ -262,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
* Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this.
*/
- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+ ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -670,6 +674,38 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
ht_conf->single_chain_sufficient = !need_multiple;
}
+static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
+{
+ struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+ int ret;
+
+ if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+ iwl_is_any_associated(priv)) {
+ struct iwl_calib_chain_noise_reset_cmd cmd;
+
+ /* clear data for chain noise calibration algorithm */
+ data->chain_noise_a = 0;
+ data->chain_noise_b = 0;
+ data->chain_noise_c = 0;
+ data->chain_signal_a = 0;
+ data->chain_signal_b = 0;
+ data->chain_signal_c = 0;
+ data->beacon_count = 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ iwl_set_calib_hdr(&cmd.hdr,
+ priv->_agn.phy_calib_chain_noise_reset_cmd);
+ ret = trans_send_cmd_pdu(priv,
+ REPLY_PHY_CALIBRATION_CMD,
+ CMD_SYNC, sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv,
+ "Could not send REPLY_PHY_CALIBRATION_CMD\n");
+ data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+ IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
+ }
+}
+
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -727,6 +763,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
}
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
}
+
+ iwlagn_bt_coex_rssi_monitor(priv);
}
if (ctx->ht.enabled) {
@@ -776,7 +814,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
iwl_power_update_mode(priv, false);
/* Enable RX differential gain and sensitivity calibrations */
- iwl_chain_noise_reset(priv);
+ if (!priv->disable_chain_noise_cal)
+ iwlagn_chain_noise_reset(priv);
priv->start_calib = 1;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 9b32f83f0b7..001622c0652 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -33,6 +33,7 @@
#include "iwl-core.h"
#include "iwl-sta.h"
#include "iwl-agn.h"
+#include "iwl-trans.h"
static struct iwl_link_quality_cmd *
iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
@@ -180,7 +181,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size;
if (not_empty || send_if_empty)
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
else
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index c05a8d9fbd2..7d3aad83e0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -339,6 +339,16 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
}
+static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
+ struct ieee80211_tx_info *info,
+ __le16 fc, __le32 *tx_flags)
+{
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
+ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
+ info->flags & IEEE80211_TX_CTL_AMPDU)
+ *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+}
+
/*
* handle build REPLY_TX command notification.
*/
@@ -388,7 +398,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
- priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
+ iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);
tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
if (ieee80211_is_mgmt(fc)) {
@@ -436,6 +446,16 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+ if (priv->tm_fixed_rate) {
+ /*
+ * rate overwrite by testmode
+ * we not only send lq command to change rate
+ * we also re-enforce per data pkt base.
+ */
+ tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
+ memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
+ sizeof(tx_cmd->rate_n_flags));
+ }
return;
}
@@ -497,8 +517,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
- ieee80211_get_tkip_key(keyconf, skb_frag,
- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
break;
@@ -831,88 +850,6 @@ drop_unlock_priv:
return -1;
}
-static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
- struct iwl_dma_ptr *ptr, size_t size)
-{
- ptr->addr = dma_alloc_coherent(priv->bus.dev, size,
- &ptr->dma, GFP_KERNEL);
- if (!ptr->addr)
- return -ENOMEM;
- ptr->size = size;
- return 0;
-}
-
-static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
- struct iwl_dma_ptr *ptr)
-{
- if (unlikely(!ptr->addr))
- return;
-
- dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma);
- memset(ptr, 0, sizeof(*ptr));
-}
-
-/**
- * iwlagn_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
-{
- int txq_id;
-
- /* Tx queues */
- if (priv->txq) {
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (txq_id == priv->cmd_queue)
- iwl_cmd_queue_free(priv);
- else
- iwl_tx_queue_free(priv, txq_id);
- }
- iwlagn_free_dma_ptr(priv, &priv->kw);
-
- iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
-
- /* free tx queue structure */
- iwl_free_txq_mem(priv);
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
-{
- int ch, txq_id;
- unsigned long flags;
-
- /* Turn off all Tx DMA fifos */
- spin_lock_irqsave(&priv->lock, flags);
-
- iwlagn_txq_set_sched(priv, 0);
-
- /* Stop each Tx DMA channel, and wait for it to be idle */
- for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
- iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
- if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
- 1000))
- IWL_ERR(priv, "Failing on timeout while stopping"
- " DMA channel %d [0x%08x]", ch,
- iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (!priv->txq)
- return;
-
- /* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (txq_id == priv->cmd_queue)
- iwl_cmd_queue_unmap(priv);
- else
- iwl_tx_queue_unmap(priv, txq_id);
-}
-
/*
* Find first available (lowest unused) Tx Queue, mark it "active".
* Called only when finding queue for aggregation.
@@ -1171,7 +1108,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
- iwlagn_txq_free_tfd(priv, txq);
+ iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
}
return nfreed;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 2043c8b3139..06304a681ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -39,6 +39,7 @@
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
#include "iwl-agn-calib.h"
+#include "iwl-trans.h"
#define IWL_AC_UNSET -1
@@ -223,7 +224,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -321,7 +322,8 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
/* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd));
}
- return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
+ return trans_send_cmd_pdu(priv,
+ COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
sizeof(coex_cmd), &coex_cmd);
}
@@ -353,7 +355,8 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
sizeof(iwlagn_bt_prio_tbl));
- if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+ if (trans_send_cmd_pdu(priv,
+ REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
sizeof(prio_tbl_cmd), &prio_tbl_cmd))
IWL_ERR(priv, "failed to send BT prio tbl command\n");
}
@@ -365,7 +368,8 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
env_cmd.action = action;
env_cmd.type = type;
- ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+ ret = trans_send_cmd_pdu(priv,
+ REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd);
if (ret)
IWL_ERR(priv, "failed to send BT env command\n");
@@ -403,7 +407,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
priv->scd_bc_tbls.dma >> 10);
/* Enable DMA channel */
- for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++)
+ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7e6c463abbd..38a1e4f5882 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -129,6 +129,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
struct iwl_tx_beacon_cmd *tx_beacon_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_TX_BEACON,
+ .flags = CMD_SYNC,
};
struct ieee80211_tx_info *info;
u32 frame_size;
@@ -205,7 +206,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
cmd.data[1] = priv->beacon_skb->data;
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
- return iwl_send_cmd_sync(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
static void iwl_bg_beacon_update(struct work_struct *work)
@@ -578,7 +579,8 @@ static void iwl_rx_handle(struct iwl_priv *priv)
if (reclaim) {
/* Invoke any callbacks, transfer the buffer to caller,
- * and fire off the (possibly) blocking iwl_send_cmd()
+ * and fire off the (possibly) blocking
+ * trans_send_cmd()
* as we reclaim the driver command queue */
if (rxb->page)
iwl_tx_cmd_complete(priv, rxb);
@@ -1563,7 +1565,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
release_firmware(ucode_raw);
}
-static const char *desc_lookup_text[] = {
+static const char * const desc_lookup_text[] = {
"OK",
"FAIL",
"BAD_PARAM",
@@ -1587,7 +1589,7 @@ static const char *desc_lookup_text[] = {
"NMI_INTERRUPT_DATA_ACTION_PT",
"NMI_TRM_HW_ER",
"NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
+ "NMI_INTERRUPT_BREAK_POINT",
"DEBUG_0",
"DEBUG_1",
"DEBUG_2",
@@ -1940,8 +1942,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
adv_cmd.critical_temperature_exit =
cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(adv_cmd), &adv_cmd);
+ ret = trans_send_cmd_pdu(priv,
+ REPLY_CT_KILL_CONFIG_CMD,
+ CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
@@ -1955,8 +1958,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
cmd.critical_temperature_R =
cpu_to_le32(priv->hw_params.ct_kill_threshold);
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(cmd), &cmd);
+ ret = trans_send_cmd_pdu(priv,
+ REPLY_CT_KILL_CONFIG_CMD,
+ CMD_SYNC, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
@@ -1980,7 +1984,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
@@ -2011,11 +2015,18 @@ int iwl_alive_start(struct iwl_priv *priv)
if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) {
/* Configure Bluetooth device coexistence support */
+ if (priv->cfg->bt_params->bt_sco_disable)
+ priv->bt_enable_pspoll = false;
+ else
+ priv->bt_enable_pspoll = true;
+
priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
iwlagn_send_advance_bt_config(priv);
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+ priv->cur_rssi_ctx = NULL;
+
iwlagn_send_prio_tbl(priv);
/* FIXME: w/a to force change uCode BT state machine */
@@ -2098,6 +2109,8 @@ static void __iwl_down(struct iwl_priv *priv)
/* reset BT coex data */
priv->bt_status = 0;
+ priv->cur_rssi_ctx = NULL;
+ priv->bt_is_sco = 0;
if (priv->cfg->bt_params)
priv->bt_traffic_load =
priv->cfg->bt_params->bt_init_traffic_load;
@@ -2273,6 +2286,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
u8 bt_ci_compliance;
u8 bt_load;
u8 bt_status;
+ bool bt_is_sco;
lockdep_assert_held(&priv->mutex);
@@ -2293,6 +2307,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
bt_ci_compliance = priv->bt_ci_compliance;
bt_load = priv->bt_traffic_load;
bt_status = priv->bt_status;
+ bt_is_sco = priv->bt_is_sco;
__iwl_down(priv);
@@ -2300,6 +2315,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
priv->bt_ci_compliance = bt_ci_compliance;
priv->bt_traffic_load = bt_load;
priv->bt_status = bt_status;
+ priv->bt_is_sco = bt_is_sco;
}
static void iwl_bg_restart(struct work_struct *data)
@@ -3326,6 +3342,29 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
kfree(priv->beacon_cmd);
}
+static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_priv *priv = hw->priv;
+
+ mutex_lock(&priv->mutex);
+
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ if (rssi_event == RSSI_EVENT_LOW)
+ priv->bt_enable_pspoll = true;
+ else if (rssi_event == RSSI_EVENT_HIGH)
+ priv->bt_enable_pspoll = false;
+
+ iwlagn_send_advance_bt_config(priv);
+ } else {
+ IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled,"
+ "ignoring RSSI callback\n");
+ }
+
+ mutex_unlock(&priv->mutex);
+}
+
struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx,
.start = iwlagn_mac_start,
@@ -3351,6 +3390,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
.offchannel_tx = iwl_mac_offchannel_tx,
.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
+ .rssi_callback = iwl_mac_rssi_callback,
CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
};
@@ -3709,8 +3749,8 @@ void __devexit iwl_remove(struct iwl_priv * priv)
iwl_dealloc_ucode(priv);
- priv->trans.ops->rx_free(priv);
- iwlagn_hw_txq_ctx_free(priv);
+ trans_rx_free(priv);
+ trans_tx_free(priv);
iwl_eeprom_free(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 4351151e2a9..5f58b44bb2a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -109,9 +109,6 @@ extern struct iwl_cfg iwl135_bg_cfg;
extern struct iwl_cfg iwl135_bgn_cfg;
extern struct iwl_mod_params iwlagn_mod_params;
-extern struct iwl_hcmd_ops iwlagn_hcmd;
-extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
-extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
extern struct ieee80211_ops iwlagn_hw_ops;
@@ -180,8 +177,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
- size_t offset);
int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
int iwlagn_hw_nic_init(struct iwl_priv *priv);
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
@@ -193,12 +188,12 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv);
void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
void iwlagn_rx_replenish(struct iwl_priv *priv);
void iwlagn_rx_replenish_now(struct iwl_priv *priv);
-int iwlagn_rxq_stop(struct iwl_priv *priv);
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
void iwl_setup_rx_handlers(struct iwl_priv *priv);
/* tx */
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+ int index);
int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len, u8 reset);
@@ -217,8 +212,6 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv);
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv);
static inline u32 iwl_tx_status_to_mac80211(u32 status)
{
@@ -257,6 +250,12 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
int iwlagn_set_pan_params(struct iwl_priv *priv);
+void iwlagn_gain_computation(struct iwl_priv *priv,
+ u32 average_noise[NUM_RX_CHAINS],
+ u16 min_average_noise_antenna_i,
+ u32 min_average_noise,
+ u8 default_chain);
+
/* bt coex */
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
@@ -265,6 +264,8 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv);
+void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_get_tx_fail_reason(u32 status);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 8a2edf8dce3..ee2563777e8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1931,6 +1931,9 @@ struct iwl_bt_cmd {
/* Disable Sync PSPoll on SCO/eSCO */
#define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE BIT(7)
+#define IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD -75 /* dBm */
+#define IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD -65 /* dBm */
+
#define IWLAGN_BT_PRIO_BOOST_MAX 0xFF
#define IWLAGN_BT_PRIO_BOOST_MIN 0x00
#define IWLAGN_BT_PRIO_BOOST_DEFAULT 0xF0
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index f91e306c249..fa3d5bacbde 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -42,6 +42,7 @@
#include "iwl-sta.h"
#include "iwl-helpers.h"
#include "iwl-agn.h"
+#include "iwl-trans.h"
u32 iwl_debug_level;
@@ -375,8 +376,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
le32_to_cpu(ctx->timing.beacon_init_val),
le16_to_cpu(ctx->timing.atim_window));
- return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
- sizeof(ctx->timing), &ctx->timing);
+ return trans_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
+ CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
}
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -1131,8 +1132,8 @@ void iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
- if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl_bt_cmd), &bt_cmd))
+ if (trans_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
@@ -1144,11 +1145,13 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
};
if (flags & CMD_ASYNC)
- return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+ return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ CMD_ASYNC,
sizeof(struct iwl_statistics_cmd),
- &statistics_cmd, NULL);
+ &statistics_cmd);
else
- return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ CMD_SYNC,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
}
@@ -1370,12 +1373,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
}
-void iwl_free_txq_mem(struct iwl_priv *priv)
-{
- kfree(priv->txq);
- priv->txq = NULL;
-}
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6c21de9f5b6..692c30cb2fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -80,31 +80,6 @@ struct iwl_cmd;
#define IWL_CMD(x) case x: return #x
-struct iwl_hcmd_utils_ops {
- u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
- void (*gain_computation)(struct iwl_priv *priv,
- u32 *average_noise,
- u16 min_average_noise_antennat_i,
- u32 min_average_noise,
- u8 default_chain);
- void (*chain_noise_reset)(struct iwl_priv *priv);
- void (*tx_cmd_protection)(struct iwl_priv *priv,
- struct ieee80211_tx_info *info,
- __le16 fc, __le32 *tx_flags);
- int (*calc_rssi)(struct iwl_priv *priv,
- struct iwl_rx_phy_res *rx_resp);
- int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
-};
-
-struct iwl_apm_ops {
- int (*init)(struct iwl_priv *priv);
- void (*config)(struct iwl_priv *priv);
-};
-
-struct iwl_temp_ops {
- void (*temperature)(struct iwl_priv *priv);
-};
-
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
@@ -118,17 +93,14 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr);
int (*set_channel_switch)(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch);
- /* power management */
- struct iwl_apm_ops apm_ops;
-
- /* power */
- void (*update_chain_flags)(struct iwl_priv *priv);
+ /* device specific configuration */
+ void (*nic_config)(struct iwl_priv *priv);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
/* temperature */
- struct iwl_temp_ops temp_ops;
+ void (*temperature)(struct iwl_priv *priv);
};
/* NIC specific ops */
@@ -138,7 +110,6 @@ struct iwl_nic_ops {
struct iwl_ops {
const struct iwl_lib_ops *lib;
- const struct iwl_hcmd_utils_ops *utils;
const struct iwl_nic_ops *nic;
};
@@ -328,8 +299,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
int iwl_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
-void iwl_free_txq_mem(struct iwl_priv *priv);
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
void iwl_free_traffic_mem(struct iwl_priv *priv);
@@ -371,8 +340,6 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
/*****************************************************
* RX
******************************************************/
-void iwl_cmd_queue_free(struct iwl_priv *priv);
-void iwl_cmd_queue_unmap(struct iwl_priv *priv);
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl_rx_queue *q);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
@@ -386,10 +353,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
* TX
******************************************************/
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
int count, int slots_num, u32 id);
-void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
void iwl_setup_watchdog(struct iwl_priv *priv);
/*****************************************************
* TX power
@@ -440,16 +405,9 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
*****************************************************/
const char *get_cmd_string(u8 cmd);
-int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
- struct iwl_host_cmd *cmd);
int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags,
u16 len, const void *data);
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
- const void *data,
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt));
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c6560e97a62..424c45c43f5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -260,11 +260,9 @@ struct iwl_channel_info {
enum {
CMD_SYNC = 0,
- CMD_SIZE_NORMAL = 0,
- CMD_NO_SKB = 0,
- CMD_ASYNC = (1 << 1),
- CMD_WANT_SKB = (1 << 2),
- CMD_MAPPED = (1 << 3),
+ CMD_ASYNC = BIT(0),
+ CMD_WANT_SKB = BIT(1),
+ CMD_ON_DEMAND = BIT(2),
};
#define DEF_CMD_PAYLOAD_SIZE 320
@@ -297,6 +295,16 @@ enum iwl_hcmd_dataflag {
IWL_HCMD_DFL_NOCOPY = BIT(0),
};
+/**
+ * struct iwl_host_cmd - Host command to the uCode
+ * @data: array of chunks that composes the data of the host command
+ * @reply_page: pointer to the page that holds the response to the host command
+ * @callback:
+ * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
+ * @len: array of the lenths of the chunks in data
+ * @dataflags:
+ * @id: id of the host command
+ */
struct iwl_host_cmd {
const void *data[IWL_MAX_CMD_TFDS];
unsigned long reply_page;
@@ -634,7 +642,6 @@ struct iwl_sensitivity_ranges {
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
- * @dma_chnl_num: Number of Tx DMA/FIFO channels
* @scd_bc_tbls_size: size of scheduler byte count tables
* @tfd_size: TFD size
* @tx/rx_chains_num: Number of TX/RX chains
@@ -656,7 +663,6 @@ struct iwl_sensitivity_ranges {
*/
struct iwl_hw_params {
u8 max_txq_num;
- u8 dma_chnl_num;
u16 scd_bc_tbls_size;
u32 tfd_size;
u8 tx_chains_num;
@@ -696,8 +702,6 @@ struct iwl_hw_params {
****************************************************************************/
extern void iwl_update_chain_flags(struct iwl_priv *priv);
extern const u8 iwl_bcast_addr[ETH_ALEN];
-extern int iwl_rxq_stop(struct iwl_priv *priv);
-extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl_queue_space(const struct iwl_queue *q);
static inline int iwl_queue_used(const struct iwl_queue *q, int i)
{
@@ -1233,19 +1237,37 @@ struct iwl_trans;
* struct iwl_trans_ops - transport specific operations
* @rx_init: inits the rx memory, allocate it if needed
+ * @rx_stop: stop the rx
* @rx_free: frees the rx memory
* @tx_init:inits the tx memory, allocate if needed
+ * @tx_stop: stop the tx
+ * @tx_free: frees the tx memory
+ * @send_cmd:send a host command
+ * @send_cmd_pdu:send a host command: flags can be CMD_*
*/
struct iwl_trans_ops {
int (*rx_init)(struct iwl_priv *priv);
+ int (*rx_stop)(struct iwl_priv *priv);
void (*rx_free)(struct iwl_priv *priv);
+
int (*tx_init)(struct iwl_priv *priv);
+ int (*tx_stop)(struct iwl_priv *priv);
+ void (*tx_free)(struct iwl_priv *priv);
+
+ int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+ int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
+ const void *data);
};
struct iwl_trans {
const struct iwl_trans_ops *ops;
};
+/* uCode ownership */
+#define IWL_OWNERSHIP_DRIVER 0
+#define IWL_OWNERSHIP_TM 1
+
struct iwl_priv {
/* ieee device used by generic ieee processing code */
@@ -1334,6 +1356,10 @@ struct iwl_priv {
int fw_index; /* firmware we're trying to load */
u32 ucode_ver; /* version of ucode, copy of
iwl_ucode.ver */
+
+ /* uCode owner: default: IWL_OWNERSHIP_DRIVER */
+ u8 ucode_owner;
+
struct fw_img ucode_rt;
struct fw_img ucode_init;
@@ -1509,6 +1535,9 @@ struct iwl_priv {
u16 dynamic_frag_thresh;
u8 bt_ci_compliance;
struct work_struct bt_traffic_change_work;
+ bool bt_enable_pspoll;
+ struct iwl_rxon_context *cur_rssi_ctx;
+ bool bt_is_sco;
struct iwl_hw_params hw_params;
@@ -1577,7 +1606,7 @@ struct iwl_priv {
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
struct iwl_testmode_trace testmode_trace;
#endif
- u32 dbg_fixed_rate;
+ u32 tm_fixed_rate;
}; /*iwl_priv */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 768d0ee276f..eee97bcf980 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -407,11 +407,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
return -EINVAL;
}
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
- return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
-}
-
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
{
if (!priv->eeprom)
@@ -449,7 +444,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
}
e = (__le16 *)priv->eeprom;
- priv->cfg->ops->lib->apm_ops.init(priv);
+ iwl_apm_init(priv);
ret = iwl_eeprom_verify_signature(priv);
if (ret < 0) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 804f910c651..e4bf8ac5e64 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -292,7 +292,6 @@ extern const u8 iwl_eeprom_band_1[14];
struct iwl_eeprom_ops {
const u32 regulatory_bands[7];
- const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
void (*update_enhanced_txpower) (struct iwl_priv *priv);
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 6dfa806aefe..0ad60b3c04d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -326,7 +326,7 @@
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
/* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH50_TCSR_CHNL_NUM (8)
+#define FH_TCSR_CHNL_NUM (8)
/* TCSR: tx_config register values */
#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 107b38e2ee9..6cff8c165ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -143,9 +143,6 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
int ret;
- if (WARN_ON(!(cmd->flags & CMD_ASYNC)))
- return -EINVAL;
-
/* An asynchronous command can not expect an SKB to be set. */
if (WARN_ON(cmd->flags & CMD_WANT_SKB))
return -EINVAL;
@@ -166,16 +163,13 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return 0;
}
-int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
int cmd_idx;
int ret;
lockdep_assert_held(&priv->mutex);
- if (WARN_ON(cmd->flags & CMD_ASYNC))
- return -EINVAL;
-
/* A synchronous command can not have a callback set. */
if (WARN_ON(cmd->callback))
return -EINVAL;
@@ -263,31 +257,15 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return iwl_send_cmd_sync(priv, cmd);
}
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
-{
- struct iwl_host_cmd cmd = {
- .id = id,
- .len = { len, },
- .data = { data, },
- };
-
- return iwl_send_cmd_sync(priv, &cmd);
-}
-
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
- u8 id, u16 len, const void *data,
- void (*callback)(struct iwl_priv *priv,
- struct iwl_device_cmd *cmd,
- struct iwl_rx_packet *pkt))
+int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
+ const void *data)
{
struct iwl_host_cmd cmd = {
.id = id,
.len = { len, },
.data = { data, },
+ .flags = flags,
};
- cmd.flags |= CMD_ASYNC;
- cmd.callback = callback;
-
- return iwl_send_cmd_async(priv, &cmd);
+ return iwl_send_cmd(priv, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index ff08da09975..60e4169f25e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -40,6 +40,7 @@
#include "iwl-core.h"
#include "iwl-agn.h"
#include "iwl-io.h"
+#include "iwl-trans.h"
/* Throughput OFF time(ms) ON time (ms)
* >300 25 25
@@ -111,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
/* Set led pattern command */
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 565e57e48be..64ff40ae102 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -42,6 +42,7 @@
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
+#include "iwl-trans.h"
/*
* Setting power level allows the card to go to sleep when not busy.
@@ -334,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4]));
- return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+ return trans_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
sizeof(struct iwl_powertable_cmd), cmd);
}
@@ -405,9 +406,9 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
clear_bit(STATUS_POWER_PMI, &priv->status);
- if (priv->cfg->ops->lib->update_chain_flags && update_chains)
- priv->cfg->ops->lib->update_chain_flags(priv);
- else if (priv->cfg->ops->lib->update_chain_flags)
+ if (update_chains)
+ iwl_update_chain_flags(priv);
+ else
IWL_DEBUG_POWER(priv,
"Cannot update the power, chain noise "
"calibration running: %d\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 87148bb3f62..f3f3efe38ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -624,8 +624,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
iwl_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work);
}
- if (priv->cfg->ops->lib->temp_ops.temperature && change)
- priv->cfg->ops->lib->temp_ops.temperature(priv);
+ if (priv->cfg->ops->lib->temperature && change)
+ priv->cfg->ops->lib->temperature(priv);
}
static void iwl_rx_reply_statistics(struct iwl_priv *priv,
@@ -902,6 +902,47 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
return decrypt_out;
}
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwlagn_calc_rssi(struct iwl_priv *priv,
+ struct iwl_rx_phy_res *rx_resp)
+{
+ /* data from PHY/DSP regarding signal strength, etc.,
+ * contents are always there, not configurable by host
+ */
+ struct iwlagn_non_cfg_phy *ncphy =
+ (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+ u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
+ u8 agc;
+
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+ agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
+
+ /* Find max rssi among 3 possible receivers.
+ * These values are measured by the digital signal processor (DSP).
+ * They should stay fairly constant even as the signal strength varies,
+ * if the radio's automatic gain control (AGC) is working right.
+ * AGC value (see below) will provide the "interesting" info.
+ */
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+ rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+ IWLAGN_OFDM_RSSI_A_BIT_POS;
+ rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+ IWLAGN_OFDM_RSSI_B_BIT_POS;
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+ rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+ IWLAGN_OFDM_RSSI_C_BIT_POS;
+
+ max_rssi = max_t(u32, rssi_a, rssi_b);
+ max_rssi = max_t(u32, max_rssi, rssi_c);
+
+ IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+ rssi_a, rssi_b, rssi_c, max_rssi, agc);
+
+ /* dBm = max_rssi dB - agc dB - constant.
+ * Higher AGC (higher radio gain) means lower signal. */
+ return max_rssi - agc - IWLAGN_RSSI_OFFSET;
+}
+
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
static void iwl_rx_reply_rx(struct iwl_priv *priv,
@@ -983,7 +1024,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
- rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+ rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
iwl_dbg_log_rx_data_frame(priv, len, header);
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 438eecd8733..f6ebe29eb79 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -37,6 +37,7 @@
#include "iwl-io.h"
#include "iwl-helpers.h"
#include "iwl-agn.h"
+#include "iwl-trans.h"
/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
* sending probe req. This should be set long enough to hear probe responses
@@ -61,7 +62,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
- .flags = CMD_WANT_SKB,
+ .flags = CMD_SYNC | CMD_WANT_SKB,
};
/* Exit instantly with error when device is not ready
@@ -74,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EIO;
- ret = iwl_send_cmd_sync(priv, &cmd);
+ ret = trans_send_cmd(priv, &cmd);
if (ret)
return ret;
@@ -349,9 +350,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
lockdep_assert_held(&priv->mutex);
- if (WARN_ON(!priv->cfg->ops->utils->request_scan))
- return -EOPNOTSUPP;
-
cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready_rf(priv)) {
@@ -380,7 +378,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
priv->scan_start = jiffies;
priv->scan_band = band;
- ret = priv->cfg->ops->utils->request_scan(priv, vif);
+ ret = iwlagn_request_scan(priv, vif);
if (ret) {
clear_bit(STATUS_SCANNING, &priv->status);
priv->scan_type = IWL_SCAN_NORMAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 7df2814fd4f..65386e575b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -35,6 +35,8 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-sta.h"
+#include "iwl-trans.h"
+#include "iwl-agn.h"
/* priv->sta_lock must be held */
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
@@ -132,6 +134,16 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
}
+static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+ u16 size = (u16)sizeof(struct iwl_addsta_cmd);
+ struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
+ memcpy(addsta, cmd, size);
+ /* resrved in 5000 */
+ addsta->rate_n_flags = cpu_to_le16(0);
+ return size;
+}
+
int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags)
{
@@ -155,8 +167,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
might_sleep();
}
- cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
- ret = iwl_send_cmd(priv, &cmd);
+ cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
+ ret = trans_send_cmd(priv, &cmd);
if (ret || (flags & CMD_ASYNC))
return ret;
@@ -412,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
cmd.flags |= CMD_WANT_SKB;
- ret = iwl_send_cmd(priv, &cmd);
+ ret = trans_send_cmd(priv, &cmd);
if (ret)
return ret;
@@ -781,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return -EINVAL;
if (is_lq_table_valid(priv, ctx, lq))
- ret = iwl_send_cmd(priv, &cmd);
+ ret = trans_send_cmd(priv, &cmd);
else
ret = -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index c00aa5a1b8b..77ed1c295da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -76,7 +76,7 @@
#include "iwl-io.h"
#include "iwl-agn.h"
#include "iwl-testmode.h"
-
+#include "iwl-trans.h"
/* The TLVs used in the gnl message policy between the kernel module and
* user space application. iwl_testmode_gnl_msg_policy is to be carried
@@ -105,6 +105,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
+ [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
};
/*
@@ -232,6 +233,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
return -ENOMSG;
}
+ cmd.flags = CMD_ON_DEMAND;
cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
@@ -239,7 +241,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
/* ok, let's submit the command to ucode */
- return iwl_send_cmd(priv, &cmd);
+ return trans_send_cmd(priv, &cmd);
}
@@ -452,7 +454,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
"Error finding fixrate setting\n");
return -ENOMSG;
}
- priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
+ priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
break;
default:
@@ -586,6 +588,42 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
return -ENOBUFS;
}
+/*
+ * This function handles the user application switch ucode ownership.
+ *
+ * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
+ * decide who the current owner of the uCode
+ *
+ * If the current owner is OWNERSHIP_TM, then the only host command
+ * can deliver to uCode is from testmode, all the other host commands
+ * will dropped.
+ *
+ * default driver is the owner of uCode in normal operational mode
+ *
+ * @hw: ieee80211_hw object that represents the device
+ * @tb: gnl message fields from the user space
+ */
+static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
+{
+ struct iwl_priv *priv = hw->priv;
+ u8 owner;
+
+ if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
+ IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
+ return -ENOMSG;
+ }
+
+ owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
+ if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
+ priv->ucode_owner = owner;
+ else {
+ IWL_DEBUG_INFO(priv, "Invalid owner\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
/* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
* invoke the corresponding handlers.
@@ -607,7 +645,7 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
*/
int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
- struct nlattr *tb[IWL_TM_ATTR_MAX - 1];
+ struct nlattr *tb[IWL_TM_ATTR_MAX];
struct iwl_priv *priv = hw->priv;
int result;
@@ -655,6 +693,11 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
result = iwl_testmode_trace(hw, tb);
break;
+ case IWL_TM_CMD_APP2DEV_OWNERSHIP:
+ IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
+ result = iwl_testmode_ownership(hw, tb);
+ break;
+
default:
IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
result = -ENOSYS;
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index d825188e521..b980bda4b0f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -103,6 +103,10 @@
* @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
* commands from kernel space to carry the eeprom response
* to user application
+ * @IWL_TM_CMD_APP2DEV_OWNERSHIP:
+ * commands from user application to own change the ownership of the uCode
+ * if application has the ownership, the only host command from
+ * testmode will deliver to uCode. Default owner is driver
*/
enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_UCODE = 1,
@@ -121,7 +125,8 @@ enum iwl_tm_cmd_t {
IWL_TM_CMD_DEV2APP_SYNC_RSP = 14,
IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15,
IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16,
- IWL_TM_CMD_MAX = 17,
+ IWL_TM_CMD_APP2DEV_OWNERSHIP = 17,
+ IWL_TM_CMD_MAX = 18,
};
/*
@@ -187,6 +192,10 @@ enum iwl_tm_cmd_t {
* The mandatory fields are:
* IWL_TM_ATTR_FIXRATE for the fixed rate
*
+ * @IWL_TM_ATTR_UCODE_OWNER:
+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
+ * The mandatory fields are:
+ * IWL_TM_ATTR_UCODE_OWNER for the new owner
*/
enum iwl_tm_attr_t {
IWL_TM_ATTR_NOT_APPLICABLE = 0,
@@ -203,7 +212,8 @@ enum iwl_tm_attr_t {
IWL_TM_ATTR_TRACE_SIZE = 11,
IWL_TM_ATTR_TRACE_DUMP = 12,
IWL_TM_ATTR_FIXRATE = 13,
- IWL_TM_ATTR_MAX = 14,
+ IWL_TM_ATTR_UCODE_OWNER = 14,
+ IWL_TM_ATTR_MAX = 15,
};
/* uCode trace buffer */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 7b7b97d8c2e..d760857c863 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -66,6 +66,7 @@
#include "iwl-helpers.h"
/*TODO remove uneeded includes when the transport layer tx_free will be here */
#include "iwl-agn.h"
+#include "iwl-core.h"
static int iwl_trans_rx_alloc(struct iwl_priv *priv)
{
@@ -188,7 +189,15 @@ static void iwl_trans_rx_free(struct iwl_priv *priv)
rxq->rb_stts = NULL;
}
-/* TODO:remove this code duplication */
+static int iwl_trans_rx_stop(struct iwl_priv *priv)
+{
+
+ /* stop Rx DMA */
+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size)
{
@@ -203,6 +212,16 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
return 0;
}
+static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
+ struct iwl_dma_ptr *ptr)
+{
+ if (unlikely(!ptr->addr))
+ return;
+
+ dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma);
+ memset(ptr, 0, sizeof(*ptr));
+}
+
static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id)
{
@@ -212,6 +231,8 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))
return -EINVAL;
+ txq->q.n_window = slots_num;
+
txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
GFP_KERNEL);
txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
@@ -307,6 +328,90 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
}
/**
+ * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
+ */
+static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl_queue *q = &txq->q;
+
+ if (!q->n_bd)
+ return;
+
+ while (q->write_ptr != q->read_ptr) {
+ /* The read_ptr needs to bound by q->n_window */
+ iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr));
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+ }
+}
+
+/**
+ * iwl_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
+{
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct device *dev = priv->bus.dev;
+ int i;
+ if (WARN_ON(!txq))
+ return;
+
+ iwl_tx_queue_unmap(priv, txq_id);
+
+ /* De-alloc array of command/tx buffers */
+ for (i = 0; i < txq->q.n_window; i++)
+ kfree(txq->cmd[i]);
+
+ /* De-alloc circular buffer of TFDs */
+ if (txq->q.n_bd) {
+ dma_free_coherent(dev, priv->hw_params.tfd_size *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
+ }
+
+ /* De-alloc array of per-TFD driver data */
+ kfree(txq->txb);
+ txq->txb = NULL;
+
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
+ /* 0-fill queue descriptor structure */
+ memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+static void iwl_trans_tx_free(struct iwl_priv *priv)
+{
+ int txq_id;
+
+ /* Tx queues */
+ if (priv->txq) {
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ iwl_tx_queue_free(priv, txq_id);
+ }
+
+ kfree(priv->txq);
+ priv->txq = NULL;
+
+ iwlagn_free_dma_ptr(priv, &priv->kw);
+
+ iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
+}
+
+/**
* iwl_trans_tx_alloc - allocate TX context
* Allocate all Tx DMA structures and initialize them
*
@@ -362,7 +467,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv)
return 0;
error:
- iwlagn_hw_txq_ctx_free(priv);
+ trans_tx_free(priv);
return ret;
}
@@ -406,15 +511,58 @@ static int iwl_trans_tx_init(struct iwl_priv *priv)
error:
/*Upon error, free only if we allocated something */
if (alloc)
- iwlagn_hw_txq_ctx_free(priv);
+ trans_tx_free(priv);
return ret;
}
+/**
+ * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
+ */
+static int iwl_trans_tx_stop(struct iwl_priv *priv)
+{
+ int ch, txq_id;
+ unsigned long flags;
+
+ /* Turn off all Tx DMA fifos */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ iwlagn_txq_set_sched(priv, 0);
+
+ /* Stop each Tx DMA channel, and wait for it to be idle */
+ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
+ iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+ if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+ 1000))
+ IWL_ERR(priv, "Failing on timeout while stopping"
+ " DMA channel %d [0x%08x]", ch,
+ iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (!priv->txq) {
+ IWL_WARN(priv, "Stopping tx queues that aren't allocated...");
+ return 0;
+ }
+
+ /* Unmap DMA from host system and free skb's */
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ iwl_tx_queue_unmap(priv, txq_id);
+
+ return 0;
+}
+
static const struct iwl_trans_ops trans_ops = {
.rx_init = iwl_trans_rx_init,
+ .rx_stop = iwl_trans_rx_stop,
.rx_free = iwl_trans_rx_free,
.tx_init = iwl_trans_tx_init,
+ .tx_stop = iwl_trans_tx_stop,
+ .tx_free = iwl_trans_tx_free,
+
+ .send_cmd = iwl_send_cmd,
+ .send_cmd_pdu = iwl_send_cmd_pdu,
};
void iwl_trans_register(struct iwl_trans *trans)
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index bec494c5a97..111acca07d7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -60,5 +60,46 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+static inline int trans_rx_init(struct iwl_priv *priv)
+{
+ return priv->trans.ops->rx_init(priv);
+}
+
+static inline int trans_rx_stop(struct iwl_priv *priv)
+{
+ return priv->trans.ops->rx_stop(priv);
+}
+
+static inline void trans_rx_free(struct iwl_priv *priv)
+{
+ priv->trans.ops->rx_free(priv);
+}
+
+static inline int trans_tx_init(struct iwl_priv *priv)
+{
+ return priv->trans.ops->tx_init(priv);
+}
+
+static inline int trans_tx_stop(struct iwl_priv *priv)
+{
+ return priv->trans.ops->tx_stop(priv);
+}
+
+static inline void trans_tx_free(struct iwl_priv *priv)
+{
+ priv->trans.ops->tx_free(priv);
+}
+
+static inline int trans_send_cmd(struct iwl_priv *priv,
+ struct iwl_host_cmd *cmd)
+{
+ return priv->trans.ops->send_cmd(priv, cmd);
+}
+
+static inline int trans_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags,
+ u16 len, const void *data)
+{
+ return priv->trans.ops->send_cmd_pdu(priv, id, flags, len, data);
+}
void iwl_trans_register(struct iwl_trans *trans);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index db5abaa2ff7..9b07e07f168 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -157,14 +157,15 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
* iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
* @priv - driver private data
* @txq - tx queue
+ * @index - the index of the TFD to be freed
*
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+ int index)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
- int index = txq->q.read_ptr;
iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
DMA_TO_DEVICE);
@@ -173,12 +174,12 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
if (txq->txb) {
struct sk_buff *skb;
- skb = txq->txb[txq->q.read_ptr].skb;
+ skb = txq->txb[index].skb;
/* can be called from irqs-disabled context */
if (skb) {
dev_kfree_skb_any(skb);
- txq->txb[txq->q.read_ptr].skb = NULL;
+ txq->txb[index].skb = NULL;
}
}
}
@@ -220,122 +221,6 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
return 0;
}
-/**
- * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
- */
-void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
-
- if (q->n_bd == 0)
- return;
-
- while (q->write_ptr != q->read_ptr) {
- iwlagn_txq_free_tfd(priv, txq);
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
- }
-}
-
-/**
- * iwl_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
-{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct device *dev = priv->bus.dev;
- int i;
-
- iwl_tx_queue_unmap(priv, txq_id);
-
- /* De-alloc array of command/tx buffers */
- for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
- kfree(txq->cmd[i]);
-
- /* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd)
- dma_free_coherent(dev, priv->hw_params.tfd_size *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
-
- /* De-alloc array of per-TFD driver data */
- kfree(txq->txb);
- txq->txb = NULL;
-
- /* deallocate arrays */
- kfree(txq->cmd);
- kfree(txq->meta);
- txq->cmd = NULL;
- txq->meta = NULL;
-
- /* 0-fill queue descriptor structure */
- memset(txq, 0, sizeof(*txq));
-}
-
-/**
- * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
- */
-void iwl_cmd_queue_unmap(struct iwl_priv *priv)
-{
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
- struct iwl_queue *q = &txq->q;
- int i;
-
- if (q->n_bd == 0)
- return;
-
- while (q->read_ptr != q->write_ptr) {
- i = get_cmd_index(q, q->read_ptr);
-
- if (txq->meta[i].flags & CMD_MAPPED) {
- iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i],
- DMA_BIDIRECTIONAL);
- txq->meta[i].flags = 0;
- }
-
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
- }
-}
-
-/**
- * iwl_cmd_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_cmd_queue_free(struct iwl_priv *priv)
-{
- struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
- struct device *dev = priv->bus.dev;
- int i;
-
- iwl_cmd_queue_unmap(priv);
-
- /* De-alloc array of command/tx buffers */
- for (i = 0; i < TFD_CMD_SLOTS; i++)
- kfree(txq->cmd[i]);
-
- /* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd)
- dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
- txq->tfds, txq->q.dma_addr);
-
- /* deallocate arrays */
- kfree(txq->cmd);
- kfree(txq->meta);
- txq->cmd = NULL;
- txq->meta = NULL;
-
- /* 0-fill queue descriptor structure */
- memset(txq, 0, sizeof(*txq));
-}
-
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -443,6 +328,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
return -EIO;
}
+ if ((priv->ucode_owner == IWL_OWNERSHIP_TM) &&
+ !(cmd->flags & CMD_ON_DEMAND)) {
+ IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+ return -EIO;
+ }
+
copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr);
@@ -496,11 +387,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd = txq->cmd[idx];
out_meta = &txq->meta[idx];
- if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return -ENOSPC;
- }
-
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
if (cmd->flags & CMD_WANT_SKB)
out_meta->source = cmd;
@@ -574,7 +460,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
#endif
}
- out_meta->flags = cmd->flags | CMD_MAPPED;
+ out_meta->flags = cmd->flags;
txq->need_update = 1;
@@ -684,7 +570,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
wake_up_interruptible(&priv->wait_command_queue);
}
- /* Mark as unmapped */
meta->flags = 0;
spin_unlock_irqrestore(&priv->hcmd_lock, flags);