Commit ea375117 authored by John W. Linville's avatar John W. Linville

Merge tag 'iwlwifi-next-for-john-2014-12-02' of...

Merge tag 'iwlwifi-next-for-john-2014-12-02' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

"Grumbach, Emmanuel" <emmanuel.grumbach@intel.com> says:

"I deprecate here -8.ucode since -9 has been published long ago.
Along with that I have a new activity, we have now better
infrastructure for firmware debugging. This will allow to
have configurable probes insides the firmware.
Luca continues his work on NetDetect, this feature is now
complete. All the rest is minor fixes here and there."
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents fbf61095 61df750c
...@@ -966,21 +966,21 @@ struct iwl_rem_sta_cmd { ...@@ -966,21 +966,21 @@ struct iwl_rem_sta_cmd {
/* WiFi queues mask */ /* WiFi queues mask */
#define IWL_SCD_BK_MSK cpu_to_le32(BIT(0)) #define IWL_SCD_BK_MSK BIT(0)
#define IWL_SCD_BE_MSK cpu_to_le32(BIT(1)) #define IWL_SCD_BE_MSK BIT(1)
#define IWL_SCD_VI_MSK cpu_to_le32(BIT(2)) #define IWL_SCD_VI_MSK BIT(2)
#define IWL_SCD_VO_MSK cpu_to_le32(BIT(3)) #define IWL_SCD_VO_MSK BIT(3)
#define IWL_SCD_MGMT_MSK cpu_to_le32(BIT(3)) #define IWL_SCD_MGMT_MSK BIT(3)
/* PAN queues mask */ /* PAN queues mask */
#define IWL_PAN_SCD_BK_MSK cpu_to_le32(BIT(4)) #define IWL_PAN_SCD_BK_MSK BIT(4)
#define IWL_PAN_SCD_BE_MSK cpu_to_le32(BIT(5)) #define IWL_PAN_SCD_BE_MSK BIT(5)
#define IWL_PAN_SCD_VI_MSK cpu_to_le32(BIT(6)) #define IWL_PAN_SCD_VI_MSK BIT(6)
#define IWL_PAN_SCD_VO_MSK cpu_to_le32(BIT(7)) #define IWL_PAN_SCD_VO_MSK BIT(7)
#define IWL_PAN_SCD_MGMT_MSK cpu_to_le32(BIT(7)) #define IWL_PAN_SCD_MGMT_MSK BIT(7)
#define IWL_PAN_SCD_MULTICAST_MSK cpu_to_le32(BIT(8)) #define IWL_PAN_SCD_MULTICAST_MSK BIT(8)
#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00) #define IWL_AGG_TX_QUEUE_MSK 0xffc00
#define IWL_DROP_ALL BIT(1) #define IWL_DROP_ALL BIT(1)
...@@ -1005,12 +1005,17 @@ struct iwl_rem_sta_cmd { ...@@ -1005,12 +1005,17 @@ struct iwl_rem_sta_cmd {
* 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable. * 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
* 2: Dump all FIFO * 2: Dump all FIFO
*/ */
struct iwl_txfifo_flush_cmd { struct iwl_txfifo_flush_cmd_v3 {
__le32 queue_control; __le32 queue_control;
__le16 flush_control; __le16 flush_control;
__le16 reserved; __le16 reserved;
} __packed; } __packed;
struct iwl_txfifo_flush_cmd_v2 {
__le16 queue_control;
__le16 flush_control;
} __packed;
/* /*
* REPLY_WEP_KEY = 0x20 * REPLY_WEP_KEY = 0x20
*/ */
......
...@@ -137,37 +137,38 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, ...@@ -137,37 +137,38 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
*/ */
int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
{ {
struct iwl_txfifo_flush_cmd flush_cmd; struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = {
struct iwl_host_cmd cmd = { .flush_control = cpu_to_le16(IWL_DROP_ALL),
.id = REPLY_TXFIFO_FLUSH, };
.len = { sizeof(struct iwl_txfifo_flush_cmd), }, struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = {
.data = { &flush_cmd, }, .flush_control = cpu_to_le16(IWL_DROP_ALL),
}; };
memset(&flush_cmd, 0, sizeof(flush_cmd)); u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK;
flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
IWL_SCD_MGMT_MSK;
if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK | queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK |
IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK |
IWL_PAN_SCD_BE_MSK |
IWL_PAN_SCD_BK_MSK |
IWL_PAN_SCD_MGMT_MSK | IWL_PAN_SCD_MGMT_MSK |
IWL_PAN_SCD_MULTICAST_MSK; IWL_PAN_SCD_MULTICAST_MSK;
if (priv->nvm_data->sku_cap_11n_enable) if (priv->nvm_data->sku_cap_11n_enable)
flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; queue_control |= IWL_AGG_TX_QUEUE_MSK;
if (scd_q_msk) if (scd_q_msk)
flush_cmd.queue_control = cpu_to_le32(scd_q_msk); queue_control = scd_q_msk;
IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control);
flush_cmd.queue_control); flush_cmd_v3.queue_control = cpu_to_le32(queue_control);
flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control);
return iwl_dvm_send_cmd(priv, &cmd); if (IWL_UCODE_API(priv->fw->ucode_ver) > 2)
return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
sizeof(flush_cmd_v3),
&flush_cmd_v3);
return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
sizeof(flush_cmd_v2), &flush_cmd_v2);
} }
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
......
...@@ -73,12 +73,12 @@ ...@@ -73,12 +73,12 @@
#define IWL3160_UCODE_API_MAX 10 #define IWL3160_UCODE_API_MAX 10
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 9 #define IWL7260_UCODE_API_OK 10
#define IWL3160_UCODE_API_OK 9 #define IWL3160_UCODE_API_OK 10
/* Lowest firmware API version supported */ /* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 8 #define IWL7260_UCODE_API_MIN 9
#define IWL3160_UCODE_API_MIN 8 #define IWL3160_UCODE_API_MIN 9
/* NVM versions */ /* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d #define IWL7260_NVM_VERSION 0x0a1d
...@@ -89,6 +89,8 @@ ...@@ -89,6 +89,8 @@
#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265_NVM_VERSION 0x0a1d #define IWL7265_NVM_VERSION 0x0a1d
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265D_NVM_VERSION 0x0c11
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7260_FW_PRE "iwlwifi-7260-" #define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
...@@ -275,7 +277,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = { ...@@ -275,7 +277,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = {
.fw_name_pre = IWL7265D_FW_PRE, .fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7000, IWL_DEVICE_7000,
.ht_params = &iwl7265_ht_params, .ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
}; };
...@@ -285,7 +287,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = { ...@@ -285,7 +287,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = {
.fw_name_pre = IWL7265D_FW_PRE, .fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7000, IWL_DEVICE_7000,
.ht_params = &iwl7265_ht_params, .ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
}; };
...@@ -295,7 +297,7 @@ const struct iwl_cfg iwl7265d_n_cfg = { ...@@ -295,7 +297,7 @@ const struct iwl_cfg iwl7265d_n_cfg = {
.fw_name_pre = IWL7265D_FW_PRE, .fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7000, IWL_DEVICE_7000,
.ht_params = &iwl7265_ht_params, .ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265_NVM_VERSION, .nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION, .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
}; };
......
...@@ -72,10 +72,10 @@ ...@@ -72,10 +72,10 @@
#define IWL8000_UCODE_API_MAX 10 #define IWL8000_UCODE_API_MAX 10
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK 8 #define IWL8000_UCODE_API_OK 10
/* Lowest firmware API version supported */ /* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 8 #define IWL8000_UCODE_API_MIN 9
/* NVM versions */ /* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d #define IWL8000_NVM_VERSION 0x0a1d
...@@ -159,8 +159,8 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = { ...@@ -159,8 +159,8 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO, .max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
}; };
const struct iwl_cfg iwl4265_2ac_sdio_cfg = { const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
.name = "Intel(R) Dual Band Wireless-AC 4265", .name = "Intel(R) Dual Band Wireless-AC 4165",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000, IWL_DEVICE_8000,
.ht_params = &iwl8000_ht_params, .ht_params = &iwl8000_ht_params,
......
...@@ -371,6 +371,7 @@ extern const struct iwl_cfg iwl8260_2n_cfg; ...@@ -371,6 +371,7 @@ extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg; extern const struct iwl_cfg iwl8260_2ac_cfg;
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4265_2ac_sdio_cfg; extern const struct iwl_cfg iwl4265_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
#endif /* CONFIG_IWLMVM */ #endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */ #endif /* __IWL_CONFIG_H__ */
...@@ -78,9 +78,6 @@ ...@@ -78,9 +78,6 @@
#include "iwl-config.h" #include "iwl-config.h"
#include "iwl-modparams.h" #include "iwl-modparams.h"
/* private includes */
#include "iwl-fw-file.h"
/****************************************************************************** /******************************************************************************
* *
* module boiler plate * module boiler plate
...@@ -187,6 +184,11 @@ static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) ...@@ -187,6 +184,11 @@ static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
static void iwl_dealloc_ucode(struct iwl_drv *drv) static void iwl_dealloc_ucode(struct iwl_drv *drv)
{ {
int i; int i;
kfree(drv->fw.dbg_dest_tlv);
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++)
kfree(drv->fw.dbg_conf_tlv[i]);
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i); iwl_free_fw_img(drv, drv->fw.img + i);
} }
...@@ -248,6 +250,9 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) ...@@ -248,6 +250,9 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
/* /*
* Starting 8000B - FW name format has changed. This overwrites the * Starting 8000B - FW name format has changed. This overwrites the
* previous name and uses the new format. * previous name and uses the new format.
*
* TODO:
* Once there is only one supported step for 8000 family - delete this!
*/ */
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
char rev_step[2] = { char rev_step[2] = {
...@@ -258,6 +263,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) ...@@ -258,6 +263,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP) if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
rev_step[0] = 0; rev_step[0] = 0;
/*
* If hw_rev wasn't set yet - default as B-step. If it IS A-step
* we'll reload that FW later instead.
*/
if (drv->trans->hw_rev == 0)
rev_step[0] = 'B';
snprintf(drv->firmware_name, sizeof(drv->firmware_name), snprintf(drv->firmware_name, sizeof(drv->firmware_name),
"%s%s-%s.ucode", name_pre, rev_step, tag); "%s%s-%s.ucode", name_pre, rev_step, tag);
} }
...@@ -301,6 +313,11 @@ struct iwl_firmware_pieces { ...@@ -301,6 +313,11 @@ struct iwl_firmware_pieces {
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
/* FW debug data parsed for driver usage */
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];
}; };
/* /*
...@@ -574,6 +591,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -574,6 +591,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
char buildstr[25]; char buildstr[25];
u32 build; u32 build;
int num_of_cpus; int num_of_cpus;
bool usniffer_images = false;
bool usniffer_req = false;
if (len < sizeof(*ucode)) { if (len < sizeof(*ucode)) {
IWL_ERR(drv, "uCode has invalid length: %zd\n", len); IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
...@@ -846,12 +865,79 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -846,12 +865,79 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
capa->n_scan_channels = capa->n_scan_channels =
le32_to_cpup((__le32 *)tlv_data); le32_to_cpup((__le32 *)tlv_data);
break; break;
case IWL_UCODE_TLV_FW_DBG_DEST: {
struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data;
if (pieces->dbg_dest_tlv) {
IWL_ERR(drv,
"dbg destination ignored, already exists\n");
break;
}
pieces->dbg_dest_tlv = dest;
IWL_INFO(drv, "Found debug destination: %s\n",
get_fw_dbg_mode_string(dest->monitor_mode));
drv->fw.dbg_dest_reg_num =
tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv,
reg_ops);
drv->fw.dbg_dest_reg_num /=
sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]);
break;
}
case IWL_UCODE_TLV_FW_DBG_CONF: {
struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data;
if (!pieces->dbg_dest_tlv) {
IWL_ERR(drv,
"Ignore dbg config %d - no destination configured\n",
conf->id);
break;
}
if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) {
IWL_ERR(drv,
"Skip unknown configuration: %d\n",
conf->id);
break;
}
if (pieces->dbg_conf_tlv[conf->id]) {
IWL_ERR(drv,
"Ignore duplicate dbg config %d\n",
conf->id);
break;
}
if (conf->usniffer)
usniffer_req = true;
IWL_INFO(drv, "Found debug configuration: %d\n",
conf->id);
pieces->dbg_conf_tlv[conf->id] = conf;
pieces->dbg_conf_tlv_len[conf->id] = tlv_len;
break;
}
case IWL_UCODE_TLV_SEC_RT_USNIFFER:
usniffer_images = true;
iwl_store_ucode_sec(pieces, tlv_data,
IWL_UCODE_REGULAR_USNIFFER,
tlv_len);
break;
default: default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break; break;
} }
} }
if (usniffer_req && !usniffer_images) {
IWL_ERR(drv,
"user selected to work with usniffer but usniffer image isn't available in ucode package\n");
return -EINVAL;
}
if (len) { if (len) {
IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len); IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len); iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
...@@ -989,13 +1075,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -989,13 +1075,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
struct iwl_ucode_header *ucode; struct iwl_ucode_header *ucode;
struct iwlwifi_opmode_table *op; struct iwlwifi_opmode_table *op;
int err; int err;
struct iwl_firmware_pieces pieces; struct iwl_firmware_pieces *pieces;
const unsigned int api_max = drv->cfg->ucode_api_max; const unsigned int api_max = drv->cfg->ucode_api_max;
unsigned int api_ok = drv->cfg->ucode_api_ok; unsigned int api_ok = drv->cfg->ucode_api_ok;
const unsigned int api_min = drv->cfg->ucode_api_min; const unsigned int api_min = drv->cfg->ucode_api_min;
u32 api_ver; u32 api_ver;
int i; int i;
bool load_module = false; bool load_module = false;
u32 hw_rev = drv->trans->hw_rev;
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size = fw->ucode_capa.standard_phy_calibration_size =
...@@ -1005,7 +1092,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1005,7 +1092,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (!api_ok) if (!api_ok)
api_ok = api_max; api_ok = api_max;
memset(&pieces, 0, sizeof(pieces)); pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
if (!pieces)
return;
if (!ucode_raw) { if (!ucode_raw) {
if (drv->fw_index <= api_ok) if (drv->fw_index <= api_ok)
...@@ -1028,9 +1117,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1028,9 +1117,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
ucode = (struct iwl_ucode_header *)ucode_raw->data; ucode = (struct iwl_ucode_header *)ucode_raw->data;
if (ucode->ver) if (ucode->ver)
err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces); err = iwl_parse_v1_v2_firmware(drv, ucode_raw, pieces);
else else
err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces, err = iwl_parse_tlv_firmware(drv, ucode_raw, pieces,
&fw->ucode_capa); &fw->ucode_capa);
if (err) if (err)
...@@ -1071,7 +1160,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1071,7 +1160,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* In mvm uCode there is no difference between data and instructions * In mvm uCode there is no difference between data and instructions
* sections. * sections.
*/ */
if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, drv->cfg)) if (!fw->mvm_fw && validate_sec_sizes(drv, pieces, drv->cfg))
goto try_again; goto try_again;
/* Allocate ucode buffers for card's bus-master loading ... */ /* Allocate ucode buffers for card's bus-master loading ... */
...@@ -1080,9 +1169,33 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1080,9 +1169,33 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* 1) unmodified from disk * 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */ * 2) backup cache for save/restore during power-downs */
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
if (iwl_alloc_ucode(drv, &pieces, i)) if (iwl_alloc_ucode(drv, pieces, i))
goto out_free_fw; goto out_free_fw;
if (pieces->dbg_dest_tlv) {
drv->fw.dbg_dest_tlv =
kmemdup(pieces->dbg_dest_tlv,
sizeof(*pieces->dbg_dest_tlv) +
sizeof(pieces->dbg_dest_tlv->reg_ops[0]) *
drv->fw.dbg_dest_reg_num, GFP_KERNEL);
if (!drv->fw.dbg_dest_tlv)
goto out_free_fw;
}
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) {
if (pieces->dbg_conf_tlv[i]) {
drv->fw.dbg_conf_tlv_len[i] =
pieces->dbg_conf_tlv_len[i];
drv->fw.dbg_conf_tlv[i] =
kmemdup(pieces->dbg_conf_tlv[i],
drv->fw.dbg_conf_tlv_len[i],
GFP_KERNEL);
if (!drv->fw.dbg_conf_tlv[i])
goto out_free_fw;
}
}
/* Now that we can no longer fail, copy information */ /* Now that we can no longer fail, copy information */
/* /*
...@@ -1090,20 +1203,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1090,20 +1203,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* for each event, which is of mode 1 (including timestamp) for all * for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information. * new microcodes that include this information.
*/ */
fw->init_evtlog_ptr = pieces.init_evtlog_ptr; fw->init_evtlog_ptr = pieces->init_evtlog_ptr;
if (pieces.init_evtlog_size) if (pieces->init_evtlog_size)
fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
else else
fw->init_evtlog_size = fw->init_evtlog_size =
drv->cfg->base_params->max_event_log_size; drv->cfg->base_params->max_event_log_size;
fw->init_errlog_ptr = pieces.init_errlog_ptr; fw->init_errlog_ptr = pieces->init_errlog_ptr;
fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr; fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
if (pieces.inst_evtlog_size) if (pieces->inst_evtlog_size)
fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
else else
fw->inst_evtlog_size = fw->inst_evtlog_size =
drv->cfg->base_params->max_event_log_size; drv->cfg->base_params->max_event_log_size;
fw->inst_errlog_ptr = pieces.inst_errlog_ptr; fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
/* /*
* figure out the offset of chain noise reset and gain commands * figure out the offset of chain noise reset and gain commands
...@@ -1162,10 +1275,55 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1162,10 +1275,55 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
op->name, err); op->name, err);
#endif #endif
} }
/*
* We may have loaded the wrong FW file in 8000 HW family if it is an
* A-step card, and if drv->trans->hw_rev wasn't properly read when
* the FW file had been loaded. (This might happen in SDIO.) In such a
* case - unload and reload the correct file.
*
* TODO:
* Once there is only one supported step for 8000 family - delete this!
*/
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP &&
drv->trans->hw_rev != hw_rev) {
char firmware_name[32];
/* Free previous FW resources */
if (drv->op_mode)
_iwl_op_mode_stop(drv);
iwl_dealloc_ucode(drv);
/* Build name of correct-step FW */
snprintf(firmware_name, sizeof(firmware_name),
strrchr(drv->firmware_name, '-'));
snprintf(drv->firmware_name, sizeof(drv->firmware_name),
"%s%s", drv->cfg->fw_name_pre, firmware_name);
/* Clear data before loading correct FW */
list_del(&drv->list);
/* Request correct FW file this time */
IWL_DEBUG_INFO(drv, "attempting to load A-step FW %s\n",
drv->firmware_name);
err = request_firmware(&ucode_raw, drv->firmware_name,
drv->trans->dev);
if (err) {
IWL_ERR(drv, "Failed swapping FW!\n");
goto out_unbind;
}
/* Redo callback function - this time with right FW */
iwl_req_fw_callback(ucode_raw, context);
}
kfree(pieces);
return; return;
try_again: try_again:
/* try next, if any */ /* try next, if any */
kfree(pieces);
release_firmware(ucode_raw); release_firmware(ucode_raw);
if (iwl_request_firmware(drv, false)) if (iwl_request_firmware(drv, false))
goto out_unbind; goto out_unbind;
...@@ -1176,6 +1334,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1176,6 +1334,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
iwl_dealloc_ucode(drv); iwl_dealloc_ucode(drv);
release_firmware(ucode_raw); release_firmware(ucode_raw);
out_unbind: out_unbind:
kfree(pieces);
complete(&drv->request_firmware_complete); complete(&drv->request_firmware_complete);
device_release_driver(drv->trans->dev); device_release_driver(drv->trans->dev);
} }
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file. * sections like this in a single file.
* @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
*/ */
enum iwl_fw_error_dump_type { enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0, IWL_FW_ERROR_DUMP_SRAM = 0,
...@@ -90,6 +91,8 @@ enum iwl_fw_error_dump_type { ...@@ -90,6 +91,8 @@ enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
IWL_FW_ERROR_DUMP_FW_MONITOR = 5, IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
IWL_FW_ERROR_DUMP_PRPH = 6, IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_TXF = 7,
IWL_FW_ERROR_DUMP_FH_REGS = 8,
IWL_FW_ERROR_DUMP_MAX, IWL_FW_ERROR_DUMP_MAX,
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -322,6 +322,7 @@ enum secure_boot_config_reg { ...@@ -322,6 +322,7 @@ enum secure_boot_config_reg {
LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002, LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002,
}; };
#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0 (0xA01E30)
#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR (0x1E30) #define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR (0x1E30)
#define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR (0x1E34) #define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR (0x1E34)
enum secure_boot_status_reg { enum secure_boot_status_reg {
...@@ -333,6 +334,7 @@ enum secure_boot_status_reg { ...@@ -333,6 +334,7 @@ enum secure_boot_status_reg {
LMPM_SECURE_BOOT_STATUS_SUCCESS = 0x00000003, LMPM_SECURE_BOOT_STATUS_SUCCESS = 0x00000003,
}; };
#define FH_UCODE_LOAD_STATUS (0x1AF0)
#define CSR_UCODE_LOAD_STATUS_ADDR (0x1E70) #define CSR_UCODE_LOAD_STATUS_ADDR (0x1E70)
enum secure_load_status_reg { enum secure_load_status_reg {
LMPM_CPU_UCODE_LOADING_STARTED = 0x00000001, LMPM_CPU_UCODE_LOADING_STARTED = 0x00000001,
...@@ -349,10 +351,10 @@ enum secure_load_status_reg { ...@@ -349,10 +351,10 @@ enum secure_load_status_reg {
#define LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE (0x400000) #define LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE (0x400000)
#define LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE (0x402000) #define LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE (0x402000)
#define LMPM_SECURE_CPU1_HDR_MEM_SPACE (0x404000) #define LMPM_SECURE_CPU1_HDR_MEM_SPACE (0x420000)
#define LMPM_SECURE_CPU2_HDR_MEM_SPACE (0x405000) #define LMPM_SECURE_CPU2_HDR_MEM_SPACE (0x420400)
#define LMPM_SECURE_TIME_OUT (50000) /* 5 msec */ #define LMPM_SECURE_TIME_OUT (100) /* 10 micro */
/* Rx FIFO */ /* Rx FIFO */
#define RXF_SIZE_ADDR (0xa00c88) #define RXF_SIZE_ADDR (0xa00c88)
......
...@@ -574,6 +574,9 @@ enum iwl_trans_state { ...@@ -574,6 +574,9 @@ enum iwl_trans_state {
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
* start of the 802.11 header in the @rx_mpdu_cmd * start of the 802.11 header in the @rx_mpdu_cmd
* @dflt_pwr_limit: default power limit fetched from the platform (ACPI) * @dflt_pwr_limit: default power limit fetched from the platform (ACPI)
* @dbg_dest_tlv: points to the destination TLV for debug
* @dbg_conf_tlv: array of pointers to configuration TLVs for debug
* @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
*/ */
struct iwl_trans { struct iwl_trans {
const struct iwl_trans_ops *ops; const struct iwl_trans_ops *ops;
...@@ -605,6 +608,10 @@ struct iwl_trans { ...@@ -605,6 +608,10 @@ struct iwl_trans {
u64 dflt_pwr_limit; u64 dflt_pwr_limit;
const struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
u8 dbg_dest_reg_num;
/* pointer to trans specific struct */ /* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */ /*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *)); char trans_specific[0] __aligned(sizeof(void *));
......
...@@ -94,8 +94,8 @@ ...@@ -94,8 +94,8 @@
#define IWL_MVM_BT_COEX_MPLUT 1 #define IWL_MVM_BT_COEX_MPLUT 1
#define IWL_MVM_BT_COEX_RRC 1 #define IWL_MVM_BT_COEX_RRC 1
#define IWL_MVM_BT_COEX_TTC 1 #define IWL_MVM_BT_COEX_TTC 1
#define IWL_MVM_BT_COEX_MPLUT_REG0 0x2e402280 #define IWL_MVM_BT_COEX_MPLUT_REG0 0x28412201
#define IWL_MVM_BT_COEX_MPLUT_REG1 0x7711a751 #define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451
#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
......
This diff is collapsed.
...@@ -1339,6 +1339,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, ...@@ -1339,6 +1339,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
PRINT_MVM_REF(IWL_MVM_REF_NMI); PRINT_MVM_REF(IWL_MVM_REF_NMI);
PRINT_MVM_REF(IWL_MVM_REF_TM_CMD); PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK); PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
......
...@@ -241,16 +241,12 @@ enum iwl_wowlan_wakeup_filters { ...@@ -241,16 +241,12 @@ enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16), IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16),
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */ }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
struct iwl_wowlan_config_cmd_v2 { struct iwl_wowlan_config_cmd {
__le32 wakeup_filter; __le32 wakeup_filter;
__le16 non_qos_seq; __le16 non_qos_seq;
__le16 qos_seq[8]; __le16 qos_seq[8];
u8 wowlan_ba_teardown_tids; u8 wowlan_ba_teardown_tids;
u8 is_11n_connection; u8 is_11n_connection;
} __packed; /* WOWLAN_CONFIG_API_S_VER_2 */
struct iwl_wowlan_config_cmd_v3 {
struct iwl_wowlan_config_cmd_v2 common;
u8 offloading_tid; u8 offloading_tid;
u8 reserved[3]; u8 reserved[3];
} __packed; /* WOWLAN_CONFIG_API_S_VER_3 */ } __packed; /* WOWLAN_CONFIG_API_S_VER_3 */
......
...@@ -1047,4 +1047,48 @@ struct iwl_umac_scan_complete { ...@@ -1047,4 +1047,48 @@ struct iwl_umac_scan_complete {
__le32 reserved; __le32 reserved;
} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */ } __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5
/**
* struct iwl_scan_offload_profile_match - match information
* @bssid: matched bssid
* @channel: channel where the match occurred
* @energy:
* @matching_feature:
* @matching_channels: bitmap of channels that matched, referencing
* the channels passed in tue scan offload request
*/
struct iwl_scan_offload_profile_match {
u8 bssid[ETH_ALEN];
__le16 reserved;
u8 channel;
u8 energy;
u8 matching_feature;
u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
/**
* struct iwl_scan_offload_profiles_query - match results query response
* @matched_profiles: bitmap of matched profiles, referencing the
* matches passed in the scan offload request
* @last_scan_age: age of the last offloaded scan
* @n_scans_done: number of offloaded scans done
* @gp2_d0u: GP2 when D0U occurred
* @gp2_invoked: GP2 when scan offload was invoked
* @resume_while_scanning: not used
* @self_recovery: obsolete
* @reserved: reserved
* @matches: array of match information, one for each match
*/
struct iwl_scan_offload_profiles_query {
__le32 matched_profiles;
__le32 last_scan_age;
__le32 n_scans_done;
__le32 gp2_d0u;
__le32 gp2_invoked;
u8 resume_while_scanning;
u8 self_recovery;
__le16 reserved;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
#endif #endif
...@@ -249,11 +249,9 @@ enum { ...@@ -249,11 +249,9 @@ enum {
WOWLAN_TX_POWER_PER_DB = 0xe6, WOWLAN_TX_POWER_PER_DB = 0xe6,
/* and for NetDetect */ /* and for NetDetect */
NET_DETECT_CONFIG_CMD = 0x54, SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
NET_DETECT_PROFILES_QUERY_CMD = 0x56, SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD = 0x58,
NET_DETECT_PROFILES_CMD = 0x57, SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD = 0x59,
NET_DETECT_HOTSPOTS_CMD = 0x58,
NET_DETECT_HOTSPOTS_QUERY_CMD = 0x59,
REPLY_MAX = 0xff, REPLY_MAX = 0xff,
}; };
...@@ -1617,7 +1615,7 @@ enum iwl_sf_scenario { ...@@ -1617,7 +1615,7 @@ enum iwl_sf_scenario {
#define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */ #define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */
/* smart FIFO default values */ /* smart FIFO default values */
#define SF_W_MARK_SISO 4096 #define SF_W_MARK_SISO 6144
#define SF_W_MARK_MIMO2 8192 #define SF_W_MARK_MIMO2 8192
#define SF_W_MARK_MIMO3 6144 #define SF_W_MARK_MIMO3 6144
#define SF_W_MARK_LEGACY 4096 #define SF_W_MARK_LEGACY 4096
......
...@@ -186,6 +186,11 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, ...@@ -186,6 +186,11 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
static const u8 alive_cmd[] = { MVM_ALIVE }; static const u8 alive_cmd[] = { MVM_ALIVE };
struct iwl_sf_region st_fwrd_space; struct iwl_sf_region st_fwrd_space;
if (ucode_type == IWL_UCODE_REGULAR &&
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_CUSTOM) &&
iwl_fw_dbg_conf_enabled(mvm->fw, FW_DBG_CUSTOM))
fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER);
else
fw = iwl_get_ucode_image(mvm, ucode_type); fw = iwl_get_ucode_image(mvm, ucode_type);
if (WARN_ON(!fw)) if (WARN_ON(!fw))
return -EINVAL; return -EINVAL;
...@@ -394,6 +399,42 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -394,6 +399,42 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
return ret; return ret;
} }
static int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm,
enum iwl_fw_dbg_conf conf_id)
{
u8 *ptr;
int ret;
int i;
if (WARN_ONCE(conf_id >= ARRAY_SIZE(mvm->fw->dbg_conf_tlv),
"Invalid configuration %d\n", conf_id))
return -EINVAL;
if (!mvm->fw->dbg_conf_tlv[conf_id])
return -EINVAL;
if (mvm->fw_dbg_conf != FW_DBG_INVALID)
IWL_WARN(mvm, "FW already configured (%d) - re-configuring\n",
mvm->fw_dbg_conf);
/* Send all HCMDs for configuring the FW debug */
ptr = (void *)&mvm->fw->dbg_conf_tlv[conf_id]->hcmd;
for (i = 0; i < mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
ret = iwl_mvm_send_cmd_pdu(mvm, cmd->id, 0,
le16_to_cpu(cmd->len), cmd->data);
if (ret)
return ret;
ptr += sizeof(*cmd);
ptr += le16_to_cpu(cmd->len);
}
mvm->fw_dbg_conf = conf_id;
return ret;
}
int iwl_mvm_up(struct iwl_mvm *mvm) int iwl_mvm_up(struct iwl_mvm *mvm)
{ {
int ret, i; int ret, i;
...@@ -445,6 +486,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -445,6 +486,9 @@ 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");
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, mvm->fw->valid_tx_ant);
if (ret) if (ret)
goto error; goto error;
......
...@@ -1304,31 +1304,22 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, ...@@ -1304,31 +1304,22 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd) struct iwl_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
struct iwl_mvm_tx_resp *beacon_notify_hdr; struct iwl_mvm_tx_resp *beacon_notify_hdr;
struct ieee80211_vif *csa_vif; struct ieee80211_vif *csa_vif;
struct ieee80211_vif *tx_blocked_vif; struct ieee80211_vif *tx_blocked_vif;
u64 tsf;
u16 status; u16 status;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) {
struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
beacon_notify_hdr = &beacon->beacon_notify_hdr; beacon_notify_hdr = &beacon->beacon_notify_hdr;
tsf = le64_to_cpu(beacon->tsf);
mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
} else {
struct iwl_beacon_notif *beacon = (void *)pkt->data;
beacon_notify_hdr = &beacon->beacon_notify_hdr;
tsf = le64_to_cpu(beacon->tsf);
}
status = le16_to_cpu(beacon_notify_hdr->status.status) & TX_STATUS_MSK; status = le16_to_cpu(beacon_notify_hdr->status.status) & TX_STATUS_MSK;
IWL_DEBUG_RX(mvm, IWL_DEBUG_RX(mvm,
"beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n", "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
status, beacon_notify_hdr->failure_frame, tsf, status, beacon_notify_hdr->failure_frame,
le64_to_cpu(beacon->tsf),
mvm->ap_last_beacon_gp2, mvm->ap_last_beacon_gp2,
le32_to_cpu(beacon_notify_hdr->initial_rate)); le32_to_cpu(beacon_notify_hdr->initial_rate));
......
...@@ -337,7 +337,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -337,7 +337,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->flags |= IEEE80211_HW_MFP_CAPABLE;
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT && if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
!iwlwifi_mod_params.uapsd_disable) { !iwlwifi_mod_params.uapsd_disable) {
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
...@@ -370,7 +369,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -370,7 +369,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
...@@ -2577,10 +2575,16 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -2577,10 +2575,16 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (mvm->fw->ucode_capa.capa[0] &
IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
/* Use aux roc framework (HS20) */ /* Use aux roc framework (HS20) */
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration); vif, duration);
goto out_unlock; goto out_unlock;
}
IWL_ERR(mvm, "hotspot not supported\n");
ret = -EINVAL;
goto out_unlock;
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
/* handle below */ /* handle below */
break; break;
......
...@@ -295,7 +295,6 @@ enum iwl_bt_force_ant_mode { ...@@ -295,7 +295,6 @@ enum iwl_bt_force_ant_mode {
* struct iwl_mvm_vif_bf_data - beacon filtering related data * struct iwl_mvm_vif_bf_data - beacon filtering related data
* @bf_enabled: indicates if beacon filtering is enabled * @bf_enabled: indicates if beacon filtering is enabled
* @ba_enabled: indicated if beacon abort is enabled * @ba_enabled: indicated if beacon abort is enabled
* @last_beacon_signal: last beacon rssi signal in dbm
* @ave_beacon_signal: average beacon signal * @ave_beacon_signal: average beacon signal
* @last_cqm_event: rssi of the last cqm event * @last_cqm_event: rssi of the last cqm event
* @bt_coex_min_thold: minimum threshold for BT coex * @bt_coex_min_thold: minimum threshold for BT coex
...@@ -671,6 +670,7 @@ struct iwl_mvm { ...@@ -671,6 +670,7 @@ struct iwl_mvm {
/* -1 for always, 0 for never, >0 for that many times */ /* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw; s8 restart_fw;
struct work_struct fw_error_dump_wk; struct work_struct fw_error_dump_wk;
enum iwl_fw_dbg_conf fw_dbg_conf;
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led; struct led_classdev led;
...@@ -685,6 +685,10 @@ struct iwl_mvm { ...@@ -685,6 +685,10 @@ struct iwl_mvm {
/* sched scan settings for net detect */ /* sched scan settings for net detect */
struct cfg80211_sched_scan_request *nd_config; struct cfg80211_sched_scan_request *nd_config;
struct ieee80211_scan_ies nd_ies; struct ieee80211_scan_ies nd_ies;
struct cfg80211_match_set *nd_match_sets;
int n_nd_match_sets;
struct ieee80211_channel **nd_channels;
int n_nd_channels;
bool net_detect; bool net_detect;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
...@@ -1143,7 +1147,7 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1143,7 +1147,7 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
} }
#endif #endif
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
struct iwl_wowlan_config_cmd_v2 *cmd); struct iwl_wowlan_config_cmd *cmd);
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
bool disable_offloading, bool disable_offloading,
......
...@@ -339,11 +339,15 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ...@@ -339,11 +339,15 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
} *file_sec; } *file_sec;
const u8 *eof, *temp; const u8 *eof, *temp;
int max_section_size; int max_section_size;
const __le32 *dword_buff;
#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_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4) #define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
#define NVM_HEADER_0 (0x2A504C54)
#define NVM_HEADER_1 (0x4E564D2A)
#define NVM_HEADER_SIZE (4 * sizeof(u32))
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
...@@ -372,12 +376,6 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ...@@ -372,12 +376,6 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",
mvm->nvm_file_name, fw_entry->size); mvm->nvm_file_name, fw_entry->size);
if (fw_entry->size < sizeof(*file_sec)) {
IWL_ERR(mvm, "NVM file too small\n");
ret = -EINVAL;
goto out;
}
if (fw_entry->size > MAX_NVM_FILE_LEN) { if (fw_entry->size > MAX_NVM_FILE_LEN) {
IWL_ERR(mvm, "NVM file too large\n"); IWL_ERR(mvm, "NVM file too large\n");
ret = -EINVAL; ret = -EINVAL;
...@@ -385,8 +383,25 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ...@@ -385,8 +383,25 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
} }
eof = fw_entry->data + fw_entry->size; eof = fw_entry->data + fw_entry->size;
dword_buff = (__le32 *)fw_entry->data;
/* some NVM file will contain a header.
* The header is identified by 2 dwords header as follow:
* dword[0] = 0x2A504C54
* dword[1] = 0x4E564D2A
*
* This header must be skipped when providing the NVM data to the FW.
*/
if (fw_entry->size > NVM_HEADER_SIZE &&
dword_buff[0] == cpu_to_le32(NVM_HEADER_0) &&
dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) {
file_sec = (void *)(fw_entry->data + NVM_HEADER_SIZE);
IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
IWL_INFO(mvm, "NVM Manufacturing date %08X\n",
le32_to_cpu(dword_buff[3]));
} else {
file_sec = (void *)fw_entry->data; file_sec = (void *)fw_entry->data;
}
while (true) { while (true) {
if (file_sec->data > eof) { if (file_sec->data > eof) {
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
#include "mvm.h" #include "mvm.h"
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
struct iwl_wowlan_config_cmd_v2 *cmd) struct iwl_wowlan_config_cmd *cmd)
{ {
int i; int i;
......
...@@ -325,11 +325,9 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { ...@@ -325,11 +325,9 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(WOWLAN_KEK_KCK_MATERIAL), CMD(WOWLAN_KEK_KCK_MATERIAL),
CMD(WOWLAN_GET_STATUSES), CMD(WOWLAN_GET_STATUSES),
CMD(WOWLAN_TX_POWER_PER_DB), CMD(WOWLAN_TX_POWER_PER_DB),
CMD(NET_DETECT_CONFIG_CMD), CMD(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
CMD(NET_DETECT_PROFILES_QUERY_CMD), CMD(SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD),
CMD(NET_DETECT_PROFILES_CMD), CMD(SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD),
CMD(NET_DETECT_HOTSPOTS_CMD),
CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
CMD(CARD_STATE_NOTIFICATION), CMD(CARD_STATE_NOTIFICATION),
CMD(MISSED_BEACONS_NOTIFICATION), CMD(MISSED_BEACONS_NOTIFICATION),
CMD(BT_COEX_PRIO_TABLE), CMD(BT_COEX_PRIO_TABLE),
...@@ -498,6 +496,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -498,6 +496,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv;
trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num;
memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
sizeof(trans->dbg_conf_tlv));
/* set up notification wait support */ /* set up notification wait support */
iwl_notification_wait_init(&mvm->notif_wait); iwl_notification_wait_init(&mvm->notif_wait);
...@@ -1002,7 +1004,7 @@ static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, ...@@ -1002,7 +1004,7 @@ static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac,
} }
static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
struct iwl_wowlan_config_cmd_v3 *cmd, struct iwl_wowlan_config_cmd *cmd,
struct iwl_d0i3_iter_data *iter_data) struct iwl_d0i3_iter_data *iter_data)
{ {
struct ieee80211_sta *ap_sta; struct ieee80211_sta *ap_sta;
...@@ -1018,14 +1020,14 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, ...@@ -1018,14 +1020,14 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
goto out; goto out;
mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta); mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
cmd->common.is_11n_connection = ap_sta->ht_cap.ht_supported; cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
cmd->offloading_tid = iter_data->offloading_tid; cmd->offloading_tid = iter_data->offloading_tid;
/* /*
* The d0i3 uCode takes care of the nonqos counters, * The d0i3 uCode takes care of the nonqos counters,
* so configure only the qos seq ones. * so configure only the qos seq ones.
*/ */
iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &cmd->common); iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
out: out:
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -1037,14 +1039,11 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) ...@@ -1037,14 +1039,11 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
struct iwl_d0i3_iter_data d0i3_iter_data = { struct iwl_d0i3_iter_data d0i3_iter_data = {
.mvm = mvm, .mvm = mvm,
}; };
struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = { struct iwl_wowlan_config_cmd wowlan_config_cmd = {
.common = { .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
.wakeup_filter =
cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
IWL_WOWLAN_WAKEUP_BEACON_MISS | IWL_WOWLAN_WAKEUP_BEACON_MISS |
IWL_WOWLAN_WAKEUP_LINK_CHANGE | IWL_WOWLAN_WAKEUP_LINK_CHANGE |
IWL_WOWLAN_WAKEUP_BCN_FILTERING), IWL_WOWLAN_WAKEUP_BCN_FILTERING),
},
}; };
struct iwl_d3_manager_config d3_cfg_cmd = { struct iwl_d3_manager_config d3_cfg_cmd = {
.min_sleep_time = cpu_to_le32(1000), .min_sleep_time = cpu_to_le32(1000),
......
This diff is collapsed.
...@@ -989,6 +989,65 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, ...@@ -989,6 +989,65 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
spin_unlock_bh(&txq->lock); spin_unlock_bh(&txq->lock);
} }
static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
lockdep_assert_held(&trans_pcie->reg_lock);
if (trans_pcie->cmd_in_flight)
return 0;
trans_pcie->cmd_in_flight = true;
/*
* wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set.
*/
if (trans->cfg->base_params->apmg_wake_up_wa) {
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
udelay(2);
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
15000);
if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
trans_pcie->cmd_in_flight = false;
IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
return -EIO;
}
}
return 0;
}
static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
lockdep_assert_held(&trans_pcie->reg_lock);
if (WARN_ON(!trans_pcie->cmd_in_flight))
return 0;
trans_pcie->cmd_in_flight = false;
if (trans->cfg->base_params->apmg_wake_up_wa)
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return 0;
}
/* /*
* iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd
* *
...@@ -1024,14 +1083,9 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) ...@@ -1024,14 +1083,9 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
} }
} }
if (trans->cfg->base_params->apmg_wake_up_wa && if (q->read_ptr == q->write_ptr) {
q->read_ptr == q->write_ptr) {
spin_lock_irqsave(&trans_pcie->reg_lock, flags); spin_lock_irqsave(&trans_pcie->reg_lock, flags);
WARN_ON(!trans_pcie->cmd_in_flight); iwl_pcie_clear_cmd_in_flight(trans);
trans_pcie->cmd_in_flight = false;
__iwl_trans_pcie_clear_bit(trans,
CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
} }
...@@ -1419,36 +1473,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, ...@@ -1419,36 +1473,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
spin_lock_irqsave(&trans_pcie->reg_lock, flags); spin_lock_irqsave(&trans_pcie->reg_lock, flags);
ret = iwl_pcie_set_cmd_in_flight(trans);
/*
* wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set.
*/
if (trans->cfg->base_params->apmg_wake_up_wa &&
!trans_pcie->cmd_in_flight) {
trans_pcie->cmd_in_flight = true;
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
udelay(2);
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
15000);
if (ret < 0) { if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, idx = ret;
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
trans_pcie->cmd_in_flight = false;
IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
idx = -EIO;
goto out; goto out;
} }
}
/* Increment and update queue's write index */ /* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr); q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment