Merge tag 'iwlwifi-for-kalle-2016-02-15' into HEAD

These are a few fixes for the current cycle.
3 out of the 5 patches fix a bugzilla.

* fix a race that users reported when we try to load the firmware
  and the hardware rfkill interrupt triggers at the same time.
* Luca fixes a very visible bug in scheduled scan: our firmware
  doesn't support scheduled scan with no profile configured and
  the supplicant sometimes requests such scheduled scans.
* build system fix
* firmware name update for 8265
* typo fix in return value
This commit is contained in:
Emmanuel Grumbach 2016-02-25 10:59:41 +02:00
commit 3cce9bb07b
12 changed files with 243 additions and 127 deletions

View File

@ -53,7 +53,6 @@ config IWLWIFI_LEDS
config IWLDVM config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support" tristate "Intel Wireless WiFi DVM Firmware support"
depends on m
help help
This is the driver that supports the DVM firmware. The list This is the driver that supports the DVM firmware. The list
of the devices that use this firmware is available here: of the devices that use this firmware is available here:

View File

@ -74,16 +74,19 @@
#define IWL7260_UCODE_API_MAX 17 #define IWL7260_UCODE_API_MAX 17
#define IWL7265_UCODE_API_MAX 17 #define IWL7265_UCODE_API_MAX 17
#define IWL7265D_UCODE_API_MAX 20 #define IWL7265D_UCODE_API_MAX 20
#define IWL3168_UCODE_API_MAX 20
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 13 #define IWL7260_UCODE_API_OK 13
#define IWL7265_UCODE_API_OK 13 #define IWL7265_UCODE_API_OK 13
#define IWL7265D_UCODE_API_OK 13 #define IWL7265D_UCODE_API_OK 13
#define IWL3168_UCODE_API_OK 20
/* Lowest firmware API version supported */ /* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 13 #define IWL7260_UCODE_API_MIN 13
#define IWL7265_UCODE_API_MIN 13 #define IWL7265_UCODE_API_MIN 13
#define IWL7265D_UCODE_API_MIN 13 #define IWL7265D_UCODE_API_MIN 13
#define IWL3168_UCODE_API_MIN 20
/* NVM versions */ /* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d #define IWL7260_NVM_VERSION 0x0a1d
@ -92,6 +95,8 @@
#define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL3165_NVM_VERSION 0x709 #define IWL3165_NVM_VERSION 0x709
#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL3168_NVM_VERSION 0xd01
#define IWL3168_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 IWL7265D_NVM_VERSION 0x0c11
@ -109,6 +114,9 @@
#define IWL3160_FW_PRE "iwlwifi-3160-" #define IWL3160_FW_PRE "iwlwifi-3160-"
#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
#define IWL3168_FW_PRE "iwlwifi-3168-"
#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode"
#define IWL7265_FW_PRE "iwlwifi-7265-" #define IWL7265_FW_PRE "iwlwifi-7265-"
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
@ -180,6 +188,12 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.ucode_api_ok = IWL7265_UCODE_API_OK, \ .ucode_api_ok = IWL7265_UCODE_API_OK, \
.ucode_api_min = IWL7265_UCODE_API_MIN .ucode_api_min = IWL7265_UCODE_API_MIN
#define IWL_DEVICE_3008 \
IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL3168_UCODE_API_MAX, \
.ucode_api_ok = IWL3168_UCODE_API_OK, \
.ucode_api_min = IWL3168_UCODE_API_MIN
#define IWL_DEVICE_7005D \ #define IWL_DEVICE_7005D \
IWL_DEVICE_7000_COMMON, \ IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL7265D_UCODE_API_MAX, \ .ucode_api_max = IWL7265D_UCODE_API_MAX, \
@ -299,11 +313,11 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
const struct iwl_cfg iwl3168_2ac_cfg = { const struct iwl_cfg iwl3168_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168", .name = "Intel(R) Dual Band Wireless AC 3168",
.fw_name_pre = IWL7265D_FW_PRE, .fw_name_pre = IWL3168_FW_PRE,
IWL_DEVICE_7000, IWL_DEVICE_3008,
.ht_params = &iwl7000_ht_params, .ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3165_NVM_VERSION, .nvm_ver = IWL3168_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION, .nvm_calib_ver = IWL3168_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN, .dccm_len = IWL7265_DCCM_LEN,
}; };
@ -376,5 +390,6 @@ const struct iwl_cfg iwl7265d_n_cfg = {
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK));

View File

@ -7,6 +7,7 @@
* *
* Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@ -70,12 +71,15 @@
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX 20 #define IWL8000_UCODE_API_MAX 20
#define IWL8265_UCODE_API_MAX 20
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK 13 #define IWL8000_UCODE_API_OK 13
#define IWL8265_UCODE_API_OK 20
/* Lowest firmware API version supported */ /* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 13 #define IWL8000_UCODE_API_MIN 13
#define IWL8265_UCODE_API_MIN 20
/* NVM versions */ /* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d #define IWL8000_NVM_VERSION 0x0a1d
@ -93,6 +97,10 @@
#define IWL8000_MODULE_FIRMWARE(api) \ #define IWL8000_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE "-" __stringify(api) ".ucode" IWL8000_FW_PRE "-" __stringify(api) ".ucode"
#define IWL8265_FW_PRE "iwlwifi-8265-"
#define IWL8265_MODULE_FIRMWARE(api) \
IWL8265_FW_PRE __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10 #define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.support_tx_backoff = true, .support_tx_backoff = true,
}; };
#define IWL_DEVICE_8000 \ #define IWL_DEVICE_8000_COMMON \
.ucode_api_max = IWL8000_UCODE_API_MAX, \
.ucode_api_ok = IWL8000_UCODE_API_OK, \
.ucode_api_min = IWL8000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_8000, \ .device_family = IWL_DEVICE_FAMILY_8000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.thermal_params = &iwl8000_tt_params, \ .thermal_params = &iwl8000_tt_params, \
.apmg_not_supported = true .apmg_not_supported = true
#define IWL_DEVICE_8000 \
IWL_DEVICE_8000_COMMON, \
.ucode_api_max = IWL8000_UCODE_API_MAX, \
.ucode_api_ok = IWL8000_UCODE_API_OK, \
.ucode_api_min = IWL8000_UCODE_API_MIN \
#define IWL_DEVICE_8260 \
IWL_DEVICE_8000_COMMON, \
.ucode_api_max = IWL8000_UCODE_API_MAX, \
.ucode_api_ok = IWL8000_UCODE_API_OK, \
.ucode_api_min = IWL8000_UCODE_API_MIN \
#define IWL_DEVICE_8265 \
IWL_DEVICE_8000_COMMON, \
.ucode_api_max = IWL8265_UCODE_API_MAX, \
.ucode_api_ok = IWL8265_UCODE_API_OK, \
.ucode_api_min = IWL8265_UCODE_API_MIN \
const struct iwl_cfg iwl8260_2n_cfg = { const struct iwl_cfg iwl8260_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 8260", .name = "Intel(R) Dual Band Wireless N 8260",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000, IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params, .ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = {
const struct iwl_cfg iwl8260_2ac_cfg = { const struct iwl_cfg iwl8260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8260", .name = "Intel(R) Dual Band Wireless AC 8260",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000, IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params, .ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
const struct iwl_cfg iwl8265_2ac_cfg = { const struct iwl_cfg iwl8265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8265", .name = "Intel(R) Dual Band Wireless AC 8265",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8265_FW_PRE,
IWL_DEVICE_8000, IWL_DEVICE_8265,
.ht_params = &iwl8000_ht_params, .ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = {
const struct iwl_cfg iwl8260_2ac_sdio_cfg = { const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.name = "Intel(R) Dual Band Wireless-AC 8260", .name = "Intel(R) Dual Band Wireless-AC 8260",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000, IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params, .ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION, .nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION, .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
}; };
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK));

View File

@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev);
snprintf(drv->firmware_name, sizeof(drv->firmware_name), if (rev_step != 'A')
"%s%c-%s.ucode", name_pre, rev_step, tag); snprintf(drv->firmware_name,
sizeof(drv->firmware_name), "%s%c-%s.ucode",
name_pre, rev_step, tag);
} }
IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",

View File

@ -510,6 +510,9 @@ struct iwl_mvm_tx_resp {
* @scd_ssn: the index of the last contiguously sent packet * @scd_ssn: the index of the last contiguously sent packet
* @txed: number of Txed frames in this batch * @txed: number of Txed frames in this batch
* @txed_2_done: number of Acked frames in this batch * @txed_2_done: number of Acked frames in this batch
* @reduced_txp: power reduced according to TPC. This is the actual value and
* not a copy from the LQ command. Thus, if not the first rate was used
* for Tx-ing then this value will be set to 0 by FW.
*/ */
struct iwl_mvm_ba_notif { struct iwl_mvm_ba_notif {
__le32 sta_addr_lo32; __le32 sta_addr_lo32;
@ -524,7 +527,8 @@ struct iwl_mvm_ba_notif {
__le16 scd_ssn; __le16 scd_ssn;
u8 txed; u8 txed;
u8 txed_2_done; u8 txed_2_done;
__le16 reserved1; u8 reduced_txp;
u8 reserved1;
} __packed; } __packed;
/* /*

View File

@ -2,6 +2,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as * under the terms of version 2 of the GNU General Public License as
@ -724,14 +725,28 @@ static int _rs_collect_tx_data(struct iwl_mvm *mvm,
return 0; return 0;
} }
static int rs_collect_tx_data(struct iwl_mvm *mvm, static int rs_collect_tpc_data(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta, struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes, int scale_index, int attempts, int successes,
u8 reduced_txp) u8 reduced_txp)
{
struct iwl_rate_scale_data *window = NULL;
if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION))
return -EINVAL;
window = &tbl->tpc_win[reduced_txp];
return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
window);
}
static int rs_collect_tlc_data(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes)
{ {
struct iwl_rate_scale_data *window = NULL; struct iwl_rate_scale_data *window = NULL;
int ret;
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
return -EINVAL; return -EINVAL;
@ -745,16 +760,6 @@ static int rs_collect_tx_data(struct iwl_mvm *mvm,
/* Select window for current tx bit rate */ /* Select window for current tx bit rate */
window = &(tbl->win[scale_index]); window = &(tbl->win[scale_index]);
ret = _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
window);
if (ret)
return ret;
if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION))
return -EINVAL;
window = &tbl->tpc_win[reduced_txp];
return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
window); window);
} }
@ -1301,17 +1306,30 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* first index into rate scale table. * first index into rate scale table.
*/ */
if (info->flags & IEEE80211_TX_STAT_AMPDU) { if (info->flags & IEEE80211_TX_STAT_AMPDU) {
/* ampdu_ack_len = 0 marks no BA was received. In this case rs_collect_tpc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
* treat it as a single frame loss as we don't want the success info->status.ampdu_len,
* ratio to dip too quickly because a BA wasn't received info->status.ampdu_ack_len,
reduced_txp);
/* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
* it as a single frame loss as we don't want the success ratio
* to dip too quickly because a BA wasn't received.
* For TPC, there's no need for this optimisation since we want
* to recover very quickly from a bad power reduction and,
* therefore we'd like the success ratio to get an immediate hit
* when failing to get a BA, so we'd switch back to a lower or
* zero power reduction. When FW transmits agg with a rate
* different from the initial rate, it will not use reduced txp
* and will send BA notification twice (one empty with reduced
* txp equal to the value from LQ and one with reduced txp 0).
* We need to update counters for each txp level accordingly.
*/ */
if (info->status.ampdu_ack_len == 0) if (info->status.ampdu_ack_len == 0)
info->status.ampdu_len = 1; info->status.ampdu_len = 1;
rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index, rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
info->status.ampdu_len, info->status.ampdu_len,
info->status.ampdu_ack_len, info->status.ampdu_ack_len);
reduced_txp);
/* Update success/fail counts if not searching for new mode */ /* Update success/fail counts if not searching for new mode */
if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
@ -1344,9 +1362,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
else else
continue; continue;
rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index, rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
1, i < retries ? 0 : legacy_success, lq_rate.index, 1,
reduced_txp); i < retries ? 0 : legacy_success,
reduced_txp);
rs_collect_tlc_data(mvm, lq_sta, tmp_tbl,
lq_rate.index, 1,
i < retries ? 0 : legacy_success);
} }
/* Update success/fail counts if not searching for new mode */ /* Update success/fail counts if not searching for new mode */

View File

@ -1301,6 +1301,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
return -EBUSY; return -EBUSY;
} }
/* we don't support "match all" in the firmware */
if (!req->n_match_sets)
return -EOPNOTSUPP;
ret = iwl_mvm_check_running_scans(mvm, type); ret = iwl_mvm_check_running_scans(mvm, type);
if (ret) if (ret)
return ret; return ret;

View File

@ -1064,7 +1064,6 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
mvmsta->tid_data[tid].rate_n_flags = mvmsta->tid_data[tid].rate_n_flags =
le32_to_cpu(tx_resp->initial_rate); le32_to_cpu(tx_resp->initial_rate);
mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc;
mvmsta->tid_data[tid].tx_time = mvmsta->tid_data[tid].tx_time =
le16_to_cpu(tx_resp->wireless_media_time); le16_to_cpu(tx_resp->wireless_media_time);
} }
@ -1095,7 +1094,7 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info,
/* TODO: not accounted if the whole A-MPDU failed */ /* TODO: not accounted if the whole A-MPDU failed */
info->status.tx_time = tid_data->tx_time; info->status.tx_time = tid_data->tx_time;
info->status.status_driver_data[0] = info->status.status_driver_data[0] =
(void *)(uintptr_t)tid_data->reduced_tpc; (void *)(uintptr_t)ba_notif->reduced_txp;
info->status.status_driver_data[1] = info->status.status_driver_data[1] =
(void *)(uintptr_t)tid_data->rate_n_flags; (void *)(uintptr_t)tid_data->rate_n_flags;
} }
@ -1168,6 +1167,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
scd_flow, ba_resp_scd_ssn, ba_notif->txed, scd_flow, ba_resp_scd_ssn, ba_notif->txed,
ba_notif->txed_2_done); ba_notif->txed_2_done);
IWL_DEBUG_TX_REPLY(mvm, "reduced txp from ba notif %d\n",
ba_notif->reduced_txp);
tid_data->next_reclaimed = ba_resp_scd_ssn; tid_data->next_reclaimed = ba_resp_scd_ssn;
iwl_mvm_check_ratid_empty(mvm, sta, tid); iwl_mvm_check_ratid_empty(mvm, sta, tid);

View File

@ -380,7 +380,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
/* 3168 Series */ /* 3168 Series */
{IWL_PCI_DEVICE(0x24FB, 0x2010, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x2050, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x2150, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)},
/* 7265 Series */ /* 7265 Series */
@ -477,6 +480,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)}, {IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)},
/* 9000 Series */ /* 9000 Series */
{IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)},

View File

@ -507,6 +507,15 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
} }
static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n");
trans_pcie->inta_mask = CSR_INT_BIT_FH_TX;
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
}
static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);

View File

@ -1614,9 +1614,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
inta & ~trans_pcie->inta_mask); inta & ~trans_pcie->inta_mask);
} }
/* Re-enable all interrupts */ /* we are loading the firmware, enable FH_TX interrupt only */
/* only Re-enable if disabled by irq */ if (handled & CSR_INT_BIT_FH_TX)
if (test_bit(STATUS_INT_ENABLED, &trans->status)) iwl_enable_fw_load_int(trans);
/* only Re-enable all interrupt if disabled by irq */
else if (test_bit(STATUS_INT_ENABLED, &trans->status))
iwl_enable_interrupts(trans); iwl_enable_interrupts(trans);
/* Re-enable RF_KILL if it occurred */ /* Re-enable RF_KILL if it occurred */
else if (handled & CSR_INT_BIT_RF_KILL) else if (handled & CSR_INT_BIT_RF_KILL)

View File

@ -1022,82 +1022,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
&first_ucode_section); &first_ucode_section);
} }
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill;
int ret;
mutex_lock(&trans_pcie->mutex);
/* Someone called stop_device, don't try to start_fw */
if (trans_pcie->is_down) {
IWL_WARN(trans,
"Can't start_fw since the HW hasn't been started\n");
ret = EIO;
goto out;
}
/* This may fail if AMT took ownership of the device */
if (iwl_pcie_prepare_card_hw(trans)) {
IWL_WARN(trans, "Exit HW not ready\n");
ret = -EIO;
goto out;
}
iwl_enable_rfkill_int(trans);
/* If platform's RF_KILL switch is NOT set to KILL */
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
if (hw_rfkill && !run_in_rfkill) {
ret = -ERFKILL;
goto out;
}
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
ret = iwl_pcie_nic_init(trans);
if (ret) {
IWL_ERR(trans, "Unable to init nic\n");
goto out;
}
/* make sure rfkill handshake bits are cleared */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
/* clear (again), then enable host interrupts */
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
iwl_enable_interrupts(trans);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else
ret = iwl_pcie_load_given_ucode(trans, fw);
out:
mutex_unlock(&trans_pcie->mutex);
return ret;
}
static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
{
iwl_pcie_reset_ict(trans);
iwl_pcie_tx_start(trans, scd_addr);
}
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -1128,7 +1052,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
* already dead. * already dead.
*/ */
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); IWL_DEBUG_INFO(trans,
"DEVICE_ENABLED bit was set and is now cleared\n");
iwl_pcie_tx_stop(trans); iwl_pcie_tx_stop(trans);
iwl_pcie_rx_stop(trans); iwl_pcie_rx_stop(trans);
@ -1162,7 +1087,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
spin_unlock(&trans_pcie->irq_lock); spin_unlock(&trans_pcie->irq_lock);
/* clear all status bits */ /* clear all status bits */
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status); clear_bit(STATUS_INT_ENABLED, &trans->status);
@ -1195,10 +1119,116 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
if (hw_rfkill != was_hw_rfkill) if (hw_rfkill != was_hw_rfkill)
iwl_trans_pcie_rf_kill(trans, hw_rfkill); iwl_trans_pcie_rf_kill(trans, hw_rfkill);
/* re-take ownership to prevent other users from stealing the deivce */ /* re-take ownership to prevent other users from stealing the device */
iwl_pcie_prepare_card_hw(trans); iwl_pcie_prepare_card_hw(trans);
} }
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill;
int ret;
/* This may fail if AMT took ownership of the device */
if (iwl_pcie_prepare_card_hw(trans)) {
IWL_WARN(trans, "Exit HW not ready\n");
ret = -EIO;
goto out;
}
iwl_enable_rfkill_int(trans);
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
/*
* We enabled the RF-Kill interrupt and the handler may very
* well be running. Disable the interrupts to make sure no other
* interrupt can be fired.
*/
iwl_disable_interrupts(trans);
/* Make sure it finished running */
synchronize_irq(trans_pcie->pci_dev->irq);
mutex_lock(&trans_pcie->mutex);
/* If platform's RF_KILL switch is NOT set to KILL */
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
if (hw_rfkill && !run_in_rfkill) {
ret = -ERFKILL;
goto out;
}
/* Someone called stop_device, don't try to start_fw */
if (trans_pcie->is_down) {
IWL_WARN(trans,
"Can't start_fw since the HW hasn't been started\n");
ret = -EIO;
goto out;
}
/* make sure rfkill handshake bits are cleared */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
/* clear (again), then enable host interrupts */
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
ret = iwl_pcie_nic_init(trans);
if (ret) {
IWL_ERR(trans, "Unable to init nic\n");
goto out;
}
/*
* Now, we load the firmware and don't want to be interrupted, even
* by the RF-Kill interrupt (hence mask all the interrupt besides the
* FH_TX interrupt which is needed to load the firmware). If the
* RF-Kill switch is toggled, we will find out after having loaded
* the firmware and return the proper value to the caller.
*/
iwl_enable_fw_load_int(trans);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else
ret = iwl_pcie_load_given_ucode(trans, fw);
iwl_enable_interrupts(trans);
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
if (hw_rfkill && !run_in_rfkill)
ret = -ERFKILL;
out:
mutex_unlock(&trans_pcie->mutex);
return ret;
}
static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
{
iwl_pcie_reset_ict(trans);
iwl_pcie_tx_start(trans, scd_addr);
}
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);