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 @@
*
******************************************************************************/
/*
* module name, copyright, version, etc.
*/
#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_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
......@@ -1011,13 +997,11 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
if (priv->lib->bt_params)
iwlagn_bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl_bg_statistics_periodic;
setup_timer(&priv->statistics_periodic, iwl_bg_statistics_periodic,
(unsigned long)priv);
init_timer(&priv->ucode_trace);
priv->ucode_trace.data = (unsigned long)priv;
priv->ucode_trace.function = iwl_bg_ucode_trace;
setup_timer(&priv->ucode_trace, iwl_bg_ucode_trace,
(unsigned long)priv);
}
void iwl_cancel_deferred_work(struct iwl_priv *priv)
......
......@@ -612,15 +612,10 @@ void iwl_tt_initialize(struct iwl_priv *priv)
memset(tt, 0, sizeof(struct iwl_tt_mgmt));
tt->state = IWL_TI_0;
init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
priv->thermal_throttle.ct_kill_exit_tm.function =
iwl_tt_check_exit_ct_kill;
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_timer(&priv->thermal_throttle.ct_kill_exit_tm,
iwl_tt_check_exit_ct_kill, (unsigned long)priv);
setup_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
iwl_tt_ready_for_ct_kill, (unsigned long)priv);
/* setup deferred ct kill work */
INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
......
......@@ -92,6 +92,12 @@
#define IWL7265D_NVM_VERSION 0x0c11
#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_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
......@@ -138,7 +144,8 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \
.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 = {
.name = "Intel(R) Dual Band Wireless AC 7260",
......@@ -149,6 +156,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
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,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
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,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
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,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2ac_cfg = {
......@@ -193,6 +204,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2n_cfg = {
......@@ -203,6 +215,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_n_cfg = {
......@@ -213,6 +226,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
......@@ -240,6 +254,7 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
.nvm_ver = IWL3165_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2ac_cfg = {
......@@ -250,6 +265,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2n_cfg = {
......@@ -260,6 +276,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_n_cfg = {
......@@ -270,6 +287,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2ac_cfg = {
......@@ -280,6 +298,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2n_cfg = {
......@@ -290,6 +309,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_n_cfg = {
......@@ -300,6 +320,7 @@ const struct iwl_cfg iwl7265d_n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
......
......@@ -81,12 +81,19 @@
#define IWL8000_NVM_VERSION 0x0a1d
#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_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE "-" __stringify(api) ".ucode"
#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 */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
......@@ -124,7 +131,11 @@ static const struct iwl_ht_params iwl8000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.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 = {
.name = "Intel(R) Dual Band Wireless N 8260",
......@@ -153,6 +164,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.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,
.disable_dummy_notification = true,
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
......@@ -167,6 +179,7 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.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,
.bt_shared_single_ant = true,
.disable_dummy_notification = true,
......
......@@ -261,6 +261,10 @@ struct iwl_pwr_tx_backoff {
* station can receive in HT
* @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the
* 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.
* API differences in uCode shouldn't be handled here but through TLVs
......@@ -298,11 +302,16 @@ struct iwl_cfg {
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init;
const char *default_nvm_file;
const char *default_nvm_file_8000A;
unsigned int max_rx_agg_size;
bool disable_dummy_notification;
unsigned int max_tx_agg_size;
unsigned int max_ht_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;
extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_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;
#endif /* CONFIG_IWLMVM */
......
......@@ -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_PREPARE_DONE (0x02000000) /* ME_OWN */
#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_MBOX_SET_REG_OS_ALIVE BIT(5)
......
......@@ -84,21 +84,8 @@
*
******************************************************************************/
/*
* module name, copyright, version, etc.
*/
#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_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
......@@ -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
* 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) {
char rev_step[2] = {
......@@ -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)
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),
"%s%s-%s.ucode", name_pre, rev_step, tag);
}
......@@ -926,6 +903,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
IWL_UCODE_REGULAR_USNIFFER,
tlv_len);
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:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
......@@ -1082,7 +1065,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
u32 api_ver;
int i;
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.standard_phy_calibration_size =
......@@ -1275,50 +1257,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
op->name, err);
#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;
try_again:
......@@ -1430,6 +1368,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1,
.wd_disable = true,
.d0i3_disable = true,
#ifndef CONFIG_IWLWIFI_UAPSD
.uapsd_disable = true,
#endif /* CONFIG_IWLWIFI_UAPSD */
......@@ -1492,7 +1431,7 @@ static int __init iwl_drv_init(void)
for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
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");
#ifdef CONFIG_IWLWIFI_DEBUGFS
......@@ -1546,6 +1485,10 @@ MODULE_PARM_DESC(wd_disable,
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);
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,
bool, S_IRUGO);
#ifdef CONFIG_IWLWIFI_UAPSD
......
......@@ -68,7 +68,6 @@
/* for all modules */
#define DRV_NAME "iwlwifi"
#define IWLWIFI_VERSION "in-tree:"
#define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
......
......@@ -71,7 +71,6 @@
/**
* 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_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
......@@ -82,9 +81,10 @@
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
* @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
* @IWL_FW_ERROR_DUMP_MEM: chunk of memory
*/
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_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3,
......@@ -93,6 +93,7 @@ enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_TXF = 7,
IWL_FW_ERROR_DUMP_FH_REGS = 8,
IWL_FW_ERROR_DUMP_MEM = 9,
IWL_FW_ERROR_DUMP_MAX,
};
......@@ -180,6 +181,23 @@ struct iwl_fw_error_dump_prph {
__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
* @data: previous data block
......
......@@ -132,6 +132,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
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_CONF = 39,
};
......
......@@ -152,6 +152,8 @@ struct iwl_fw_cscheme_list {
* @mvm_fw: indicates this is MVM firmware
* @cipher_scheme: optional external cipher scheme.
* @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_conf_tlv: array of pointers to configuration TLVs for debug
* @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries
......@@ -181,6 +183,8 @@ struct iwl_fw {
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
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_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
size_t dbg_conf_tlv_len[FW_DBG_MAX];
......
......@@ -103,6 +103,7 @@ enum iwl_disable_11n {
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
* @d0i3_disable: disable d0i3, default = 1,
* @fw_monitor: allow to use firmware monitor
*/
struct iwl_mod_params {
......@@ -121,6 +122,7 @@ struct iwl_mod_params {
int ant_coupling;
char *nvm_file;
bool uapsd_disable;
bool d0i3_disable;
bool fw_monitor;
};
......
......@@ -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_dash = NVM_RF_CFG_DASH_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,
......@@ -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);
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);
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
......
......@@ -99,6 +99,7 @@
#define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
#define APMG_PCIDEV_STT_VAL_WAKE_ME (0x00004000)
#define APMG_RTC_INT_STT_RFKILL (0x10000000)
......@@ -365,11 +366,15 @@ enum secure_load_status_reg {
#define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c)
/* FW monitor */
#define MON_BUFF_SAMPLE_CTL (0xa03c00)
#define MON_BUFF_BASE_ADDR (0xa03c3c)
#define MON_BUFF_END_ADDR (0xa03c40)
#define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48)
#define DBGC_IN_SAMPLE (0xa03c00)
#define DBGC_OUT_CTRL (0xa03c0c)
/* FW chicken bits */
#define LMPM_CHICK 0xA01FF8
enum {
......
......@@ -382,6 +382,8 @@ enum iwl_trans_status {
* are considered stuck and will trigger device restart
* @command_names: array of command names, must be 256 entries
* (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_op_mode *op_mode;
......@@ -396,6 +398,8 @@ struct iwl_trans_config {
bool scd_set_active;
unsigned int queue_watchdog_timeout;
const char *const *command_names;
u32 sdio_adma_addr;
};
struct iwl_trans_dump_data {
......@@ -551,6 +555,21 @@ enum iwl_trans_state {
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
*
......@@ -612,6 +631,8 @@ struct iwl_trans {
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
u8 dbg_dest_reg_num;
enum iwl_d0i3_mode d0i3_mode;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
......
......@@ -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,
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_mvm *mvm = data->mvm;
......@@ -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,
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 = {
.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,
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_mvm *mvm = data->mvm;
......@@ -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,
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 = {
.mvm = mvm,
};
......
......@@ -102,5 +102,33 @@
#define IWL_MVM_QUOTA_THRESHOLD 8
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 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 */
......@@ -793,7 +793,7 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
struct ieee80211_sta *ap_sta)
{
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 */
......@@ -1137,12 +1137,43 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
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)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
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);
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
......@@ -1626,7 +1657,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
if (IS_ERR_OR_NULL(ap_sta))
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++) {
u16 seq = status.qos_seq_ctr[i];
/* firmware stores last-used value, we store next value */
......@@ -1876,8 +1907,20 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
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 __iwl_mvm_resume(mvm, false);
}
......
......@@ -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],
lockdep_is_held(&mvm->mutex));
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,
"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,
return -EINVAL;
if (scan_rx_ant > ANT_ABC)
return -EINVAL;
if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
return -EINVAL;
if (mvm->scan_rx_ant != scan_rx_ant) {
......@@ -945,6 +945,56 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
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__)
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
......@@ -1459,6 +1509,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 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(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
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)
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(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
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
......
......@@ -653,8 +653,11 @@ enum iwl_scan_channel_flags {
};
/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
* @flags: enum iwl_scan_channel_flgs
* @non_ebs_ratio: how many regular scan iteration before EBS
* @flags: enum iwl_scan_channel_flags
* @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 {
__le16 flags;
......
......@@ -70,6 +70,7 @@
#include "iwl-debug.h"
#include "iwl-csr.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 "mvm.h"
......@@ -269,7 +270,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
enum iwl_ucode_type ucode_type = mvm->cur_ucode;
/* 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 =
mvm->fw->default_calib[ucode_type].event_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)
mvm->calibrating = true;
/* 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)
goto error;
......@@ -399,8 +400,26 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
return ret;
}
static int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm,
enum iwl_fw_dbg_conf conf_id)
void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm)
{
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;
int ret;
......@@ -489,7 +508,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
mvm->fw_dbg_conf = FW_DBG_INVALID;
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)
goto error;
......@@ -584,7 +603,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
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)
goto error;
......
......@@ -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);
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);
beacon_cmd.tx.rate_n_flags =
......
......@@ -85,6 +85,7 @@
#include "testmode.h"
#include "iwl-fw-error-dump.h"
#include "iwl-prph.h"
#include "iwl-csr.h"
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[] = {
{
.num_different_channels = 1,
.num_different_channels = 2,
.max_interfaces = 3,
.limits = iwl_mvm_limits,
.n_limits = ARRAY_SIZE(iwl_mvm_limits),
......@@ -377,6 +378,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->max_remain_on_channel_duration = 10000;
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 */
memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
......@@ -459,15 +462,17 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
device_can_wakeup(mvm->trans->dev)) {
mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
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_resume &&
device_can_wakeup(mvm->trans->dev)) {
mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE |
WIPHY_WOWLAN_NET_DETECT;
mvm->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_RFKILL_RELEASE |
WIPHY_WOWLAN_NET_DETECT;
if (!iwlwifi_mod_params.sw_crypto)
mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_GTK_REKEY_FAILURE |
......@@ -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_data *dump_data;
struct iwl_fw_error_dump_info *dump_info;
struct iwl_fw_error_dump_mem *dump_mem;
struct iwl_mvm_dump_ptrs *fw_error_dump;
const struct fw_img *img;
u32 sram_len, sram_ofs;
u32 file_len, rxf_len;
unsigned long flags;
int reg_val;
u32 smem_len = mvm->cfg->smem_len;
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);
if (!fw_error_dump)
return;
img = &mvm->fw->img[mvm->cur_ucode];
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
/* 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];
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
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 */
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)
file_len = sizeof(*dump_file) +
sizeof(*dump_data) * 3 +
sram_len +
sram_len + sizeof(*dump_mem) +
rxf_len +
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);
if (!dump_file) {
kfree(fw_error_dump);
......@@ -814,6 +838,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
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_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,
sizeof(dump_info->fw_human_readable));
strncpy(dump_info->dev_human_readable, mvm->cfg->name,
......@@ -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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
dump_data->len = cpu_to_le32(sram_len);
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
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);
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->op_mode_len = file_len;
if (fw_error_dump->trans_ptr)
......@@ -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))
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);
mvm->scan_status = IWL_MVM_SCAN_NONE;
......@@ -893,10 +937,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
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_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
......@@ -933,6 +973,19 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
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);
ret = __iwl_mvm_mac_start(mvm);
mutex_unlock(&mvm->mutex);
......@@ -982,6 +1035,13 @@ static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
_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
......@@ -2088,7 +2148,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
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,
......@@ -3103,7 +3163,7 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
bool set)
{
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) {
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)
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
{
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);
}
......@@ -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_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_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);
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);
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);
/* BT Coex */
......@@ -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_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__ */
......@@ -84,15 +84,8 @@
#include "time-event.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_VERSION IWLWIFI_VERSION
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
......@@ -146,13 +139,14 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
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) >>
FW_PHY_CFG_RADIO_TYPE_POS;
radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
FW_PHY_CFG_RADIO_STEP_POS;
radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
FW_PHY_CFG_RADIO_DASH_POS;
radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >>
FW_PHY_CFG_RADIO_TYPE_POS;
radio_cfg_step = (phy_config & FW_PHY_CFG_RADIO_STEP) >>
FW_PHY_CFG_RADIO_STEP_POS;
radio_cfg_dash = (phy_config & FW_PHY_CFG_RADIO_DASH) >>
FW_PHY_CFG_RADIO_DASH_POS;
/* SKU control */
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
......@@ -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.scd_set_active = true;
trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
snprintf(mvm->hw->wiphy->fw_version,
sizeof(mvm->hw->wiphy->fw_version),
"%s", fw->fw_version);
......@@ -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);
iwl_mvm_tt_initialize(mvm, min_backoff);
/* 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;
else
mvm->nvm_file_name = mvm->cfg->default_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
mvm->nvm_file_name = mvm->cfg->default_nvm_file;
}
if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
"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,
out:
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);
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)
};
struct iwl_d3_manager_config d3_cfg_cmd = {
.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");
......@@ -1146,7 +1149,7 @@ void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
if (mvm->d0i3_offloading && qos_seq) {
/* 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++) {
u16 seq = le16_to_cpu(qos_seq[i]);
/* firmware stores last-used one, we store next one */
......@@ -1245,7 +1248,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
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);
......
......@@ -176,7 +176,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
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 {
#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_NO_REDUCTION 0
#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_MAX (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
......@@ -181,14 +149,7 @@ enum {
/* load per tid defines for A-MPDU activation */
#define IWL_AGG_TPT_THREHOLD 0
#define IWL_AGG_LOAD_THRESHOLD 10
#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 {
LQ_NONE,
......
......@@ -72,6 +72,8 @@
#define IWL_PLCP_QUIET_THRESH 1
#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 {
u32 max_out_time;
......@@ -97,7 +99,7 @@ static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
{
if (mvm->scan_rx_ant != ANT_NONE)
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)
......@@ -128,7 +130,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
u32 tx_ant;
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);
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,
struct ieee80211_vif *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 &&
mvmvif->phy_ctxt->id < MAX_PHYS)
*global_bound = true;
*global_cnt += 1;
}
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,
struct iwl_mvm_scan_params *params)
{
bool global_bound = false;
int global_cnt = 0;
enum ieee80211_band band;
u8 frag_passive_dwell = 0;
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_scan_condition_iterator,
&global_bound);
&global_cnt);
if (!global_bound)
if (!global_cnt)
goto not_bound;
params->suspend_time = 30;
......@@ -314,7 +316,11 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
IWL_UCODE_TLV_API_FRAGMENTED_SCAN) {
params->suspend_time = 105;
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 {
params->suspend_time = 120;
params->max_out_time = 120;
......@@ -1296,10 +1302,14 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
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 =
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
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))
......@@ -1603,7 +1613,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
SCAN_CONFIG_FLAG_SET_MAC_ADDR |
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
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->legacy_rates = iwl_mvm_scan_config_rates(mvm);
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,
int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
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 = {
.sta_id = mvm_sta->sta_id,
.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,
struct ieee80211_sta *sta)
{
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;
lockdep_assert_held(&mvm->mutex);
......@@ -481,7 +481,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
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;
lockdep_assert_held(&mvm->mutex);
......@@ -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 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 = {};
int ret;
u32 status;
......@@ -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,
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 = {};
int ret;
u32 status;
......@@ -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,
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) {
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;
}
......@@ -1280,7 +1280,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
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)
return sta->addr;
......
......@@ -69,6 +69,7 @@
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;
if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
......@@ -77,12 +78,15 @@ static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
IWL_ERR(mvm, "Enter CT Kill\n");
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
* the temperature will not change unless we manually set it
* again (or disable testing).
*/
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));
}
......@@ -452,6 +456,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff)
tt->params = &iwl7000_tt_params;
tt->throttle = false;
tt->dynamic_smps = false;
tt->min_backoff = min_backoff;
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,
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_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);
if (info->band == IEEE80211_BAND_2GHZ &&
......
......@@ -620,7 +620,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
/* 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;
if (vif->type == NL80211_IFTYPE_AP)
......@@ -662,7 +662,7 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm)
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;
if (!mvm->cfg->rx_with_siso_diversity)
......
......@@ -318,6 +318,11 @@ struct iwl_trans_pcie {
/*protect hw register */
spinlock_t reg_lock;
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;
struct page *fw_mon_page;
......@@ -381,6 +386,9 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs);
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)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
......
......@@ -443,10 +443,25 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
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");
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);
/* Stop device's DMA activity */
......@@ -893,6 +908,9 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
if (ret)
return ret;
if (trans->dbg_dest_tlv)
iwl_pcie_apply_destination(trans);
/* Notify FW loading is done */
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,
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
bool hw_rfkill;
......@@ -945,6 +964,9 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
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 */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
......@@ -1010,7 +1032,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* 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 */
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)
iwl_disable_interrupts(trans);
spin_unlock(&trans_pcie->irq_lock);
iwl_pcie_apm_stop(trans);
iwl_pcie_apm_stop(trans, true);
spin_lock(&trans_pcie->irq_lock);
iwl_disable_interrupts(trans);
......@@ -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);
}
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)
{
#define IWL_CMD(x) case x: return #x
......@@ -2264,6 +2318,9 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.release_nic_access = iwl_trans_pcie_release_nic_access,
.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,
};
......@@ -2404,6 +2461,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
trans_pcie->inta_mask = CSR_INI_SET_MASK;
trans->d0i3_mode = IWL_D0I3_MODE_ON_SUSPEND;
return trans;
......
......@@ -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)
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:
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);
int ret;
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)
return 0;
......@@ -1036,6 +1050,12 @@ static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
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))
return 0;
......@@ -1473,7 +1493,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
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) {
idx = ret;
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,
wait_write_ptr = ieee80211_has_morefrags(fc);
/* start timer if queue currently empty */
if (txq->need_update && q->read_ptr == q->write_ptr &&
trans_pcie->wd_timeout)
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
if (q->read_ptr == q->write_ptr) {
if (txq->need_update && 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 */
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