Commit 0971f7d9 authored by John W. Linville's avatar John W. Linville
parents db18014f 82b715c2
...@@ -109,7 +109,7 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg; ...@@ -109,7 +109,7 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
struct iwl_ucode_capabilities; struct iwl_ucode_capabilities;
extern struct ieee80211_ops iwlagn_hw_ops; extern const struct ieee80211_ops iwlagn_hw_ops;
static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
{ {
...@@ -480,7 +480,7 @@ do { \ ...@@ -480,7 +480,7 @@ do { \
} while (0) } while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */ #endif /* CONFIG_IWLWIFI_DEBUG */
extern const char *iwl_dvm_cmd_strings[REPLY_MAX]; extern const char *const iwl_dvm_cmd_strings[REPLY_MAX];
static inline const char *iwl_dvm_get_cmd_string(u8 cmd) static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
{ {
......
...@@ -317,7 +317,7 @@ static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { ...@@ -317,7 +317,7 @@ static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.nrg_th_cca = 62, .nrg_th_cca = 62,
}; };
static struct iwl_sensitivity_ranges iwl5150_sensitivity = { static const struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.min_nrg_cck = 95, .min_nrg_cck = 95,
.auto_corr_min_ofdm = 90, .auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_mrc = 170,
......
...@@ -1564,7 +1564,7 @@ static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, ...@@ -1564,7 +1564,7 @@ static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
struct ieee80211_ops iwlagn_hw_ops = { const struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx, .tx = iwlagn_mac_tx,
.start = iwlagn_mac_start, .start = iwlagn_mac_start,
.stop = iwlagn_mac_stop, .stop = iwlagn_mac_stop,
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define IWL_CMD_ENTRY(x) [x] = #x #define IWL_CMD_ENTRY(x) [x] = #x
const char *iwl_dvm_cmd_strings[REPLY_MAX] = { const char *const iwl_dvm_cmd_strings[REPLY_MAX] = {
IWL_CMD_ENTRY(REPLY_ALIVE), IWL_CMD_ENTRY(REPLY_ALIVE),
IWL_CMD_ENTRY(REPLY_ERROR), IWL_CMD_ENTRY(REPLY_ERROR),
IWL_CMD_ENTRY(REPLY_ECHO), IWL_CMD_ENTRY(REPLY_ECHO),
......
...@@ -404,6 +404,38 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data) ...@@ -404,6 +404,38 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
return 0; return 0;
} }
static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
struct iwl_ucode_capabilities *capa)
{
const struct iwl_ucode_api *ucode_api = (void *)data;
u32 api_index = le32_to_cpu(ucode_api->api_index);
if (api_index >= IWL_API_ARRAY_SIZE) {
IWL_ERR(drv, "api_index larger than supported by driver\n");
return -EINVAL;
}
capa->api[api_index] = le32_to_cpu(ucode_api->api_flags);
return 0;
}
static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
struct iwl_ucode_capabilities *capa)
{
const struct iwl_ucode_capa *ucode_capa = (void *)data;
u32 api_index = le32_to_cpu(ucode_capa->api_index);
if (api_index >= IWL_CAPABILITIES_ARRAY_SIZE) {
IWL_ERR(drv, "api_index larger than supported by driver\n");
return -EINVAL;
}
capa->capa[api_index] = le32_to_cpu(ucode_capa->api_capa);
return 0;
}
static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw, const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces) struct iwl_firmware_pieces *pieces)
...@@ -638,6 +670,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -638,6 +670,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
*/ */
capa->flags = le32_to_cpup((__le32 *)tlv_data); capa->flags = le32_to_cpup((__le32 *)tlv_data);
break; break;
case IWL_UCODE_TLV_API_CHANGES_SET:
if (tlv_len != sizeof(struct iwl_ucode_api))
goto invalid_tlv_len;
if (iwl_set_ucode_api_flags(drv, tlv_data, capa))
goto tlv_error;
break;
case IWL_UCODE_TLV_ENABLED_CAPABILITIES:
if (tlv_len != sizeof(struct iwl_ucode_capa))
goto invalid_tlv_len;
if (iwl_set_ucode_capabilities(drv, tlv_data, capa))
goto tlv_error;
break;
case IWL_UCODE_TLV_INIT_EVTLOG_PTR: case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
if (tlv_len != sizeof(u32)) if (tlv_len != sizeof(u32))
goto invalid_tlv_len; goto invalid_tlv_len;
...@@ -728,6 +772,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -728,6 +772,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(u32)) if (tlv_len != sizeof(u32))
goto invalid_tlv_len; goto invalid_tlv_len;
drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data);
drv->fw.valid_tx_ant = (drv->fw.phy_config &
FW_PHY_CFG_TX_CHAIN) >>
FW_PHY_CFG_TX_CHAIN_POS;
drv->fw.valid_rx_ant = (drv->fw.phy_config &
FW_PHY_CFG_RX_CHAIN) >>
FW_PHY_CFG_RX_CHAIN_POS;
break; break;
case IWL_UCODE_TLV_SECURE_SEC_RT: case IWL_UCODE_TLV_SECURE_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
...@@ -1301,8 +1351,7 @@ MODULE_PARM_DESC(antenna_coupling, ...@@ -1301,8 +1351,7 @@ MODULE_PARM_DESC(antenna_coupling,
module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO);
MODULE_PARM_DESC(wd_disable, MODULE_PARM_DESC(wd_disable,
"Disable stuck queue watchdog timer 0=system default, " "Disable stuck queue watchdog timer 0=system default, 1=disable (default: 1)");
"1=disable, 2=enable (default: 0)");
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");
......
...@@ -70,6 +70,20 @@ ...@@ -70,6 +70,20 @@
#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>"
/* radio config bits (actual values from NVM definition) */
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
#define NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(x) (x & 0xF)
#define NVM_RF_CFG_DASH_MSK_FAMILY_8000(x) ((x >> 4) & 0xF)
#define NVM_RF_CFG_STEP_MSK_FAMILY_8000(x) ((x >> 8) & 0xF)
#define NVM_RF_CFG_TYPE_MSK_FAMILY_8000(x) ((x >> 12) & 0xFFF)
#define NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(x) ((x >> 24) & 0xF)
#define NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(x) ((x >> 28) & 0xF)
/** /**
* DOC: Driver system flows - drv component * DOC: Driver system flows - drv component
......
...@@ -81,16 +81,17 @@ struct iwl_nvm_data { ...@@ -81,16 +81,17 @@ struct iwl_nvm_data {
bool sku_cap_band_24GHz_enable; bool sku_cap_band_24GHz_enable;
bool sku_cap_band_52GHz_enable; bool sku_cap_band_52GHz_enable;
bool sku_cap_11n_enable; bool sku_cap_11n_enable;
bool sku_cap_11ac_enable;
bool sku_cap_amt_enable; bool sku_cap_amt_enable;
bool sku_cap_ipan_enable; bool sku_cap_ipan_enable;
u8 radio_cfg_type; u16 radio_cfg_type;
u8 radio_cfg_step; u8 radio_cfg_step;
u8 radio_cfg_dash; u8 radio_cfg_dash;
u8 radio_cfg_pnum; u8 radio_cfg_pnum;
u8 valid_tx_ant, valid_rx_ant; u8 valid_tx_ant, valid_rx_ant;
u16 nvm_version; u32 nvm_version;
s8 max_tx_pwr_half_dbm; s8 max_tx_pwr_half_dbm;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
......
...@@ -126,6 +126,8 @@ enum iwl_ucode_tlv_type { ...@@ -126,6 +126,8 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
IWL_UCODE_TLV_NUM_OF_CPU = 27, IWL_UCODE_TLV_NUM_OF_CPU = 27,
IWL_UCODE_TLV_CSCHEME = 28, IWL_UCODE_TLV_CSCHEME = 28,
IWL_UCODE_TLV_API_CHANGES_SET = 29,
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
}; };
struct iwl_ucode_tlv { struct iwl_ucode_tlv {
...@@ -158,4 +160,19 @@ struct iwl_tlv_ucode_header { ...@@ -158,4 +160,19 @@ struct iwl_tlv_ucode_header {
u8 data[0]; u8 data[0];
}; };
/*
* ucode TLVs
*
* ability to get extension for: flags & capabilities from ucode binaries files
*/
struct iwl_ucode_api {
__le32 api_index;
__le32 api_flags;
} __packed;
struct iwl_ucode_capa {
__le32 api_index;
__le32 api_capa;
} __packed;
#endif /* __iwl_fw_file_h__ */ #endif /* __iwl_fw_file_h__ */
...@@ -92,8 +92,8 @@ ...@@ -92,8 +92,8 @@
* @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
* @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
* containing CAM (Continuous Active Mode) indication. * containing CAM (Continuous Active Mode) indication.
* @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
* single bound interface). * P2P client interfaces simultaneously if they are in different bindings.
* @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
* @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
* @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
...@@ -118,7 +118,7 @@ enum iwl_ucode_tlv_flag { ...@@ -118,7 +118,7 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17),
IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19),
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20),
IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21), IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
...@@ -165,11 +165,15 @@ enum iwl_ucode_sec { ...@@ -165,11 +165,15 @@ enum iwl_ucode_sec {
* just an offset to the HW address. * just an offset to the HW address.
*/ */
#define IWL_UCODE_SECTION_MAX 12 #define IWL_UCODE_SECTION_MAX 12
#define IWL_API_ARRAY_SIZE 1
#define IWL_CAPABILITIES_ARRAY_SIZE 1
struct iwl_ucode_capabilities { struct iwl_ucode_capabilities {
u32 max_probe_length; u32 max_probe_length;
u32 standard_phy_calibration_size; u32 standard_phy_calibration_size;
u32 flags; u32 flags;
u32 api[IWL_API_ARRAY_SIZE];
u32 capa[IWL_CAPABILITIES_ARRAY_SIZE];
}; };
/* one for each uCode image (inst/data, init/runtime/wowlan) */ /* one for each uCode image (inst/data, init/runtime/wowlan) */
...@@ -288,22 +292,12 @@ struct iwl_fw { ...@@ -288,22 +292,12 @@ struct iwl_fw {
struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX]; struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX];
u32 phy_config; u32 phy_config;
u8 valid_tx_ant;
u8 valid_rx_ant;
bool mvm_fw; bool mvm_fw;
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
}; };
static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
{
return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >>
FW_PHY_CFG_TX_CHAIN_POS;
}
static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
{
return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >>
FW_PHY_CFG_RX_CHAIN_POS;
}
#endif /* __iwl_fw_h__ */ #endif /* __iwl_fw_h__ */
...@@ -93,7 +93,7 @@ enum iwl_power_level { ...@@ -93,7 +93,7 @@ enum iwl_power_level {
* use IWL_DISABLE_HT_* constants * use IWL_DISABLE_HT_* constants
* @amsdu_size_8K: enable 8K amsdu size, default = 0 * @amsdu_size_8K: enable 8K amsdu size, default = 0
* @restart_fw: restart firmware, default = 1 * @restart_fw: restart firmware, default = 1
* @wd_disable: enable stuck queue check, default = 0 * @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true * @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0 * @led_mode: system default, default = 0
* @power_save: disable power save, default = false * @power_save: disable power save, default = false
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
struct iwl_nvm_data * struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains); const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, u8 tx_chains, u8 rx_chains);
#endif /* __iwl_nvm_parse_h__ */ #endif /* __iwl_nvm_parse_h__ */
...@@ -393,7 +393,7 @@ struct iwl_trans_config { ...@@ -393,7 +393,7 @@ struct iwl_trans_config {
bool rx_buf_size_8k; bool rx_buf_size_8k;
bool bc_table_dword; bool bc_table_dword;
unsigned int queue_watchdog_timeout; unsigned int queue_watchdog_timeout;
const char **command_names; const char *const *command_names;
}; };
struct iwl_trans; struct iwl_trans;
......
...@@ -591,7 +591,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -591,7 +591,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
(vif->type == NL80211_IFTYPE_STATION && vif->p2p && (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))) mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
S_IRUSR); S_IRUSR);
......
...@@ -531,6 +531,76 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, ...@@ -531,6 +531,76 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
} }
#undef PRINT_STAT_LE32 #undef PRINT_STAT_LE32
static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
char __user *user_buf, size_t count,
loff_t *ppos,
struct iwl_mvm_frame_stats *stats)
{
char *buff;
int pos = 0, idx, i;
int ret;
size_t bufsz = 1024;
buff = kmalloc(bufsz, GFP_KERNEL);
if (!buff)
return -ENOMEM;
spin_lock_bh(&mvm->drv_stats_lock);
pos += scnprintf(buff + pos, bufsz - pos,
"Legacy/HT/VHT\t:\t%d/%d/%d\n",
stats->legacy_frames,
stats->ht_frames,
stats->vht_frames);
pos += scnprintf(buff + pos, bufsz - pos, "20/40/80\t:\t%d/%d/%d\n",
stats->bw_20_frames,
stats->bw_40_frames,
stats->bw_80_frames);
pos += scnprintf(buff + pos, bufsz - pos, "NGI/SGI\t\t:\t%d/%d\n",
stats->ngi_frames,
stats->sgi_frames);
pos += scnprintf(buff + pos, bufsz - pos, "SISO/MIMO2\t:\t%d/%d\n",
stats->siso_frames,
stats->mimo2_frames);
pos += scnprintf(buff + pos, bufsz - pos, "FAIL/SCSS\t:\t%d/%d\n",
stats->fail_frames,
stats->success_frames);
pos += scnprintf(buff + pos, bufsz - pos, "MPDUs agg\t:\t%d\n",
stats->agg_frames);
pos += scnprintf(buff + pos, bufsz - pos, "A-MPDUs\t\t:\t%d\n",
stats->ampdu_count);
pos += scnprintf(buff + pos, bufsz - pos, "Avg MPDUs/A-MPDU:\t%d\n",
stats->ampdu_count > 0 ?
(stats->agg_frames / stats->ampdu_count) : 0);
pos += scnprintf(buff + pos, bufsz - pos, "Last Rates\n");
idx = stats->last_frame_idx - 1;
for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
if (stats->last_rates[idx] == 0)
continue;
pos += scnprintf(buff + pos, bufsz - pos, "Rate[%d]: ",
(int)(ARRAY_SIZE(stats->last_rates) - i));
pos += rs_pretty_print_rate(buff + pos, stats->last_rates[idx]);
}
spin_unlock_bh(&mvm->drv_stats_lock);
ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos);
kfree(buff);
return ret;
}
static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
&mvm->drv_rx_stats);
}
static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -591,7 +661,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, ...@@ -591,7 +661,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 & ~iwl_fw_valid_rx_ant(mvm->fw)) if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
return -EINVAL; return -EINVAL;
mvm->scan_rx_ant = scan_rx_ant; mvm->scan_rx_ant = scan_rx_ant;
...@@ -907,6 +977,49 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, ...@@ -907,6 +977,49 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
static ssize_t
iwl_dbgfs_prph_reg_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL;
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t
iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
u8 args;
u32 value;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */
if (args == 1)
goto out;
/* otherwise, make sure we have both address and value */
if (args != 2)
return -EINVAL;
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
out:
return count;
}
MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
/* Device wide debugfs entries */ /* Device wide debugfs entries */
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
...@@ -916,6 +1029,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif); ...@@ -916,6 +1029,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
...@@ -947,10 +1061,12 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) ...@@ -947,10 +1061,12 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_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(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
......
...@@ -257,7 +257,8 @@ enum { ...@@ -257,7 +257,8 @@ enum {
/* Bit 17-18: (0) SS, (1) SS*2 */ /* Bit 17-18: (0) SS, (1) SS*2 */
#define RATE_MCS_STBC_POS 17 #define RATE_MCS_STBC_POS 17
#define RATE_MCS_STBC_MSK (1 << RATE_MCS_STBC_POS) #define RATE_MCS_HT_STBC_MSK (3 << RATE_MCS_STBC_POS)
#define RATE_MCS_VHT_STBC_MSK (1 << RATE_MCS_STBC_POS)
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ /* Bit 19: (0) Beamforming is off, (1) Beamforming is on */
#define RATE_MCS_BF_POS 19 #define RATE_MCS_BF_POS 19
......
...@@ -306,7 +306,6 @@ struct iwl_phy_cfg_cmd { ...@@ -306,7 +306,6 @@ struct iwl_phy_cfg_cmd {
#define PHY_CFG_RX_CHAIN_B BIT(13) #define PHY_CFG_RX_CHAIN_B BIT(13)
#define PHY_CFG_RX_CHAIN_C BIT(14) #define PHY_CFG_RX_CHAIN_C BIT(14)
#define NVM_MAX_NUM_SECTIONS 11
/* Target of the NVM_ACCESS_CMD */ /* Target of the NVM_ACCESS_CMD */
enum { enum {
...@@ -318,8 +317,11 @@ enum { ...@@ -318,8 +317,11 @@ enum {
/* Section types for NVM_ACCESS_CMD */ /* Section types for NVM_ACCESS_CMD */
enum { enum {
NVM_SECTION_TYPE_SW = 1, NVM_SECTION_TYPE_SW = 1,
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4, NVM_SECTION_TYPE_CALIBRATION = 4,
NVM_SECTION_TYPE_PRODUCTION = 5, NVM_SECTION_TYPE_PRODUCTION = 5,
NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
NVM_MAX_NUM_SECTIONS = 12,
}; };
/** /**
...@@ -710,6 +712,7 @@ enum { ...@@ -710,6 +712,7 @@ enum {
TE_V2_NOTIF_HOST_FRAG_END = BIT(5), TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
T2_V2_START_IMMEDIATELY = BIT(11),
TE_V2_NOTIF_MSK = 0xff, TE_V2_NOTIF_MSK = 0xff,
......
...@@ -130,7 +130,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, ...@@ -130,7 +130,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
} else { } else {
palive2 = (void *)pkt->data; palive2 = (void *)pkt->data;
mvm->support_umac_log = true;
mvm->error_event_table = mvm->error_event_table =
le32_to_cpu(palive2->error_event_table_ptr); le32_to_cpu(palive2->error_event_table_ptr);
mvm->log_event_table = mvm->log_event_table =
...@@ -141,6 +140,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, ...@@ -141,6 +140,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
alive_data->valid = le16_to_cpu(palive2->status) == alive_data->valid = le16_to_cpu(palive2->status) ==
IWL_ALIVE_STATUS_OK; IWL_ALIVE_STATUS_OK;
if (mvm->umac_error_event_table)
mvm->support_umac_log = true;
IWL_DEBUG_FW(mvm, IWL_DEBUG_FW(mvm,
"Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", "Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
le16_to_cpu(palive2->status), palive2->ver_type, le16_to_cpu(palive2->status), palive2->ver_type,
...@@ -320,7 +322,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -320,7 +322,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
} }
/* Send TX valid antennas before triggering calibrations */ /* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret) if (ret)
goto error; goto error;
...@@ -356,8 +358,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -356,8 +358,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
GFP_KERNEL); GFP_KERNEL);
if (!mvm->nvm_data) if (!mvm->nvm_data)
return -ENOMEM; return -ENOMEM;
mvm->nvm_data->valid_rx_ant = 1;
mvm->nvm_data->valid_tx_ant = 1;
mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels; mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
mvm->nvm_data->bands[0].n_channels = 1; mvm->nvm_data->bands[0].n_channels = 1;
mvm->nvm_data->bands[0].n_bitrates = 1; mvm->nvm_data->bands[0].n_bitrates = 1;
...@@ -369,8 +369,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -369,8 +369,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
return ret; return ret;
} }
#define UCODE_CALIB_TIMEOUT (2*HZ)
int iwl_mvm_up(struct iwl_mvm *mvm) int iwl_mvm_up(struct iwl_mvm *mvm)
{ {
int ret, i; int ret, i;
...@@ -422,7 +420,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -422,7 +420,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret) if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret) if (ret)
goto error; goto error;
...@@ -507,7 +505,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) ...@@ -507,7 +505,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error; goto error;
} }
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret) if (ret)
goto error; goto error;
......
...@@ -952,7 +952,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, ...@@ -952,7 +952,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
TX_CMD_FLG_TSF); TX_CMD_FLG_TSF);
mvm->mgmt_last_antenna_idx = mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->mgmt_last_antenna_idx); mvm->mgmt_last_antenna_idx);
beacon_cmd.tx.rate_n_flags = beacon_cmd.tx.rate_n_flags =
......
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <net/tcp.h> #include <net/tcp.h>
#include "iwl-op-mode.h" #include "iwl-op-mode.h"
...@@ -280,6 +281,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -280,6 +281,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->queues = mvm->first_agg_queue; hw->queues = mvm->first_agg_queue;
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
IEEE80211_RADIOTAP_MCS_HAVE_STBC;
hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
hw->rate_control_algorithm = "iwl-mvm-rs"; hw->rate_control_algorithm = "iwl-mvm-rs";
/* /*
...@@ -1301,7 +1305,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -1301,7 +1305,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
mvmvif->ap_ibss_active = true; mvmvif->ap_ibss_active = true;
/* power updated needs to be done before quotas */ /* power updated needs to be done before quotas */
mvm->bound_vif_cnt++;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
ret = iwl_mvm_update_quotas(mvm, vif); ret = iwl_mvm_update_quotas(mvm, vif);
...@@ -1320,7 +1323,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -1320,7 +1323,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
return 0; return 0;
out_quota_failed: out_quota_failed:
mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
mvmvif->ap_ibss_active = false; mvmvif->ap_ibss_active = false;
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
...@@ -1357,7 +1359,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, ...@@ -1357,7 +1359,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif);
mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
iwl_mvm_mac_ctxt_remove(mvm, vif); iwl_mvm_mac_ctxt_remove(mvm, vif);
...@@ -2093,7 +2094,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -2093,7 +2094,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* Power state must be updated before quotas, * Power state must be updated before quotas,
* otherwise fw will complain. * otherwise fw will complain.
*/ */
mvm->bound_vif_cnt++;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
/* Setting the quota at this stage is only required for monitor /* Setting the quota at this stage is only required for monitor
...@@ -2111,7 +2111,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -2111,7 +2111,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
out_remove_binding: out_remove_binding:
iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif);
mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
out_unlock: out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
...@@ -2144,7 +2143,6 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -2144,7 +2143,6 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
} }
iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif);
mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif); iwl_mvm_power_update_mac(mvm, vif);
out_unlock: out_unlock:
...@@ -2235,7 +2233,7 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, ...@@ -2235,7 +2233,7 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
} }
#endif #endif
struct ieee80211_ops iwl_mvm_hw_ops = { const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx, .tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action, .ampdu_action = iwl_mvm_mac_ampdu_action,
.start = iwl_mvm_mac_start, .start = iwl_mvm_mac_start,
......
...@@ -91,8 +91,7 @@ enum iwl_mvm_tx_fifo { ...@@ -91,8 +91,7 @@ enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_MCAST = 5, IWL_MVM_TX_FIFO_MCAST = 5,
}; };
extern struct ieee80211_ops iwl_mvm_hw_ops; extern const struct ieee80211_ops iwl_mvm_hw_ops;
extern const struct iwl_mvm_power_ops pm_mac_ops;
/** /**
* struct iwl_mvm_mod_params - module parameters for iwlmvm * struct iwl_mvm_mod_params - module parameters for iwlmvm
...@@ -426,6 +425,28 @@ struct iwl_mvm_tt_mgmt { ...@@ -426,6 +425,28 @@ struct iwl_mvm_tt_mgmt {
bool throttle; bool throttle;
}; };
#define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8
struct iwl_mvm_frame_stats {
u32 legacy_frames;
u32 ht_frames;
u32 vht_frames;
u32 bw_20_frames;
u32 bw_40_frames;
u32 bw_80_frames;
u32 bw_160_frames;
u32 sgi_frames;
u32 ngi_frames;
u32 siso_frames;
u32 mimo2_frames;
u32 agg_frames;
u32 ampdu_count;
u32 success_frames;
u32 fail_frames;
u32 last_rates[IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES];
int last_frame_idx;
};
struct iwl_mvm { struct iwl_mvm {
/* for logger access */ /* for logger access */
struct device *dev; struct device *dev;
...@@ -519,6 +540,7 @@ struct iwl_mvm { ...@@ -519,6 +540,7 @@ struct iwl_mvm {
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *debugfs_dir; struct dentry *debugfs_dir;
u32 dbgfs_sram_offset, dbgfs_sram_len; u32 dbgfs_sram_offset, dbgfs_sram_len;
u32 dbgfs_prph_reg_addr;
bool disable_power_off; bool disable_power_off;
bool disable_power_off_d3; bool disable_power_off_d3;
...@@ -526,6 +548,9 @@ struct iwl_mvm { ...@@ -526,6 +548,9 @@ struct iwl_mvm {
struct debugfs_blob_wrapper nvm_sw_blob; struct debugfs_blob_wrapper nvm_sw_blob;
struct debugfs_blob_wrapper nvm_calib_blob; struct debugfs_blob_wrapper nvm_calib_blob;
struct debugfs_blob_wrapper nvm_prod_blob; struct debugfs_blob_wrapper nvm_prod_blob;
struct iwl_mvm_frame_stats drv_rx_stats;
spinlock_t drv_stats_lock;
#endif #endif
struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX];
...@@ -587,8 +612,6 @@ struct iwl_mvm { ...@@ -587,8 +612,6 @@ struct iwl_mvm {
u8 first_agg_queue; u8 first_agg_queue;
u8 last_agg_queue; u8 last_agg_queue;
u8 bound_vif_cnt;
/* Indicate if device power save is allowed */ /* Indicate if device power save is allowed */
bool ps_disabled; bool ps_disabled;
/* Indicate if device power management is allowed */ /* Indicate if device power management is allowed */
...@@ -812,6 +835,10 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -812,6 +835,10 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
/* rate scaling */ /* rate scaling */
int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init);
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
struct iwl_mvm_frame_stats *stats,
u32 rate, bool agg);
int rs_pretty_print_rate(char *buf, const u32 rate);
/* power management */ /* power management */
int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm); int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm);
......
...@@ -228,13 +228,23 @@ static struct iwl_nvm_data * ...@@ -228,13 +228,23 @@ static struct iwl_nvm_data *
iwl_parse_nvm_sections(struct iwl_mvm *mvm) iwl_parse_nvm_sections(struct iwl_mvm *mvm)
{ {
struct iwl_nvm_section *sections = mvm->nvm_sections; struct iwl_nvm_section *sections = mvm->nvm_sections;
const __le16 *hw, *sw, *calib; const __le16 *hw, *sw, *calib, *regulatory, *mac_override;
/* Checking for required sections */ /* Checking for required sections */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
IWL_ERR(mvm, "Can't parse empty NVM sections\n"); !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
return NULL; IWL_ERR(mvm, "Can't parse empty NVM sections\n");
return NULL;
}
} else {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 NVM sections\n");
return NULL;
}
} }
if (WARN_ON(!mvm->cfg)) if (WARN_ON(!mvm->cfg))
...@@ -243,9 +253,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) ...@@ -243,9 +253,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
mac_override =
(const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
iwl_fw_valid_tx_ant(mvm->fw), regulatory, mac_override,
iwl_fw_valid_rx_ant(mvm->fw)); mvm->fw->valid_tx_ant,
mvm->fw->valid_rx_ant);
} }
#define MAX_NVM_FILE_LEN 16384 #define MAX_NVM_FILE_LEN 16384
...@@ -285,6 +300,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ...@@ -285,6 +300,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12) #define NVM_WORD2_ID(x) (x >> 12)
#define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
...@@ -335,8 +352,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ...@@ -335,8 +352,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break; break;
} }
section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); section_size =
2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
} else {
section_size = 2 * NVM_WORD2_LEN_FAMILY_8000(
le16_to_cpu(file_sec->word2));
section_id = NVM_WORD1_ID_FAMILY_8000(
le16_to_cpu(file_sec->word1));
}
if (section_size > IWL_MAX_NVM_SECTION_SIZE) { if (section_size > IWL_MAX_NVM_SECTION_SIZE) {
IWL_ERR(mvm, "ERROR - section too large (%d)\n", IWL_ERR(mvm, "ERROR - section too large (%d)\n",
...@@ -406,6 +431,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm) ...@@ -406,6 +431,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
{ {
int ret, i, section; int ret, i, section;
u8 *nvm_buffer, *temp; u8 *nvm_buffer, *temp;
int nvm_to_read[NVM_MAX_NUM_SECTIONS];
int num_of_sections_to_read;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL; return -EINVAL;
...@@ -418,12 +445,20 @@ int iwl_nvm_init(struct iwl_mvm *mvm) ...@@ -418,12 +445,20 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
return ret; return ret;
} else { } else {
/* list of NVM sections we are allowed/need to read */ /* list of NVM sections we are allowed/need to read */
int nvm_to_read[] = { if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
mvm->cfg->nvm_hw_section_num, nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;
NVM_SECTION_TYPE_SW, nvm_to_read[1] = NVM_SECTION_TYPE_SW;
NVM_SECTION_TYPE_CALIBRATION, nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION;
NVM_SECTION_TYPE_PRODUCTION, nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION;
}; num_of_sections_to_read = 4;
} else {
nvm_to_read[0] = NVM_SECTION_TYPE_SW;
nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION;
nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION;
nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY;
nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE;
num_of_sections_to_read = 5;
}
/* Read From FW NVM */ /* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
...@@ -433,7 +468,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm) ...@@ -433,7 +468,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
GFP_KERNEL); GFP_KERNEL);
if (!nvm_buffer) if (!nvm_buffer)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { for (i = 0; i < num_of_sections_to_read; i++) {
section = nvm_to_read[i]; section = nvm_to_read[i];
/* we override the constness for initial read */ /* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer); ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
......
...@@ -245,7 +245,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { ...@@ -245,7 +245,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
#undef RX_HANDLER #undef RX_HANDLER
#define CMD(x) [x] = #x #define CMD(x) [x] = #x
static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(MVM_ALIVE), CMD(MVM_ALIVE),
CMD(REPLY_ERROR), CMD(REPLY_ERROR),
CMD(INIT_COMPLETE_NOTIF), CMD(INIT_COMPLETE_NOTIF),
......
...@@ -156,13 +156,13 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, ...@@ -156,13 +156,13 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
idle_cnt = chains_static; idle_cnt = chains_static;
active_cnt = chains_dynamic; active_cnt = chains_dynamic;
cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) << cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant <<
PHY_RX_CHAIN_VALID_POS); PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
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(iwl_fw_valid_tx_ant(mvm->fw)); cmd->txchain_info = cpu_to_le32(mvm->fw->valid_tx_ant);
} }
/* /*
......
...@@ -425,7 +425,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, ...@@ -425,7 +425,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
return 0; return 0;
if (vif->p2p && if (vif->p2p &&
!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)) !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))
return 0; return 0;
iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_build_cmd(mvm, vif, &cmd);
...@@ -511,8 +511,11 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, ...@@ -511,8 +511,11 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
struct iwl_power_constraint { struct iwl_power_constraint {
struct ieee80211_vif *bf_vif; struct ieee80211_vif *bf_vif;
struct ieee80211_vif *bss_vif; struct ieee80211_vif *bss_vif;
u16 bss_phyctx_id;
u16 p2p_phyctx_id;
bool pm_disabled; bool pm_disabled;
bool ps_disabled; bool ps_disabled;
struct iwl_mvm *mvm;
}; };
static void iwl_mvm_power_iterator(void *_data, u8 *mac, static void iwl_mvm_power_iterator(void *_data, u8 *mac,
...@@ -520,6 +523,7 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, ...@@ -520,6 +523,7 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_power_constraint *power_iterator = _data; struct iwl_power_constraint *power_iterator = _data;
struct iwl_mvm *mvm = power_iterator->mvm;
switch (ieee80211_vif_type_p2p(vif)) { switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
...@@ -539,11 +543,28 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, ...@@ -539,11 +543,28 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
/* no BSS power mgmt if we have a P2P client*/ if (mvmvif->phy_ctxt)
power_iterator->pm_disabled = true; power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id;
IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n",
power_iterator->p2p_phyctx_id,
power_iterator->bss_phyctx_id);
if (!(mvm->fw->ucode_capa.flags &
IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
/* no BSS power mgmt if we have a P2P client*/
power_iterator->pm_disabled = true;
} else if (power_iterator->p2p_phyctx_id < MAX_PHYS &&
power_iterator->bss_phyctx_id < MAX_PHYS &&
power_iterator->p2p_phyctx_id ==
power_iterator->bss_phyctx_id) {
power_iterator->pm_disabled = true;
}
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (mvmvif->phy_ctxt)
power_iterator->bss_phyctx_id = mvmvif->phy_ctxt->id;
/* we should have only one BSS vif */ /* we should have only one BSS vif */
WARN_ON(power_iterator->bss_vif); WARN_ON(power_iterator->bss_vif);
power_iterator->bss_vif = vif; power_iterator->bss_vif = vif;
...@@ -551,6 +572,17 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, ...@@ -551,6 +572,17 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
if (mvmvif->bf_data.bf_enabled && if (mvmvif->bf_data.bf_enabled &&
!WARN_ON(power_iterator->bf_vif)) !WARN_ON(power_iterator->bf_vif))
power_iterator->bf_vif = vif; power_iterator->bf_vif = vif;
IWL_DEBUG_POWER(mvm, "bss: p2p_id=%d, bss_id=%d\n",
power_iterator->p2p_phyctx_id,
power_iterator->bss_phyctx_id);
if (mvm->fw->ucode_capa.flags &
IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM &&
(power_iterator->p2p_phyctx_id < MAX_PHYS &&
power_iterator->bss_phyctx_id < MAX_PHYS &&
power_iterator->p2p_phyctx_id ==
power_iterator->bss_phyctx_id))
power_iterator->pm_disabled = true;
break; break;
default: default:
...@@ -572,16 +604,16 @@ iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm, ...@@ -572,16 +604,16 @@ iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm,
ieee80211_iterate_active_interfaces_atomic(mvm->hw, ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_power_iterator, constraint); iwl_mvm_power_iterator, constraint);
/* TODO: remove this and determine this variable in the iterator */
if (mvm->bound_vif_cnt > 1)
constraint->pm_disabled = true;
} }
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, 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);
struct iwl_power_constraint constraint = {}; struct iwl_power_constraint constraint = {
.p2p_phyctx_id = MAX_PHYS,
.bss_phyctx_id = MAX_PHYS,
.mvm = mvm,
};
bool ba_enable; bool ba_enable;
int ret; int ret;
......
...@@ -166,7 +166,7 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -166,7 +166,7 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (sta->smps_mode == IEEE80211_SMPS_STATIC) if (sta->smps_mode == IEEE80211_SMPS_STATIC)
return false; return false;
if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2) if (num_of_ant(mvm->fw->valid_tx_ant) < 2)
return false; return false;
if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
...@@ -917,7 +917,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, ...@@ -917,7 +917,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
if (num_of_ant(rate->ant) > 1) if (num_of_ant(rate->ant) > 1)
rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); rate->ant = first_antenna(mvm->fw->valid_tx_ant);
/* Relevant in both switching to SISO or Legacy */ /* Relevant in both switching to SISO or Legacy */
rate->sgi = false; rate->sgi = false;
...@@ -1477,7 +1477,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, ...@@ -1477,7 +1477,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
const struct rs_tx_column *next_col; const struct rs_tx_column *next_col;
allow_column_func_t allow_func; allow_column_func_t allow_func;
u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw); u8 valid_ants = mvm->fw->valid_tx_ant;
const u16 *expected_tpt_tbl; const u16 *expected_tpt_tbl;
s32 tpt, max_expected_tpt; s32 tpt, max_expected_tpt;
...@@ -2089,7 +2089,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, ...@@ -2089,7 +2089,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
i = lq_sta->last_txrate_idx; i = lq_sta->last_txrate_idx;
valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); valid_tx_ant = mvm->fw->valid_tx_ant;
if (!lq_sta->search_better_tbl) if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl; active_tbl = lq_sta->active_tbl;
...@@ -2240,6 +2240,73 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, ...@@ -2240,6 +2240,73 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
} }
} }
#ifdef CONFIG_IWLWIFI_DEBUGFS
static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm,
struct iwl_mvm_frame_stats *stats)
{
spin_lock_bh(&mvm->drv_stats_lock);
memset(stats, 0, sizeof(*stats));
spin_unlock_bh(&mvm->drv_stats_lock);
}
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
struct iwl_mvm_frame_stats *stats,
u32 rate, bool agg)
{
u8 nss = 0, mcs = 0;
spin_lock(&mvm->drv_stats_lock);
if (agg)
stats->agg_frames++;
stats->success_frames++;
switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {
case RATE_MCS_CHAN_WIDTH_20:
stats->bw_20_frames++;
break;
case RATE_MCS_CHAN_WIDTH_40:
stats->bw_40_frames++;
break;
case RATE_MCS_CHAN_WIDTH_80:
stats->bw_80_frames++;
break;
default:
WARN_ONCE(1, "bad BW. rate 0x%x", rate);
}
if (rate & RATE_MCS_HT_MSK) {
stats->ht_frames++;
mcs = rate & RATE_HT_MCS_RATE_CODE_MSK;
nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1;
} else if (rate & RATE_MCS_VHT_MSK) {
stats->vht_frames++;
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
} else {
stats->legacy_frames++;
}
if (nss == 1)
stats->siso_frames++;
else if (nss == 2)
stats->mimo2_frames++;
if (rate & RATE_MCS_SGI_MSK)
stats->sgi_frames++;
else
stats->ngi_frames++;
stats->last_rates[stats->last_frame_idx] = rate;
stats->last_frame_idx = (stats->last_frame_idx + 1) %
ARRAY_SIZE(stats->last_rates);
spin_unlock(&mvm->drv_stats_lock);
}
#endif
/* /*
* Called after adding a new station to initialize rate scaling * Called after adding a new station to initialize rate scaling
*/ */
...@@ -2319,7 +2386,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2319,7 +2386,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* These values will be overridden later */ /* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk = lq_sta->lq.single_stream_ant_msk =
first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); first_antenna(mvm->fw->valid_tx_ant);
lq_sta->lq.dual_stream_ant_msk = ANT_AB; lq_sta->lq.dual_stream_ant_msk = ANT_AB;
/* as default allow aggregation for all tids */ /* as default allow aggregation for all tids */
...@@ -2334,7 +2401,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2334,7 +2401,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0; lq_sta->dbg_fixed_rate = 0;
#endif #endif
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
#endif
rs_initialize_lq(mvm, sta, lq_sta, band, init); rs_initialize_lq(mvm, sta, lq_sta, band, init);
} }
...@@ -2445,7 +2514,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, ...@@ -2445,7 +2514,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
memcpy(&rate, initial_rate, sizeof(rate)); memcpy(&rate, initial_rate, sizeof(rate));
valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); valid_tx_ant = mvm->fw->valid_tx_ant;
if (is_siso(&rate)) { if (is_siso(&rate)) {
num_rates = RS_INITIAL_SISO_NUM_RATES; num_rates = RS_INITIAL_SISO_NUM_RATES;
...@@ -2546,7 +2615,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, ...@@ -2546,7 +2615,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta,
} }
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
static int rs_pretty_print_rate(char *buf, const u32 rate) int rs_pretty_print_rate(char *buf, const u32 rate)
{ {
char *type, *bw; char *type, *bw;
...@@ -2595,7 +2664,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) ...@@ -2595,7 +2664,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate)
return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n", return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n",
type, rs_pretty_ant(ant), bw, mcs, nss, type, rs_pretty_ant(ant), bw, mcs, nss,
(rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ",
(rate & RATE_MCS_STBC_MSK) ? "STBC " : "", (rate & RATE_MCS_HT_STBC_MSK) ? "STBC " : "",
(rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
(rate & RATE_MCS_BF_MSK) ? "BF " : "", (rate & RATE_MCS_BF_MSK) ? "BF " : "",
(rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : "");
...@@ -2676,9 +2745,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, ...@@ -2676,9 +2745,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n", desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate); lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
(iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "", (mvm->fw->valid_tx_ant & ANT_A) ? "ANT_A," : "",
(iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", (mvm->fw->valid_tx_ant & ANT_B) ? "ANT_B," : "",
(iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); (mvm->fw->valid_tx_ant & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n", desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(rate)) ? "legacy" : (is_legacy(rate)) ? "legacy" :
is_vht(rate) ? "VHT" : "HT"); is_vht(rate) ? "VHT" : "HT");
......
...@@ -77,6 +77,15 @@ int iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -77,6 +77,15 @@ int iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info)); memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info));
mvm->ampdu_ref++; mvm->ampdu_ref++;
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (mvm->last_phy_info.phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
spin_lock(&mvm->drv_stats_lock);
mvm->drv_rx_stats.ampdu_count++;
spin_unlock(&mvm->drv_stats_lock);
}
#endif
return 0; return 0;
} }
...@@ -368,21 +377,33 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -368,21 +377,33 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
rx_status.flag |= RX_FLAG_SHORT_GI; rx_status.flag |= RX_FLAG_SHORT_GI;
if (rate_n_flags & RATE_HT_MCS_GF_MSK) if (rate_n_flags & RATE_HT_MCS_GF_MSK)
rx_status.flag |= RX_FLAG_HT_GF; rx_status.flag |= RX_FLAG_HT_GF;
if (rate_n_flags & RATE_MCS_LDPC_MSK)
rx_status.flag |= RX_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK) { if (rate_n_flags & RATE_MCS_HT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >>
RATE_MCS_STBC_POS;
rx_status.flag |= RX_FLAG_HT; rx_status.flag |= RX_FLAG_HT;
rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
} else if (rate_n_flags & RATE_MCS_VHT_MSK) { } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >>
RATE_MCS_STBC_POS;
rx_status.vht_nss = rx_status.vht_nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1; RATE_VHT_MCS_NSS_POS) + 1;
rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
rx_status.flag |= RX_FLAG_VHT; rx_status.flag |= RX_FLAG_VHT;
rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
} else { } else {
rx_status.rate_idx = rx_status.rate_idx =
iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
rx_status.band); rx_status.band);
} }
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags,
rx_status.flag & RX_FLAG_AMPDU_DETAILS);
#endif
iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status, iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status,
rxb, &rx_status); rxb, &rx_status);
return 0; return 0;
......
...@@ -82,7 +82,7 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) ...@@ -82,7 +82,7 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
if (mvm->scan_rx_ant != ANT_NONE) if (mvm->scan_rx_ant != ANT_NONE)
rx_ant = mvm->scan_rx_ant; rx_ant = mvm->scan_rx_ant;
else else
rx_ant = iwl_fw_valid_rx_ant(mvm->fw); rx_ant = mvm->fw->valid_rx_ant;
rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;
...@@ -124,7 +124,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, ...@@ -124,7 +124,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, iwl_fw_valid_tx_ant(mvm->fw), iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
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;
......
...@@ -438,7 +438,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, ...@@ -438,7 +438,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd.duration = cpu_to_le32(duration); time_cmd.duration = cpu_to_le32(duration);
time_cmd.repeat = 1; time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
TE_V2_NOTIF_HOST_EVENT_END); TE_V2_NOTIF_HOST_EVENT_END |
T2_V2_START_IMMEDIATELY);
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
} }
...@@ -553,7 +554,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -553,7 +554,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
time_cmd.repeat = 1; time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
TE_V2_NOTIF_HOST_EVENT_END); TE_V2_NOTIF_HOST_EVENT_END |
T2_V2_START_IMMEDIATELY);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
} }
......
...@@ -122,7 +122,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -122,7 +122,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
* it * it
*/ */
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
} else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { } else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
tx_cmd->pm_frame_timeout = cpu_to_le16(2); tx_cmd->pm_frame_timeout = cpu_to_le16(2);
} else { } else {
tx_cmd->pm_frame_timeout = 0; tx_cmd->pm_frame_timeout = 0;
...@@ -207,7 +207,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, ...@@ -207,7 +207,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
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, iwl_fw_valid_tx_ant(mvm->fw), iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->mgmt_last_antenna_idx); mvm->mgmt_last_antenna_idx);
rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
......
...@@ -289,8 +289,8 @@ u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx) ...@@ -289,8 +289,8 @@ u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx)
return last_idx; return last_idx;
} }
static struct { static const struct {
char *name; const char *name;
u8 num; u8 num;
} advanced_lookup[] = { } advanced_lookup[] = {
{ "NMI_INTERRUPT_WDG", 0x34 }, { "NMI_INTERRUPT_WDG", 0x34 },
...@@ -589,7 +589,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -589,7 +589,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(iwl_fw_valid_rx_ant(mvm->fw)) == 1) if (num_of_ant(mvm->fw->valid_rx_ant) == 1)
return; return;
if (vif->type == NL80211_IFTYPE_AP) if (vif->type == NL80211_IFTYPE_AP)
......
...@@ -304,7 +304,7 @@ struct iwl_trans_pcie { ...@@ -304,7 +304,7 @@ struct iwl_trans_pcie {
bool bc_table_dword; bool bc_table_dword;
u32 rx_page_order; u32 rx_page_order;
const char **command_names; const char *const *command_names;
/* queue watchdog */ /* queue watchdog */
unsigned long wd_timeout; unsigned long wd_timeout;
......
...@@ -155,37 +155,26 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, ...@@ -155,37 +155,26 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
if (rxq->need_update == 0) if (rxq->need_update == 0)
goto exit_unlock; goto exit_unlock;
if (trans->cfg->base_params->shadow_reg_enable) { /*
/* shadow register enabled */ * explicitly wake up the NIC if:
/* Device expects a multiple of 8 */ * 1. shadow registers aren't enabled
rxq->write_actual = (rxq->write & ~0x7); * 2. there is a chance that the NIC is asleep
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); */
} else { if (!trans->cfg->base_params->shadow_reg_enable &&
/* If power-saving is in use, make sure device is awake */ test_bit(STATUS_TPOWER_PMI, &trans->status)) {
if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n",
IWL_DEBUG_INFO(trans, reg);
"Rx queue requesting wakeup," iwl_set_bit(trans, CSR_GP_CNTRL,
" GP1 = 0x%x\n", reg); CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
iwl_set_bit(trans, CSR_GP_CNTRL, goto exit_unlock;
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
goto exit_unlock;
}
rxq->write_actual = (rxq->write & ~0x7);
iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
rxq->write_actual);
/* Else device is assumed to be awake */
} else {
/* Device expects a multiple of 8 */
rxq->write_actual = (rxq->write & ~0x7);
iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
rxq->write_actual);
} }
} }
rxq->write_actual = round_down(rxq->write, 8);
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
rxq->need_update = 0; rxq->need_update = 0;
exit_unlock: exit_unlock:
......
...@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) ...@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR(trans, "scratch %d = 0x%08x\n", i, IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
le32_to_cpu(txq->scratchbufs[i].scratch)); le32_to_cpu(txq->scratchbufs[i].scratch));
iwl_trans_fw_error(trans); iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
} }
/* /*
...@@ -296,43 +296,38 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) ...@@ -296,43 +296,38 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
if (txq->need_update == 0) if (txq->need_update == 0)
return; return;
if (trans->cfg->base_params->shadow_reg_enable || /*
txq_id == trans_pcie->cmd_queue) { * explicitly wake up the NIC if:
/* shadow register enabled */ * 1. shadow registers aren't enabled
iwl_write32(trans, HBUS_TARG_WRPTR, * 2. NIC is woken up for CMD regardless of shadow outside this function
txq->q.write_ptr | (txq_id << 8)); * 3. there is a chance that the NIC is asleep
} else { */
/* if we're trying to save power */ if (!trans->cfg->base_params->shadow_reg_enable &&
if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { txq_id != trans_pcie->cmd_queue &&
/* wake up nic if it's powered down ... test_bit(STATUS_TPOWER_PMI, &trans->status)) {
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
IWL_DEBUG_INFO(trans,
"Tx queue %d requesting wakeup,"
" GP1 = 0x%x\n", txq_id, reg);
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return;
}
IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id,
txq->q.write_ptr);
iwl_write_direct32(trans, HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8));
/* /*
* else not in power-save mode, * wake up nic if it's powered down ...
* uCode will never sleep when we're * uCode will wake up, and interrupt us again, so next
* trying to tx (during RFKILL, we're not trying to tx). * time we'll skip this part.
*/ */
} else reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
iwl_write32(trans, HBUS_TARG_WRPTR,
txq->q.write_ptr | (txq_id << 8)); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
txq_id, reg);
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return;
}
} }
/*
* if not in power-save mode, uCode will never sleep when we're
* trying to tx (during RFKILL, we're not trying to tx).
*/
IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr);
iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8));
txq->need_update = 0; txq->need_update = 0;
} }
...@@ -1029,7 +1024,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) ...@@ -1029,7 +1024,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if (nfreed++ > 0) { if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
idx, q->write_ptr, q->read_ptr); idx, q->write_ptr, q->read_ptr);
iwl_trans_fw_error(trans); iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
} }
} }
...@@ -1588,6 +1583,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, ...@@ -1588,6 +1583,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
get_cmd_string(trans_pcie, cmd->id)); get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
iwl_trans_fw_error(trans); iwl_trans_fw_error(trans);
goto cancel; goto cancel;
......
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