Commit 64bb1b94 authored by Kalle Valo's avatar Kalle Valo

Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of...

Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

* more work on d0i3 power state
* enhancements to the firmware debugging infrastructure
* support for 2 concurrent channel contexts
* fixes / cleanups in the rate control
* general cleanups
parents dd955398 834437da
...@@ -64,22 +64,8 @@ ...@@ -64,22 +64,8 @@
* *
******************************************************************************/ ******************************************************************************/
/*
* module name, copyright, version, etc.
*/
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
#ifdef CONFIG_IWLWIFI_DEBUG
#define VD "d"
#else
#define VD
#endif
#define DRV_VERSION IWLWIFI_VERSION VD
MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -1011,13 +997,11 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) ...@@ -1011,13 +997,11 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
if (priv->lib->bt_params) if (priv->lib->bt_params)
iwlagn_bt_setup_deferred_work(priv); iwlagn_bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic); setup_timer(&priv->statistics_periodic, iwl_bg_statistics_periodic,
priv->statistics_periodic.data = (unsigned long)priv; (unsigned long)priv);
priv->statistics_periodic.function = iwl_bg_statistics_periodic;
init_timer(&priv->ucode_trace); setup_timer(&priv->ucode_trace, iwl_bg_ucode_trace,
priv->ucode_trace.data = (unsigned long)priv; (unsigned long)priv);
priv->ucode_trace.function = iwl_bg_ucode_trace;
} }
void iwl_cancel_deferred_work(struct iwl_priv *priv) void iwl_cancel_deferred_work(struct iwl_priv *priv)
......
...@@ -612,15 +612,10 @@ void iwl_tt_initialize(struct iwl_priv *priv) ...@@ -612,15 +612,10 @@ void iwl_tt_initialize(struct iwl_priv *priv)
memset(tt, 0, sizeof(struct iwl_tt_mgmt)); memset(tt, 0, sizeof(struct iwl_tt_mgmt));
tt->state = IWL_TI_0; tt->state = IWL_TI_0;
init_timer(&priv->thermal_throttle.ct_kill_exit_tm); setup_timer(&priv->thermal_throttle.ct_kill_exit_tm,
priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; iwl_tt_check_exit_ct_kill, (unsigned long)priv);
priv->thermal_throttle.ct_kill_exit_tm.function = setup_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
iwl_tt_check_exit_ct_kill; iwl_tt_ready_for_ct_kill, (unsigned long)priv);
init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
priv->thermal_throttle.ct_kill_waiting_tm.data =
(unsigned long)priv;
priv->thermal_throttle.ct_kill_waiting_tm.function =
iwl_tt_ready_for_ct_kill;
/* setup deferred ct kill work */ /* setup deferred ct kill work */
INIT_WORK(&priv->tt_work, iwl_bg_tt_work); INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
......
...@@ -92,6 +92,12 @@ ...@@ -92,6 +92,12 @@
#define IWL7265D_NVM_VERSION 0x0c11 #define IWL7265D_NVM_VERSION 0x0c11
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
/* DCCM offsets and lengths */
#define IWL7000_DCCM_OFFSET 0x800000
#define IWL7260_DCCM_LEN 0x14000
#define IWL3160_DCCM_LEN 0x10000
#define IWL7265_DCCM_LEN 0x17A00
#define IWL7260_FW_PRE "iwlwifi-7260-" #define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
...@@ -138,7 +144,8 @@ static const struct iwl_ht_params iwl7000_ht_params = { ...@@ -138,7 +144,8 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \ .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \
.non_shared_ant = ANT_A, \ .non_shared_ant = ANT_A, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.dccm_offset = IWL7000_DCCM_OFFSET
const struct iwl_cfg iwl7260_2ac_cfg = { const struct iwl_cfg iwl7260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7260", .name = "Intel(R) Dual Band Wireless AC 7260",
...@@ -149,6 +156,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { ...@@ -149,6 +156,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.lp_xtal_workaround = true, .lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
}; };
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
...@@ -161,6 +169,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { ...@@ -161,6 +169,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
.high_temp = true, .high_temp = true,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.lp_xtal_workaround = true, .lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
}; };
const struct iwl_cfg iwl7260_2n_cfg = { const struct iwl_cfg iwl7260_2n_cfg = {
...@@ -172,6 +181,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { ...@@ -172,6 +181,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.lp_xtal_workaround = true, .lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
}; };
const struct iwl_cfg iwl7260_n_cfg = { const struct iwl_cfg iwl7260_n_cfg = {
...@@ -183,6 +193,7 @@ const struct iwl_cfg iwl7260_n_cfg = { ...@@ -183,6 +193,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.lp_xtal_workaround = true, .lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
}; };
const struct iwl_cfg iwl3160_2ac_cfg = { const struct iwl_cfg iwl3160_2ac_cfg = {
...@@ -193,6 +204,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = { ...@@ -193,6 +204,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
}; };
const struct iwl_cfg iwl3160_2n_cfg = { const struct iwl_cfg iwl3160_2n_cfg = {
...@@ -203,6 +215,7 @@ const struct iwl_cfg iwl3160_2n_cfg = { ...@@ -203,6 +215,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
}; };
const struct iwl_cfg iwl3160_n_cfg = { const struct iwl_cfg iwl3160_n_cfg = {
...@@ -213,6 +226,7 @@ const struct iwl_cfg iwl3160_n_cfg = { ...@@ -213,6 +226,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION, .nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION, .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true, .host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
}; };
static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = { static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
...@@ -240,6 +254,7 @@ const struct iwl_cfg iwl3165_2ac_cfg = { ...@@ -240,6 +254,7 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
.nvm_ver = IWL3165_NVM_VERSION, .nvm_ver = IWL3165_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION, .nvm_calib_ver = IWL3165_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265_2ac_cfg = { const struct iwl_cfg iwl7265_2ac_cfg = {
...@@ -250,6 +265,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = { ...@@ -250,6 +265,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265_2n_cfg = { const struct iwl_cfg iwl7265_2n_cfg = {
...@@ -260,6 +276,7 @@ const struct iwl_cfg iwl7265_2n_cfg = { ...@@ -260,6 +276,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265_n_cfg = { const struct iwl_cfg iwl7265_n_cfg = {
...@@ -270,6 +287,7 @@ const struct iwl_cfg iwl7265_n_cfg = { ...@@ -270,6 +287,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265d_2ac_cfg = { const struct iwl_cfg iwl7265d_2ac_cfg = {
...@@ -280,6 +298,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = { ...@@ -280,6 +298,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265d_2n_cfg = { const struct iwl_cfg iwl7265d_2n_cfg = {
...@@ -290,6 +309,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = { ...@@ -290,6 +309,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl7265d_n_cfg = { const struct iwl_cfg iwl7265d_n_cfg = {
...@@ -300,6 +320,7 @@ const struct iwl_cfg iwl7265d_n_cfg = { ...@@ -300,6 +320,7 @@ const struct iwl_cfg iwl7265d_n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
}; };
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
......
...@@ -81,12 +81,19 @@ ...@@ -81,12 +81,19 @@
#define IWL8000_NVM_VERSION 0x0a1d #define IWL8000_NVM_VERSION 0x0a1d
#define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */
/* Memory offsets and lengths */
#define IWL8260_DCCM_OFFSET 0x800000
#define IWL8260_DCCM_LEN 0x18000
#define IWL8260_SMEM_OFFSET 0x400000
#define IWL8260_SMEM_LEN 0x68000
#define IWL8000_FW_PRE "iwlwifi-8000" #define IWL8000_FW_PRE "iwlwifi-8000"
#define IWL8000_MODULE_FIRMWARE(api) \ #define IWL8000_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE "-" __stringify(api) ".ucode" IWL8000_FW_PRE "-" __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10 #define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" #define DEFAULT_NVM_FILE_FAMILY_8000A "iwl_nvm_8000.bin"
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000B.bin"
/* Max SDIO RX aggregation size of the ADDBA request/response */ /* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28 #define MAX_RX_AGG_SIZE_8260_SDIO 28
...@@ -124,7 +131,11 @@ static const struct iwl_ht_params iwl8000_ht_params = { ...@@ -124,7 +131,11 @@ static const struct iwl_ht_params iwl8000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \ .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.d0i3 = true, \ .d0i3 = true, \
.non_shared_ant = ANT_A .non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \
.dccm_len = IWL8260_DCCM_LEN, \
.smem_offset = IWL8260_SMEM_OFFSET, \
.smem_len = IWL8260_SMEM_LEN
const struct iwl_cfg iwl8260_2n_cfg = { const struct iwl_cfg iwl8260_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 8260", .name = "Intel(R) Dual Band Wireless N 8260",
...@@ -153,6 +164,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = { ...@@ -153,6 +164,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO, .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
.disable_dummy_notification = true, .disable_dummy_notification = true,
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO, .max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
...@@ -167,6 +179,7 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { ...@@ -167,6 +179,7 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO, .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
.bt_shared_single_ant = true, .bt_shared_single_ant = true,
.disable_dummy_notification = true, .disable_dummy_notification = true,
......
...@@ -261,6 +261,10 @@ struct iwl_pwr_tx_backoff { ...@@ -261,6 +261,10 @@ struct iwl_pwr_tx_backoff {
* station can receive in HT * station can receive in HT
* @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the * @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the
* station can receive in VHT * station can receive in VHT
* @dccm_offset: offset from which DCCM begins
* @dccm_len: length of DCCM (including runtime stack CCM)
* @smem_offset: offset from which the SMEM begins
* @smem_len: the length of SMEM
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -298,11 +302,16 @@ struct iwl_cfg { ...@@ -298,11 +302,16 @@ struct iwl_cfg {
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init; bool no_power_up_nic_in_init;
const char *default_nvm_file; const char *default_nvm_file;
const char *default_nvm_file_8000A;
unsigned int max_rx_agg_size; unsigned int max_rx_agg_size;
bool disable_dummy_notification; bool disable_dummy_notification;
unsigned int max_tx_agg_size; unsigned int max_tx_agg_size;
unsigned int max_ht_ampdu_exponent; unsigned int max_ht_ampdu_exponent;
unsigned int max_vht_ampdu_exponent; unsigned int max_vht_ampdu_exponent;
const u32 dccm_offset;
const u32 dccm_len;
const u32 smem_offset;
const u32 smem_len;
}; };
/* /*
...@@ -370,7 +379,6 @@ extern const struct iwl_cfg iwl7265d_n_cfg; ...@@ -370,7 +379,6 @@ extern const struct iwl_cfg iwl7265d_n_cfg;
extern const struct iwl_cfg iwl8260_2n_cfg; extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg; extern const struct iwl_cfg iwl8260_2ac_cfg;
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4265_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
#endif /* CONFIG_IWLMVM */ #endif /* CONFIG_IWLMVM */
......
...@@ -184,6 +184,7 @@ ...@@ -184,6 +184,7 @@
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
#define CSR_HW_IF_CONFIG_REG_ENABLE_PME (0x10000000)
#define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */ #define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */
#define CSR_MBOX_SET_REG_OS_ALIVE BIT(5) #define CSR_MBOX_SET_REG_OS_ALIVE BIT(5)
......
...@@ -84,21 +84,8 @@ ...@@ -84,21 +84,8 @@
* *
******************************************************************************/ ******************************************************************************/
/*
* module name, copyright, version, etc.
*/
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux" #define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux"
#ifdef CONFIG_IWLWIFI_DEBUG
#define VD "d"
#else
#define VD
#endif
#define DRV_VERSION IWLWIFI_VERSION VD
MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -250,9 +237,6 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) ...@@ -250,9 +237,6 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
/* /*
* Starting 8000B - FW name format has changed. This overwrites the * Starting 8000B - FW name format has changed. This overwrites the
* previous name and uses the new format. * previous name and uses the new format.
*
* TODO:
* Once there is only one supported step for 8000 family - delete this!
*/ */
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
char rev_step[2] = { char rev_step[2] = {
...@@ -263,13 +247,6 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) ...@@ -263,13 +247,6 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP) if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
rev_step[0] = 0; rev_step[0] = 0;
/*
* If hw_rev wasn't set yet - default as B-step. If it IS A-step
* we'll reload that FW later instead.
*/
if (drv->trans->hw_rev == 0)
rev_step[0] = 'B';
snprintf(drv->firmware_name, sizeof(drv->firmware_name), snprintf(drv->firmware_name, sizeof(drv->firmware_name),
"%s%s-%s.ucode", name_pre, rev_step, tag); "%s%s-%s.ucode", name_pre, rev_step, tag);
} }
...@@ -926,6 +903,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -926,6 +903,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
IWL_UCODE_REGULAR_USNIFFER, IWL_UCODE_REGULAR_USNIFFER,
tlv_len); tlv_len);
break; break;
case IWL_UCODE_TLV_SDIO_ADMA_ADDR:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
drv->fw.sdio_adma_addr =
le32_to_cpup((__le32 *)tlv_data);
break;
default: default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break; break;
...@@ -1082,7 +1065,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1082,7 +1065,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
u32 api_ver; u32 api_ver;
int i; int i;
bool load_module = false; bool load_module = false;
u32 hw_rev = drv->trans->hw_rev;
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size = fw->ucode_capa.standard_phy_calibration_size =
...@@ -1275,50 +1257,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1275,50 +1257,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
op->name, err); op->name, err);
#endif #endif
} }
/*
* We may have loaded the wrong FW file in 8000 HW family if it is an
* A-step card, and if drv->trans->hw_rev wasn't properly read when
* the FW file had been loaded. (This might happen in SDIO.) In such a
* case - unload and reload the correct file.
*
* TODO:
* Once there is only one supported step for 8000 family - delete this!
*/
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP &&
drv->trans->hw_rev != hw_rev) {
char firmware_name[32];
/* Free previous FW resources */
if (drv->op_mode)
_iwl_op_mode_stop(drv);
iwl_dealloc_ucode(drv);
/* Build name of correct-step FW */
snprintf(firmware_name, sizeof(firmware_name),
strrchr(drv->firmware_name, '-'));
snprintf(drv->firmware_name, sizeof(drv->firmware_name),
"%s%s", drv->cfg->fw_name_pre, firmware_name);
/* Clear data before loading correct FW */
list_del(&drv->list);
/* Request correct FW file this time */
IWL_DEBUG_INFO(drv, "attempting to load A-step FW %s\n",
drv->firmware_name);
err = request_firmware(&ucode_raw, drv->firmware_name,
drv->trans->dev);
if (err) {
IWL_ERR(drv, "Failed swapping FW!\n");
goto out_unbind;
}
/* Redo callback function - this time with right FW */
iwl_req_fw_callback(ucode_raw, context);
}
kfree(pieces);
return; return;
try_again: try_again:
...@@ -1430,6 +1368,7 @@ struct iwl_mod_params iwlwifi_mod_params = { ...@@ -1430,6 +1368,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true, .bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1, .power_level = IWL_POWER_INDEX_1,
.wd_disable = true, .wd_disable = true,
.d0i3_disable = true,
#ifndef CONFIG_IWLWIFI_UAPSD #ifndef CONFIG_IWLWIFI_UAPSD
.uapsd_disable = true, .uapsd_disable = true,
#endif /* CONFIG_IWLWIFI_UAPSD */ #endif /* CONFIG_IWLWIFI_UAPSD */
...@@ -1492,7 +1431,7 @@ static int __init iwl_drv_init(void) ...@@ -1492,7 +1431,7 @@ static int __init iwl_drv_init(void)
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv); INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv);
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); pr_info(DRV_DESCRIPTION "\n");
pr_info(DRV_COPYRIGHT "\n"); pr_info(DRV_COPYRIGHT "\n");
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
...@@ -1546,6 +1485,10 @@ MODULE_PARM_DESC(wd_disable, ...@@ -1546,6 +1485,10 @@ MODULE_PARM_DESC(wd_disable,
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);
MODULE_PARM_DESC(nvm_file, "NVM file name"); MODULE_PARM_DESC(nvm_file, "NVM file name");
module_param_named(d0i3_disable, iwlwifi_mod_params.d0i3_disable,
bool, S_IRUGO);
MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)");
module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable,
bool, S_IRUGO); bool, S_IRUGO);
#ifdef CONFIG_IWLWIFI_UAPSD #ifdef CONFIG_IWLWIFI_UAPSD
......
...@@ -68,7 +68,6 @@ ...@@ -68,7 +68,6 @@
/* for all modules */ /* for all modules */
#define DRV_NAME "iwlwifi" #define DRV_NAME "iwlwifi"
#define IWLWIFI_VERSION "in-tree:"
#define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation" #define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>" #define DRV_AUTHOR "<ilw@linux.intel.com>"
......
...@@ -71,7 +71,6 @@ ...@@ -71,7 +71,6 @@
/** /**
* enum iwl_fw_error_dump_type - types of data in the dump file * enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0 * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF: * @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
...@@ -82,9 +81,10 @@ ...@@ -82,9 +81,10 @@
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file. * sections like this in a single file.
* @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers * @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
* @IWL_FW_ERROR_DUMP_MEM: chunk of memory
*/ */
enum iwl_fw_error_dump_type { enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0, /* 0 is deprecated */
IWL_FW_ERROR_DUMP_CSR = 1, IWL_FW_ERROR_DUMP_CSR = 1,
IWL_FW_ERROR_DUMP_RXF = 2, IWL_FW_ERROR_DUMP_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3, IWL_FW_ERROR_DUMP_TXCMD = 3,
...@@ -93,6 +93,7 @@ enum iwl_fw_error_dump_type { ...@@ -93,6 +93,7 @@ enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_PRPH = 6, IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_TXF = 7, IWL_FW_ERROR_DUMP_TXF = 7,
IWL_FW_ERROR_DUMP_FH_REGS = 8, IWL_FW_ERROR_DUMP_FH_REGS = 8,
IWL_FW_ERROR_DUMP_MEM = 9,
IWL_FW_ERROR_DUMP_MAX, IWL_FW_ERROR_DUMP_MAX,
}; };
...@@ -180,6 +181,23 @@ struct iwl_fw_error_dump_prph { ...@@ -180,6 +181,23 @@ struct iwl_fw_error_dump_prph {
__le32 data[]; __le32 data[];
}; };
enum iwl_fw_error_dump_mem_type {
IWL_FW_ERROR_DUMP_MEM_SRAM,
IWL_FW_ERROR_DUMP_MEM_SMEM,
};
/**
* struct iwl_fw_error_dump_mem - chunk of memory
* @type: %enum iwl_fw_error_dump_mem_type
* @offset: the offset from which the memory was read
* @data: the content of the memory
*/
struct iwl_fw_error_dump_mem {
__le32 type;
__le32 offset;
u8 data[];
};
/** /**
* iwl_fw_error_next_data - advance fw error dump data pointer * iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block * @data: previous data block
......
...@@ -132,6 +132,7 @@ enum iwl_ucode_tlv_type { ...@@ -132,6 +132,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30, IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
IWL_UCODE_TLV_N_SCAN_CHANNELS = 31, IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
IWL_UCODE_TLV_SEC_RT_USNIFFER = 34, IWL_UCODE_TLV_SEC_RT_USNIFFER = 34,
IWL_UCODE_TLV_SDIO_ADMA_ADDR = 35,
IWL_UCODE_TLV_FW_DBG_DEST = 38, IWL_UCODE_TLV_FW_DBG_DEST = 38,
IWL_UCODE_TLV_FW_DBG_CONF = 39, IWL_UCODE_TLV_FW_DBG_CONF = 39,
}; };
......
...@@ -152,6 +152,8 @@ struct iwl_fw_cscheme_list { ...@@ -152,6 +152,8 @@ struct iwl_fw_cscheme_list {
* @mvm_fw: indicates this is MVM firmware * @mvm_fw: indicates this is MVM firmware
* @cipher_scheme: optional external cipher scheme. * @cipher_scheme: optional external cipher scheme.
* @human_readable: human readable version * @human_readable: human readable version
* @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
* we get the ALIVE from the uCode
* @dbg_dest_tlv: points to the destination TLV for debug * @dbg_dest_tlv: points to the destination TLV for debug
* @dbg_conf_tlv: array of pointers to configuration TLVs for debug * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
* @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries * @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries
...@@ -181,6 +183,8 @@ struct iwl_fw { ...@@ -181,6 +183,8 @@ struct iwl_fw {
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
u32 sdio_adma_addr;
struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv; struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX]; struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
size_t dbg_conf_tlv_len[FW_DBG_MAX]; size_t dbg_conf_tlv_len[FW_DBG_MAX];
......
...@@ -103,6 +103,7 @@ enum iwl_disable_11n { ...@@ -103,6 +103,7 @@ enum iwl_disable_11n {
* @power_level: power level, default = 1 * @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_* * @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0 * @ant_coupling: antenna coupling in dB, default = 0
* @d0i3_disable: disable d0i3, default = 1,
* @fw_monitor: allow to use firmware monitor * @fw_monitor: allow to use firmware monitor
*/ */
struct iwl_mod_params { struct iwl_mod_params {
...@@ -121,6 +122,7 @@ struct iwl_mod_params { ...@@ -121,6 +122,7 @@ struct iwl_mod_params {
int ant_coupling; int ant_coupling;
char *nvm_file; char *nvm_file;
bool uapsd_disable; bool uapsd_disable;
bool d0i3_disable;
bool fw_monitor; bool fw_monitor;
}; };
......
...@@ -468,6 +468,8 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, ...@@ -468,6 +468,8 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg); data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg); data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg); data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(radio_cfg);
data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
} }
static void iwl_set_hw_address(const struct iwl_cfg *cfg, static void iwl_set_hw_address(const struct iwl_cfg *cfg,
...@@ -592,6 +594,10 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, ...@@ -592,6 +594,10 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw); radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw);
iwl_set_radio_cfg(cfg, data, radio_cfg); iwl_set_radio_cfg(cfg, data, radio_cfg);
if (data->valid_tx_ant)
tx_chains &= data->valid_tx_ant;
if (data->valid_rx_ant)
rx_chains &= data->valid_rx_ant;
sku = iwl_get_sku(cfg, nvm_sw); sku = iwl_get_sku(cfg, nvm_sw);
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
......
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
#define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200) #define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
#define APMG_PCIDEV_STT_VAL_WAKE_ME (0x00004000)
#define APMG_RTC_INT_STT_RFKILL (0x10000000) #define APMG_RTC_INT_STT_RFKILL (0x10000000)
...@@ -365,11 +366,15 @@ enum secure_load_status_reg { ...@@ -365,11 +366,15 @@ enum secure_load_status_reg {
#define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c)
/* FW monitor */ /* FW monitor */
#define MON_BUFF_SAMPLE_CTL (0xa03c00)
#define MON_BUFF_BASE_ADDR (0xa03c3c) #define MON_BUFF_BASE_ADDR (0xa03c3c)
#define MON_BUFF_END_ADDR (0xa03c40) #define MON_BUFF_END_ADDR (0xa03c40)
#define MON_BUFF_WRPTR (0xa03c44) #define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48) #define MON_BUFF_CYCLE_CNT (0xa03c48)
#define DBGC_IN_SAMPLE (0xa03c00)
#define DBGC_OUT_CTRL (0xa03c0c)
/* FW chicken bits */ /* FW chicken bits */
#define LMPM_CHICK 0xA01FF8 #define LMPM_CHICK 0xA01FF8
enum { enum {
......
...@@ -382,6 +382,8 @@ enum iwl_trans_status { ...@@ -382,6 +382,8 @@ enum iwl_trans_status {
* are considered stuck and will trigger device restart * are considered stuck and will trigger device restart
* @command_names: array of command names, must be 256 entries * @command_names: array of command names, must be 256 entries
* (one for each command); for debugging only * (one for each command); for debugging only
* @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
* we get the ALIVE from the uCode
*/ */
struct iwl_trans_config { struct iwl_trans_config {
struct iwl_op_mode *op_mode; struct iwl_op_mode *op_mode;
...@@ -396,6 +398,8 @@ struct iwl_trans_config { ...@@ -396,6 +398,8 @@ struct iwl_trans_config {
bool scd_set_active; bool scd_set_active;
unsigned int queue_watchdog_timeout; unsigned int queue_watchdog_timeout;
const char *const *command_names; const char *const *command_names;
u32 sdio_adma_addr;
}; };
struct iwl_trans_dump_data { struct iwl_trans_dump_data {
...@@ -551,6 +555,21 @@ enum iwl_trans_state { ...@@ -551,6 +555,21 @@ enum iwl_trans_state {
IWL_TRANS_FW_ALIVE = 1, IWL_TRANS_FW_ALIVE = 1,
}; };
/**
* enum iwl_d0i3_mode - d0i3 mode
*
* @IWL_D0I3_MODE_OFF - d0i3 is disabled
* @IWL_D0I3_MODE_ON_IDLE - enter d0i3 when device is idle
* (e.g. no active references)
* @IWL_D0I3_MODE_ON_SUSPEND - enter d0i3 only on suspend
* (in case of 'any' trigger)
*/
enum iwl_d0i3_mode {
IWL_D0I3_MODE_OFF = 0,
IWL_D0I3_MODE_ON_IDLE,
IWL_D0I3_MODE_ON_SUSPEND,
};
/** /**
* struct iwl_trans - transport common data * struct iwl_trans - transport common data
* *
...@@ -612,6 +631,8 @@ struct iwl_trans { ...@@ -612,6 +631,8 @@ struct iwl_trans {
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX]; const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
u8 dbg_dest_reg_num; u8 dbg_dest_reg_num;
enum iwl_d0i3_mode d0i3_mode;
/* pointer to trans specific struct */ /* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */ /*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *)); char trans_specific[0] __aligned(sizeof(void *));
......
...@@ -989,7 +989,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, ...@@ -989,7 +989,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_bt_iterator_data *data = _data; struct iwl_bt_iterator_data *data = _data;
struct iwl_mvm *mvm = data->mvm; struct iwl_mvm *mvm = data->mvm;
...@@ -1025,7 +1025,7 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, ...@@ -1025,7 +1025,7 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event rssi_event) enum ieee80211_rssi_event rssi_event)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_bt_iterator_data data = { struct iwl_bt_iterator_data data = {
.mvm = mvm, .mvm = mvm,
}; };
......
...@@ -1034,7 +1034,7 @@ int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm, ...@@ -1034,7 +1034,7 @@ int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_bt_iterator_data *data = _data; struct iwl_bt_iterator_data *data = _data;
struct iwl_mvm *mvm = data->mvm; struct iwl_mvm *mvm = data->mvm;
...@@ -1070,7 +1070,7 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, ...@@ -1070,7 +1070,7 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum ieee80211_rssi_event rssi_event) enum ieee80211_rssi_event rssi_event)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_bt_iterator_data data = { struct iwl_bt_iterator_data data = {
.mvm = mvm, .mvm = mvm,
}; };
......
...@@ -102,5 +102,33 @@ ...@@ -102,5 +102,33 @@
#define IWL_MVM_QUOTA_THRESHOLD 8 #define IWL_MVM_QUOTA_THRESHOLD 8
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_DISABLE_MIMO 0 #define IWL_MVM_RS_DISABLE_MIMO 0
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_LEGACY_RETRIES_PER_RATE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1
#define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES 3
#define IWL_MVM_RS_INITIAL_SISO_NUM_RATES 3
#define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES 16
#define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES 16
#define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES 3
#define IWL_MVM_RS_SECONDARY_SISO_RETRIES 1
#define IWL_MVM_RS_RATE_MIN_FAILURE_TH 3
#define IWL_MVM_RS_RATE_MIN_SUCCESS_TH 8
#define IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT 5 /* Seconds */
#define IWL_MVM_RS_IDLE_TIMEOUT 5 /* Seconds */
#define IWL_MVM_RS_MISSED_RATE_MAX 15
#define IWL_MVM_RS_LEGACY_FAILURE_LIMIT 160
#define IWL_MVM_RS_LEGACY_SUCCESS_LIMIT 480
#define IWL_MVM_RS_LEGACY_TABLE_COUNT 160
#define IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT 400
#define IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT 4500
#define IWL_MVM_RS_NON_LEGACY_TABLE_COUNT 1500
#define IWL_MVM_RS_SR_FORCE_DECREASE 15 /* percent */
#define IWL_MVM_RS_SR_NO_DECREASE 85 /* percent */
#define IWL_MVM_RS_AGG_TIME_LIMIT 4000 /* 4 msecs. valid 100-8000 */
#define IWL_MVM_RS_AGG_DISABLE_START 3
#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE 75 /* percent */
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
#endif /* __MVM_CONSTANTS_H */ #endif /* __MVM_CONSTANTS_H */
...@@ -793,7 +793,7 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, ...@@ -793,7 +793,7 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
struct ieee80211_sta *ap_sta) struct ieee80211_sta *ap_sta)
{ {
int ret; int ret;
struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; struct iwl_mvm_sta *mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
/* TODO: wowlan_config_cmd->wowlan_ba_teardown_tids */ /* TODO: wowlan_config_cmd->wowlan_ba_teardown_tids */
...@@ -1137,12 +1137,43 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, ...@@ -1137,12 +1137,43 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_enter_d0i3_sync(struct iwl_mvm *mvm)
{
struct iwl_notification_wait wait_d3;
static const u8 d3_notif[] = { D3_CONFIG_CMD };
int ret;
iwl_init_notification_wait(&mvm->notif_wait, &wait_d3,
d3_notif, ARRAY_SIZE(d3_notif),
NULL, NULL);
ret = iwl_mvm_enter_d0i3(mvm->hw->priv);
if (ret)
goto remove_notif;
ret = iwl_wait_notification(&mvm->notif_wait, &wait_d3, HZ);
WARN_ON_ONCE(ret);
return ret;
remove_notif:
iwl_remove_notification(&mvm->notif_wait, &wait_d3);
return ret;
}
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
iwl_trans_suspend(mvm->trans); iwl_trans_suspend(mvm->trans);
if (iwl_mvm_is_d0i3_supported(mvm)) { if (wowlan->any) {
/* 'any' trigger means d0i3 usage */
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
int ret = iwl_mvm_enter_d0i3_sync(mvm);
if (ret)
return ret;
}
mutex_lock(&mvm->d0i3_suspend_mutex); mutex_lock(&mvm->d0i3_suspend_mutex);
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex); mutex_unlock(&mvm->d0i3_suspend_mutex);
...@@ -1626,7 +1657,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, ...@@ -1626,7 +1657,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
if (IS_ERR_OR_NULL(ap_sta)) if (IS_ERR_OR_NULL(ap_sta))
goto out_free; goto out_free;
mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
for (i = 0; i < IWL_MAX_TID_COUNT; i++) { for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
u16 seq = status.qos_seq_ctr[i]; u16 seq = status.qos_seq_ctr[i];
/* firmware stores last-used value, we store next value */ /* firmware stores last-used value, we store next value */
...@@ -1876,8 +1907,20 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) ...@@ -1876,8 +1907,20 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
iwl_trans_resume(mvm->trans); iwl_trans_resume(mvm->trans);
if (iwl_mvm_is_d0i3_supported(mvm)) if (mvm->hw->wiphy->wowlan_config->any) {
/* 'any' trigger means d0i3 usage */
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
int ret = iwl_mvm_exit_d0i3(hw->priv);
if (ret)
return ret;
/*
* d0i3 exit will be deferred until reconfig_complete.
* make sure there we are out of d0i3.
*/
}
return 0; return 0;
}
return __iwl_mvm_resume(mvm, false); return __iwl_mvm_resume(mvm, false);
} }
......
...@@ -268,7 +268,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, ...@@ -268,7 +268,7 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
lockdep_is_held(&mvm->mutex)); lockdep_is_held(&mvm->mutex));
if (!IS_ERR_OR_NULL(sta)) { if (!IS_ERR_OR_NULL(sta)) {
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
pos += scnprintf(buf+pos, bufsz-pos, pos += scnprintf(buf+pos, bufsz-pos,
"ap_sta_id %d - reduced Tx power %d\n", "ap_sta_id %d - reduced Tx power %d\n",
......
...@@ -933,7 +933,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, ...@@ -933,7 +933,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
return -EINVAL; return -EINVAL;
if (scan_rx_ant > ANT_ABC) if (scan_rx_ant > ANT_ABC)
return -EINVAL; return -EINVAL;
if (scan_rx_ant & ~mvm->fw->valid_rx_ant) if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
return -EINVAL; return -EINVAL;
if (mvm->scan_rx_ant != scan_rx_ant) { if (mvm->scan_rx_ant != scan_rx_ant) {
...@@ -945,6 +945,56 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, ...@@ -945,6 +945,56 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
return count; return count;
} }
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
enum iwl_fw_dbg_conf conf;
char buf[8];
const size_t bufsz = sizeof(buf);
int pos = 0;
mutex_lock(&mvm->mutex);
conf = mvm->fw_dbg_conf;
mutex_unlock(&mvm->mutex);
pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
int ret, conf_id;
ret = kstrtoint(buf, 0, &conf_id);
if (ret)
return ret;
if (WARN_ON(conf_id >= FW_DBG_MAX))
return -EINVAL;
mutex_lock(&mvm->mutex);
ret = iwl_mvm_start_fw_dbg_conf(mvm, conf_id);
mutex_unlock(&mvm->mutex);
return ret ?: count;
}
static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
mutex_lock(&mvm->mutex);
iwl_mvm_fw_dbg_collect(mvm);
mutex_unlock(&mvm->mutex);
return count;
}
#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__) #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file, static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
...@@ -1459,6 +1509,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); ...@@ -1459,6 +1509,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
...@@ -1500,6 +1552,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) ...@@ -1500,6 +1552,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
S_IWUSR | S_IRUSR); S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
......
...@@ -653,8 +653,11 @@ enum iwl_scan_channel_flags { ...@@ -653,8 +653,11 @@ enum iwl_scan_channel_flags {
}; };
/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S /* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
* @flags: enum iwl_scan_channel_flgs * @flags: enum iwl_scan_channel_flags
* @non_ebs_ratio: how many regular scan iteration before EBS * @non_ebs_ratio: defines the ratio of number of scan iterations where EBS is
* involved.
* 1 - EBS is disabled.
* 2 - every second scan will be full scan(and so on).
*/ */
struct iwl_scan_channel_opt { struct iwl_scan_channel_opt {
__le16 flags; __le16 flags;
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#include "iwl-debug.h" #include "iwl-debug.h"
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */ #include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */ #include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-prph.h"
#include "iwl-eeprom-parse.h" #include "iwl-eeprom-parse.h"
#include "mvm.h" #include "mvm.h"
...@@ -269,7 +270,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) ...@@ -269,7 +270,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
enum iwl_ucode_type ucode_type = mvm->cur_ucode; enum iwl_ucode_type ucode_type = mvm->cur_ucode;
/* Set parameters */ /* Set parameters */
phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config); phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm));
phy_cfg_cmd.calib_control.event_trigger = phy_cfg_cmd.calib_control.event_trigger =
mvm->fw->default_calib[ucode_type].event_trigger; mvm->fw->default_calib[ucode_type].event_trigger;
phy_cfg_cmd.calib_control.flow_trigger = phy_cfg_cmd.calib_control.flow_trigger =
...@@ -346,7 +347,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -346,7 +347,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
mvm->calibrating = true; mvm->calibrating = true;
/* Send TX valid antennas before triggering calibrations */ /* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
if (ret) if (ret)
goto error; goto error;
...@@ -399,8 +400,26 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -399,8 +400,26 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
return ret; return ret;
} }
static int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm)
enum iwl_fw_dbg_conf conf_id) {
lockdep_assert_held(&mvm->mutex);
/* stop recording */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
} else {
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
}
iwl_mvm_fw_error_dump(mvm);
/* start recording again */
WARN_ON_ONCE(mvm->fw->dbg_dest_tlv &&
iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
}
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id)
{ {
u8 *ptr; u8 *ptr;
int ret; int ret;
...@@ -489,7 +508,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -489,7 +508,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
mvm->fw_dbg_conf = FW_DBG_INVALID; mvm->fw_dbg_conf = FW_DBG_INVALID;
iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_CUSTOM); iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_CUSTOM);
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
if (ret) if (ret)
goto error; goto error;
...@@ -584,7 +603,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) ...@@ -584,7 +603,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error; goto error;
} }
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
if (ret) if (ret)
goto error; goto error;
......
...@@ -975,7 +975,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, ...@@ -975,7 +975,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags); beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags);
mvm->mgmt_last_antenna_idx = mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm),
mvm->mgmt_last_antenna_idx); mvm->mgmt_last_antenna_idx);
beacon_cmd.tx.rate_n_flags = beacon_cmd.tx.rate_n_flags =
......
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
#include "testmode.h" #include "testmode.h"
#include "iwl-fw-error-dump.h" #include "iwl-fw-error-dump.h"
#include "iwl-prph.h" #include "iwl-prph.h"
#include "iwl-csr.h"
static const struct ieee80211_iface_limit iwl_mvm_limits[] = { static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
{ {
...@@ -105,7 +106,7 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { ...@@ -105,7 +106,7 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
{ {
.num_different_channels = 1, .num_different_channels = 2,
.max_interfaces = 3, .max_interfaces = 3,
.limits = iwl_mvm_limits, .limits = iwl_mvm_limits,
.n_limits = ARRAY_SIZE(iwl_mvm_limits), .n_limits = ARRAY_SIZE(iwl_mvm_limits),
...@@ -377,6 +378,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -377,6 +378,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->max_remain_on_channel_duration = 10000; hw->wiphy->max_remain_on_channel_duration = 10000;
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
/* we can compensate an offset of up to 3 channels = 15 MHz */
hw->wiphy->max_adj_channel_rssi_comp = 3 * 5;
/* Extract MAC address */ /* Extract MAC address */
memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
...@@ -459,11 +462,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -459,11 +462,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
device_can_wakeup(mvm->trans->dev)) { device_can_wakeup(mvm->trans->dev)) {
mvm->wowlan.flags = WIPHY_WOWLAN_ANY; mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
hw->wiphy->wowlan = &mvm->wowlan; hw->wiphy->wowlan = &mvm->wowlan;
} else if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && }
if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_suspend &&
mvm->trans->ops->d3_resume && mvm->trans->ops->d3_resume &&
device_can_wakeup(mvm->trans->dev)) { device_can_wakeup(mvm->trans->dev)) {
mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | mvm->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ | WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE | WIPHY_WOWLAN_RFKILL_RELEASE |
...@@ -766,22 +771,37 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -766,22 +771,37 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info; struct iwl_fw_error_dump_info *dump_info;
struct iwl_fw_error_dump_mem *dump_mem;
struct iwl_mvm_dump_ptrs *fw_error_dump; struct iwl_mvm_dump_ptrs *fw_error_dump;
const struct fw_img *img;
u32 sram_len, sram_ofs; u32 sram_len, sram_ofs;
u32 file_len, rxf_len; u32 file_len, rxf_len;
unsigned long flags; unsigned long flags;
int reg_val; int reg_val;
u32 smem_len = mvm->cfg->smem_len;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* W/A for 8000 HW family A-step */
if (mvm->cfg->smem_len &&
mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
smem_len = 0x38000;
fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
if (!fw_error_dump) if (!fw_error_dump)
return; return;
/* SRAM - include stack CCM if driver knows the values for it */
if (!mvm->cfg->dccm_offset || !mvm->cfg->dccm_len) {
const struct fw_img *img;
img = &mvm->fw->img[mvm->cur_ucode]; img = &mvm->fw->img[mvm->cur_ucode];
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
} else {
sram_ofs = mvm->cfg->dccm_offset;
sram_len = mvm->cfg->dccm_len;
}
/* reading buffer size */ /* reading buffer size */
reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR); reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR);
...@@ -792,10 +812,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -792,10 +812,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
file_len = sizeof(*dump_file) + file_len = sizeof(*dump_file) +
sizeof(*dump_data) * 3 + sizeof(*dump_data) * 3 +
sram_len + sram_len + sizeof(*dump_mem) +
rxf_len + rxf_len +
sizeof(*dump_info); sizeof(*dump_info);
/* Make room for the SMEM, if it exists */
if (smem_len)
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len;
dump_file = vzalloc(file_len); dump_file = vzalloc(file_len);
if (!dump_file) { if (!dump_file) {
kfree(fw_error_dump); kfree(fw_error_dump);
...@@ -814,6 +838,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -814,6 +838,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ? mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) : cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8); cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(mvm->trans->hw_rev));
memcpy(dump_info->fw_human_readable, mvm->fw->human_readable, memcpy(dump_info->fw_human_readable, mvm->fw->human_readable,
sizeof(dump_info->fw_human_readable)); sizeof(dump_info->fw_human_readable));
strncpy(dump_info->dev_human_readable, mvm->cfg->name, strncpy(dump_info->dev_human_readable, mvm->cfg->name,
...@@ -840,11 +865,25 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -840,11 +865,25 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
} }
dump_data = iwl_fw_error_next_data(dump_data); dump_data = iwl_fw_error_next_data(dump_data);
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram_len); dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data, dump_mem = (void *)dump_data->data;
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
dump_mem->offset = cpu_to_le32(sram_ofs);
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_mem->data,
sram_len); sram_len);
if (smem_len) {
dump_data = iwl_fw_error_next_data(dump_data);
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SMEM);
dump_mem->offset = cpu_to_le32(mvm->cfg->smem_offset);
iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->smem_offset,
dump_mem->data, smem_len);
}
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans); fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
fw_error_dump->op_mode_len = file_len; fw_error_dump->op_mode_len = file_len;
if (fw_error_dump->trans_ptr) if (fw_error_dump->trans_ptr)
...@@ -864,6 +903,11 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ...@@ -864,6 +903,11 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status)) if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status))
iwl_mvm_fw_error_dump(mvm); iwl_mvm_fw_error_dump(mvm);
/* cleanup all stale references (scan, roc), but keep the
* ucode_down ref until reconfig is complete
*/
iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
iwl_trans_stop_device(mvm->trans); iwl_trans_stop_device(mvm->trans);
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
...@@ -893,10 +937,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ...@@ -893,10 +937,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw); ieee80211_wake_queues(mvm->hw);
/* cleanup all stale references (scan, roc), but keep the
* ucode_down ref until reconfig is complete */
iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
/* clear any stale d0i3 state */ /* clear any stale d0i3 state */
clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
...@@ -933,6 +973,19 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) ...@@ -933,6 +973,19 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
/* Some hw restart cleanups must not hold the mutex */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/*
* Make sure we are out of d0i3. This is needed
* to make sure the reference accounting is correct
* (and there is no stale d0i3_exit_work).
*/
wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ);
}
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
ret = __iwl_mvm_mac_start(mvm); ret = __iwl_mvm_mac_start(mvm);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
...@@ -982,6 +1035,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm) ...@@ -982,6 +1035,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n"); IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
_iwl_mvm_exit_d0i3(mvm); _iwl_mvm_exit_d0i3(mvm);
} }
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND)
if (!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ))
WARN_ONCE(1, "D0i3 exit on resume timed out\n");
} }
static void static void
...@@ -2088,7 +2148,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, ...@@ -2088,7 +2148,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
/* /*
* This is called before mac80211 does RCU synchronisation, * This is called before mac80211 does RCU synchronisation,
...@@ -3103,7 +3163,7 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, ...@@ -3103,7 +3163,7 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
bool set) bool set)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
if (!mvm_sta || !mvm_sta->vif) { if (!mvm_sta || !mvm_sta->vif) {
IWL_ERR(mvm, "Station is not associated to a vif\n"); IWL_ERR(mvm, "Station is not associated to a vif\n");
......
...@@ -850,6 +850,8 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id) ...@@ -850,6 +850,8 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
{ {
return mvm->trans->cfg->d0i3 && return mvm->trans->cfg->d0i3 &&
mvm->trans->d0i3_mode != IWL_D0I3_MODE_OFF &&
!iwlwifi_mod_params.d0i3_disable &&
(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
} }
...@@ -937,6 +939,33 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, ...@@ -937,6 +939,33 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic); int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
static inline u8 iwl_mvm_get_valid_tx_ant(struct iwl_mvm *mvm)
{
return mvm->nvm_data && mvm->nvm_data->valid_tx_ant ?
mvm->fw->valid_tx_ant & mvm->nvm_data->valid_tx_ant :
mvm->fw->valid_tx_ant;
}
static inline u8 iwl_mvm_get_valid_rx_ant(struct iwl_mvm *mvm)
{
return mvm->nvm_data && mvm->nvm_data->valid_rx_ant ?
mvm->fw->valid_rx_ant & mvm->nvm_data->valid_rx_ant :
mvm->fw->valid_rx_ant;
}
static inline u32 iwl_mvm_get_phy_config(struct iwl_mvm *mvm)
{
u32 phy_config = ~(FW_PHY_CFG_TX_CHAIN |
FW_PHY_CFG_RX_CHAIN);
u32 valid_rx_ant = iwl_mvm_get_valid_rx_ant(mvm);
u32 valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm);
phy_config |= valid_tx_ant << FW_PHY_CFG_TX_CHAIN_POS |
valid_rx_ant << FW_PHY_CFG_RX_CHAIN_POS;
return mvm->fw->phy_config & phy_config;
}
int iwl_mvm_up(struct iwl_mvm *mvm); int iwl_mvm_up(struct iwl_mvm *mvm);
int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm);
...@@ -1159,6 +1188,8 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); ...@@ -1159,6 +1188,8 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
bool iwl_mvm_ref_taken(struct iwl_mvm *mvm); bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode);
int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
/* BT Coex */ /* BT Coex */
...@@ -1344,4 +1375,7 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); ...@@ -1344,4 +1375,7 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf id);
void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm);
#endif /* __IWL_MVM_H__ */ #endif /* __IWL_MVM_H__ */
...@@ -84,15 +84,8 @@ ...@@ -84,15 +84,8 @@
#include "time-event.h" #include "time-event.h"
#include "iwl-fw-error-dump.h" #include "iwl-fw-error-dump.h"
/*
* module name, copyright, version, etc.
*/
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
#define DRV_VERSION IWLWIFI_VERSION
MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -146,12 +139,13 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) ...@@ -146,12 +139,13 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
u32 reg_val = 0; u32 reg_val = 0;
u32 phy_config = iwl_mvm_get_phy_config(mvm);
radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >> radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >>
FW_PHY_CFG_RADIO_TYPE_POS; FW_PHY_CFG_RADIO_TYPE_POS;
radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >> radio_cfg_step = (phy_config & FW_PHY_CFG_RADIO_STEP) >>
FW_PHY_CFG_RADIO_STEP_POS; FW_PHY_CFG_RADIO_STEP_POS;
radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >> radio_cfg_dash = (phy_config & FW_PHY_CFG_RADIO_DASH) >>
FW_PHY_CFG_RADIO_DASH_POS; FW_PHY_CFG_RADIO_DASH_POS;
/* SKU control */ /* SKU control */
...@@ -487,6 +481,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -487,6 +481,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD; trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
trans_cfg.scd_set_active = true; trans_cfg.scd_set_active = true;
trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
snprintf(mvm->hw->wiphy->fw_version, snprintf(mvm->hw->wiphy->fw_version,
sizeof(mvm->hw->wiphy->fw_version), sizeof(mvm->hw->wiphy->fw_version),
"%s", fw->fw_version); "%s", fw->fw_version);
...@@ -517,10 +513,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -517,10 +513,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
min_backoff = calc_min_backoff(trans, cfg); min_backoff = calc_min_backoff(trans, cfg);
iwl_mvm_tt_initialize(mvm, min_backoff); iwl_mvm_tt_initialize(mvm, min_backoff);
/* set the nvm_file_name according to priority */ /* set the nvm_file_name according to priority */
if (iwlwifi_mod_params.nvm_file) if (iwlwifi_mod_params.nvm_file) {
mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
} else {
if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
(CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP))
mvm->nvm_file_name = mvm->cfg->default_nvm_file_8000A;
else else
mvm->nvm_file_name = mvm->cfg->default_nvm_file; mvm->nvm_file_name = mvm->cfg->default_nvm_file;
}
if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name, if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
"not allowing power-up and not having nvm_file\n")) "not allowing power-up and not having nvm_file\n"))
...@@ -1031,7 +1032,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, ...@@ -1031,7 +1032,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
out: out:
rcu_read_unlock(); rcu_read_unlock();
} }
static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
{ {
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE; u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
...@@ -1047,6 +1049,7 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) ...@@ -1047,6 +1049,7 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
}; };
struct iwl_d3_manager_config d3_cfg_cmd = { struct iwl_d3_manager_config d3_cfg_cmd = {
.min_sleep_time = cpu_to_le32(1000), .min_sleep_time = cpu_to_le32(1000),
.wakeup_flags = cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR),
}; };
IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n"); IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
...@@ -1146,7 +1149,7 @@ void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq) ...@@ -1146,7 +1149,7 @@ void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
if (mvm->d0i3_offloading && qos_seq) { if (mvm->d0i3_offloading && qos_seq) {
/* update qos seq numbers if offloading was enabled */ /* update qos seq numbers if offloading was enabled */
mvm_ap_sta = (struct iwl_mvm_sta *)sta->drv_priv; mvm_ap_sta = iwl_mvm_sta_from_mac80211(sta);
for (i = 0; i < IWL_MAX_TID_COUNT; i++) { for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
u16 seq = le16_to_cpu(qos_seq[i]); u16 seq = le16_to_cpu(qos_seq[i]);
/* firmware stores last-used one, we store next one */ /* firmware stores last-used one, we store next one */
...@@ -1245,7 +1248,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm) ...@@ -1245,7 +1248,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
return ret; return ret;
} }
static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
{ {
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
......
...@@ -176,7 +176,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, ...@@ -176,7 +176,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
cmd->rxchain_info |= cpu_to_le32(active_cnt << cmd->rxchain_info |= cpu_to_le32(active_cnt <<
PHY_RX_CHAIN_MIMO_CNT_POS); PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = cpu_to_le32(mvm->fw->valid_tx_ant); cmd->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
} }
/* /*
......
This diff is collapsed.
...@@ -137,42 +137,10 @@ enum { ...@@ -137,42 +137,10 @@ enum {
#define IWL_INVALID_VALUE -1 #define IWL_INVALID_VALUE -1
#define IWL_MIN_RSSI_VAL -100
#define IWL_MAX_RSSI_VAL 0
/* These values specify how many Tx frame attempts before
* searching for a new modulation mode */
#define IWL_LEGACY_FAILURE_LIMIT 160
#define IWL_LEGACY_SUCCESS_LIMIT 480
#define IWL_LEGACY_TABLE_COUNT 160
#define IWL_NONE_LEGACY_FAILURE_LIMIT 400
#define IWL_NONE_LEGACY_SUCCESS_LIMIT 4500
#define IWL_NONE_LEGACY_TABLE_COUNT 1500
/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
#define IWL_RS_GOOD_RATIO 12800 /* 100% */
#define IWL_RATE_SCALE_SWITCH 10880 /* 85% */
#define IWL_RATE_HIGH_TH 10880 /* 85% */
#define IWL_RATE_INCREASE_TH 6400 /* 50% */
#define RS_SR_FORCE_DECREASE 1920 /* 15% */
#define RS_SR_NO_DECREASE 10880 /* 85% */
#define TPC_SR_FORCE_INCREASE 9600 /* 75% */
#define TPC_SR_NO_INCREASE 10880 /* 85% */
#define TPC_TX_POWER_STEP 3
#define TPC_MAX_REDUCTION 15 #define TPC_MAX_REDUCTION 15
#define TPC_NO_REDUCTION 0 #define TPC_NO_REDUCTION 0
#define TPC_INVALID 0xff #define TPC_INVALID 0xff
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000)
#define LINK_QUAL_AGG_TIME_LIMIT_MIN (100)
#define LINK_QUAL_AGG_DISABLE_START_DEF (3)
#define LINK_QUAL_AGG_DISABLE_START_MAX (255)
#define LINK_QUAL_AGG_DISABLE_START_MIN (0)
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63) #define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) #define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) #define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
...@@ -181,14 +149,7 @@ enum { ...@@ -181,14 +149,7 @@ enum {
/* load per tid defines for A-MPDU activation */ /* load per tid defines for A-MPDU activation */
#define IWL_AGG_TPT_THREHOLD 0 #define IWL_AGG_TPT_THREHOLD 0
#define IWL_AGG_LOAD_THRESHOLD 10
#define IWL_AGG_ALL_TID 0xff #define IWL_AGG_ALL_TID 0xff
#define TID_QUEUE_CELL_SPACING 50 /*mS */
#define TID_QUEUE_MAX_SIZE 20
#define TID_ROUND_VALUE 5 /* mS */
#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
enum iwl_table_type { enum iwl_table_type {
LQ_NONE, LQ_NONE,
......
...@@ -72,6 +72,8 @@ ...@@ -72,6 +72,8 @@
#define IWL_PLCP_QUIET_THRESH 1 #define IWL_PLCP_QUIET_THRESH 1
#define IWL_ACTIVE_QUIET_TIME 10 #define IWL_ACTIVE_QUIET_TIME 10
#define IWL_DENSE_EBS_SCAN_RATIO 5
#define IWL_SPARSE_EBS_SCAN_RATIO 1
struct iwl_mvm_scan_params { struct iwl_mvm_scan_params {
u32 max_out_time; u32 max_out_time;
...@@ -97,7 +99,7 @@ static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) ...@@ -97,7 +99,7 @@ static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
{ {
if (mvm->scan_rx_ant != ANT_NONE) if (mvm->scan_rx_ant != ANT_NONE)
return mvm->scan_rx_ant; return mvm->scan_rx_ant;
return mvm->fw->valid_rx_ant; return iwl_mvm_get_valid_rx_ant(mvm);
} }
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
...@@ -128,7 +130,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, ...@@ -128,7 +130,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
u32 tx_ant; u32 tx_ant;
mvm->scan_last_antenna_idx = mvm->scan_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm),
mvm->scan_last_antenna_idx); mvm->scan_last_antenna_idx);
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
...@@ -282,11 +284,11 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, ...@@ -282,11 +284,11 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *global_bound = data; int *global_cnt = data;
if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt && if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
mvmvif->phy_ctxt->id < MAX_PHYS) mvmvif->phy_ctxt->id < MAX_PHYS)
*global_bound = true; *global_cnt += 1;
} }
static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
...@@ -294,16 +296,16 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, ...@@ -294,16 +296,16 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
int n_ssids, u32 flags, int n_ssids, u32 flags,
struct iwl_mvm_scan_params *params) struct iwl_mvm_scan_params *params)
{ {
bool global_bound = false; int global_cnt = 0;
enum ieee80211_band band; enum ieee80211_band band;
u8 frag_passive_dwell = 0; u8 frag_passive_dwell = 0;
ieee80211_iterate_active_interfaces_atomic(mvm->hw, ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_scan_condition_iterator, iwl_mvm_scan_condition_iterator,
&global_bound); &global_cnt);
if (!global_bound) if (!global_cnt)
goto not_bound; goto not_bound;
params->suspend_time = 30; params->suspend_time = 30;
...@@ -314,7 +316,11 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, ...@@ -314,7 +316,11 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
IWL_UCODE_TLV_API_FRAGMENTED_SCAN) { IWL_UCODE_TLV_API_FRAGMENTED_SCAN) {
params->suspend_time = 105; params->suspend_time = 105;
params->max_out_time = 70; params->max_out_time = 70;
frag_passive_dwell = 20; /*
* If there is more than one active interface make
* passive scan more fragmented.
*/
frag_passive_dwell = (global_cnt < 2) ? 40 : 20;
} else { } else {
params->suspend_time = 120; params->suspend_time = 120;
params->max_out_time = 120; params->max_out_time = 120;
...@@ -1296,10 +1302,14 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm, ...@@ -1296,10 +1302,14 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
cmd->channel_opt[0].non_ebs_ratio =
cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO);
cmd->channel_opt[1].flags = cmd->channel_opt[1].flags =
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
cmd->channel_opt[1].non_ebs_ratio =
cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO);
} }
if (iwl_mvm_rrm_scan_needed(mvm)) if (iwl_mvm_rrm_scan_needed(mvm))
...@@ -1603,7 +1613,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) ...@@ -1603,7 +1613,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
SCAN_CONFIG_FLAG_SET_MAC_ADDR | SCAN_CONFIG_FLAG_SET_MAC_ADDR |
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS| SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
SCAN_CONFIG_N_CHANNELS(num_channels)); SCAN_CONFIG_N_CHANNELS(num_channels));
scan_config->tx_chains = cpu_to_le32(mvm->fw->valid_tx_ant); scan_config->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm)); scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm); scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
scan_config->out_of_channel_time = cpu_to_le32(170); scan_config->out_of_channel_time = cpu_to_le32(170);
......
...@@ -99,7 +99,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, ...@@ -99,7 +99,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update) bool update)
{ {
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd add_sta_cmd = { struct iwl_mvm_add_sta_cmd add_sta_cmd = {
.sta_id = mvm_sta->sta_id, .sta_id = mvm_sta->sta_id,
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color), .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
...@@ -259,7 +259,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, ...@@ -259,7 +259,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int i, ret, sta_id; int i, ret, sta_id;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -481,7 +481,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, ...@@ -481,7 +481,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int ret; int ret;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -774,7 +774,7 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -774,7 +774,7 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u16 ssn, bool start) int tid, u16 ssn, bool start)
{ {
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {}; struct iwl_mvm_add_sta_cmd cmd = {};
int ret; int ret;
u32 status; u32 status;
...@@ -834,7 +834,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -834,7 +834,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u8 queue, bool start) int tid, u8 queue, bool start)
{ {
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {}; struct iwl_mvm_add_sta_cmd cmd = {};
int ret; int ret;
u32 status; u32 status;
...@@ -1144,10 +1144,10 @@ static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) ...@@ -1144,10 +1144,10 @@ static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif, static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (sta) { if (sta) {
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
return mvm_sta->sta_id; return mvm_sta->sta_id;
} }
...@@ -1280,7 +1280,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm, ...@@ -1280,7 +1280,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (sta) if (sta)
return sta->addr; return sta->addr;
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm) static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
{ {
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
u32 duration = mvm->thermal_throttle.params->ct_kill_duration; u32 duration = mvm->thermal_throttle.params->ct_kill_duration;
if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
...@@ -77,12 +78,15 @@ static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm) ...@@ -77,12 +78,15 @@ static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
IWL_ERR(mvm, "Enter CT Kill\n"); IWL_ERR(mvm, "Enter CT Kill\n");
iwl_mvm_set_hw_ctkill_state(mvm, true); iwl_mvm_set_hw_ctkill_state(mvm, true);
tt->throttle = false;
tt->dynamic_smps = false;
/* Don't schedule an exit work if we're in test mode, since /* Don't schedule an exit work if we're in test mode, since
* the temperature will not change unless we manually set it * the temperature will not change unless we manually set it
* again (or disable testing). * again (or disable testing).
*/ */
if (!mvm->temperature_test) if (!mvm->temperature_test)
schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit, schedule_delayed_work(&tt->ct_kill_exit,
round_jiffies_relative(duration * HZ)); round_jiffies_relative(duration * HZ));
} }
...@@ -452,6 +456,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff) ...@@ -452,6 +456,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff)
tt->params = &iwl7000_tt_params; tt->params = &iwl7000_tt_params;
tt->throttle = false; tt->throttle = false;
tt->dynamic_smps = false;
tt->min_backoff = min_backoff; tt->min_backoff = min_backoff;
INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
} }
......
...@@ -209,7 +209,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, ...@@ -209,7 +209,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
mvm->mgmt_last_antenna_idx = mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm),
mvm->mgmt_last_antenna_idx); mvm->mgmt_last_antenna_idx);
if (info->band == IEEE80211_BAND_2GHZ && if (info->band == IEEE80211_BAND_2GHZ &&
......
...@@ -620,7 +620,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -620,7 +620,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */
if (num_of_ant(mvm->fw->valid_rx_ant) == 1) if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
return; return;
if (vif->type == NL80211_IFTYPE_AP) if (vif->type == NL80211_IFTYPE_AP)
...@@ -662,7 +662,7 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) ...@@ -662,7 +662,7 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (num_of_ant(mvm->fw->valid_rx_ant) == 1) if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
return false; return false;
if (!mvm->cfg->rx_with_siso_diversity) if (!mvm->cfg->rx_with_siso_diversity)
......
...@@ -318,6 +318,11 @@ struct iwl_trans_pcie { ...@@ -318,6 +318,11 @@ struct iwl_trans_pcie {
/*protect hw register */ /*protect hw register */
spinlock_t reg_lock; spinlock_t reg_lock;
bool cmd_in_flight; bool cmd_in_flight;
bool ref_cmd_in_flight;
/* protect ref counter */
spinlock_t ref_lock;
u32 ref_count;
dma_addr_t fw_mon_phys; dma_addr_t fw_mon_phys;
struct page *fw_mon_page; struct page *fw_mon_page;
...@@ -381,6 +386,9 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, ...@@ -381,6 +386,9 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs); struct sk_buff_head *skbs);
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
void iwl_trans_pcie_ref(struct iwl_trans *trans);
void iwl_trans_pcie_unref(struct iwl_trans *trans);
static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
{ {
struct iwl_tfd_tb *tb = &tfd->tbs[idx]; struct iwl_tfd_tb *tb = &tfd->tbs[idx];
......
...@@ -443,10 +443,25 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) ...@@ -443,10 +443,25 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
return ret; return ret;
} }
static void iwl_pcie_apm_stop(struct iwl_trans *trans) static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
{ {
IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
if (op_mode_leave) {
if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))
iwl_pcie_apm_init(trans);
/* inform ME that we are leaving */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME);
else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PREPARE |
CSR_HW_IF_CONFIG_REG_ENABLE_PME);
mdelay(5);
}
clear_bit(STATUS_DEVICE_ENABLED, &trans->status); clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
/* Stop device's DMA activity */ /* Stop device's DMA activity */
...@@ -893,6 +908,9 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans, ...@@ -893,6 +908,9 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
if (ret) if (ret)
return ret; return ret;
if (trans->dbg_dest_tlv)
iwl_pcie_apply_destination(trans);
/* Notify FW loading is done */ /* Notify FW loading is done */
iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF); iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF);
...@@ -916,6 +934,7 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans, ...@@ -916,6 +934,7 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill) const struct fw_img *fw, bool run_in_rfkill)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret; int ret;
bool hw_rfkill; bool hw_rfkill;
...@@ -945,6 +964,9 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, ...@@ -945,6 +964,9 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
return ret; return ret;
} }
/* init ref_count to 1 (should be cleared when ucode is loaded) */
trans_pcie->ref_count = 1;
/* make sure rfkill handshake bits are cleared */ /* make sure rfkill handshake bits are cleared */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
...@@ -1010,7 +1032,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -1010,7 +1032,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_apm_stop(trans); iwl_pcie_apm_stop(trans, false);
/* stop and reset the on-board processor */ /* stop and reset the on-board processor */
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
...@@ -1192,7 +1214,7 @@ static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) ...@@ -1192,7 +1214,7 @@ static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans)
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
spin_unlock(&trans_pcie->irq_lock); spin_unlock(&trans_pcie->irq_lock);
iwl_pcie_apm_stop(trans); iwl_pcie_apm_stop(trans, true);
spin_lock(&trans_pcie->irq_lock); spin_lock(&trans_pcie->irq_lock);
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
...@@ -1540,6 +1562,38 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, ...@@ -1540,6 +1562,38 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
} }
void iwl_trans_pcie_ref(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
if (iwlwifi_mod_params.d0i3_disable)
return;
spin_lock_irqsave(&trans_pcie->ref_lock, flags);
IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count);
trans_pcie->ref_count++;
spin_unlock_irqrestore(&trans_pcie->ref_lock, flags);
}
void iwl_trans_pcie_unref(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;
if (iwlwifi_mod_params.d0i3_disable)
return;
spin_lock_irqsave(&trans_pcie->ref_lock, flags);
IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count);
if (WARN_ON_ONCE(trans_pcie->ref_count == 0)) {
spin_unlock_irqrestore(&trans_pcie->ref_lock, flags);
return;
}
trans_pcie->ref_count--;
spin_unlock_irqrestore(&trans_pcie->ref_lock, flags);
}
static const char *get_csr_string(int cmd) static const char *get_csr_string(int cmd)
{ {
#define IWL_CMD(x) case x: return #x #define IWL_CMD(x) case x: return #x
...@@ -2264,6 +2318,9 @@ static const struct iwl_trans_ops trans_ops_pcie = { ...@@ -2264,6 +2318,9 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.release_nic_access = iwl_trans_pcie_release_nic_access, .release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask, .set_bits_mask = iwl_trans_pcie_set_bits_mask,
.ref = iwl_trans_pcie_ref,
.unref = iwl_trans_pcie_unref,
.dump_data = iwl_trans_pcie_dump_data, .dump_data = iwl_trans_pcie_dump_data,
}; };
...@@ -2404,6 +2461,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ...@@ -2404,6 +2461,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
} }
trans_pcie->inta_mask = CSR_INI_SET_MASK; trans_pcie->inta_mask = CSR_INI_SET_MASK;
trans->d0i3_mode = IWL_D0I3_MODE_ON_SUSPEND;
return trans; return trans;
......
...@@ -985,17 +985,31 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, ...@@ -985,17 +985,31 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
if (iwl_queue_space(&txq->q) > txq->q.low_mark) if (iwl_queue_space(&txq->q) > txq->q.low_mark)
iwl_wake_queue(trans, txq); iwl_wake_queue(trans, txq);
if (q->read_ptr == q->write_ptr) {
IWL_DEBUG_RPM(trans, "Q %d - last tx reclaimed\n", q->id);
iwl_trans_pcie_unref(trans);
}
out: out:
spin_unlock_bh(&txq->lock); spin_unlock_bh(&txq->lock);
} }
static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans) static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
const struct iwl_host_cmd *cmd)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret; int ret;
lockdep_assert_held(&trans_pcie->reg_lock); lockdep_assert_held(&trans_pcie->reg_lock);
if (!(cmd->flags & CMD_SEND_IN_IDLE) &&
!trans_pcie->ref_cmd_in_flight) {
trans_pcie->ref_cmd_in_flight = true;
IWL_DEBUG_RPM(trans, "set ref_cmd_in_flight - ref\n");
iwl_trans_pcie_ref(trans);
}
if (trans_pcie->cmd_in_flight) if (trans_pcie->cmd_in_flight)
return 0; return 0;
...@@ -1036,6 +1050,12 @@ static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) ...@@ -1036,6 +1050,12 @@ static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
lockdep_assert_held(&trans_pcie->reg_lock); lockdep_assert_held(&trans_pcie->reg_lock);
if (trans_pcie->ref_cmd_in_flight) {
trans_pcie->ref_cmd_in_flight = false;
IWL_DEBUG_RPM(trans, "clear ref_cmd_in_flight - unref\n");
iwl_trans_pcie_unref(trans);
}
if (WARN_ON(!trans_pcie->cmd_in_flight)) if (WARN_ON(!trans_pcie->cmd_in_flight))
return 0; return 0;
...@@ -1473,7 +1493,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, ...@@ -1473,7 +1493,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
spin_lock_irqsave(&trans_pcie->reg_lock, flags); spin_lock_irqsave(&trans_pcie->reg_lock, flags);
ret = iwl_pcie_set_cmd_in_flight(trans); ret = iwl_pcie_set_cmd_in_flight(trans, cmd);
if (ret < 0) { if (ret < 0) {
idx = ret; idx = ret;
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
...@@ -1819,9 +1839,13 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, ...@@ -1819,9 +1839,13 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
wait_write_ptr = ieee80211_has_morefrags(fc); wait_write_ptr = ieee80211_has_morefrags(fc);
/* start timer if queue currently empty */ /* start timer if queue currently empty */
if (txq->need_update && q->read_ptr == q->write_ptr && if (q->read_ptr == q->write_ptr) {
trans_pcie->wd_timeout) if (txq->need_update && trans_pcie->wd_timeout)
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); mod_timer(&txq->stuck_timer,
jiffies + trans_pcie->wd_timeout);
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id);
iwl_trans_pcie_ref(trans);
}
/* Tell device the write index *just past* this latest filled TFD */ /* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment