Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
eb2eacf77e
drivers/net/wireless/iwlwifi
|
@ -40,7 +40,7 @@
|
|||
#include "commands.h"
|
||||
#include "power.h"
|
||||
|
||||
static bool force_cam;
|
||||
static bool force_cam = true;
|
||||
module_param(force_cam, bool, 0644);
|
||||
MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)");
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@
|
|||
#define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */
|
||||
#define IWL3160_NVM_VERSION 0x709
|
||||
#define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */
|
||||
#define IWL3165_NVM_VERSION 0x709
|
||||
#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */
|
||||
#define IWL7265_NVM_VERSION 0x0a1d
|
||||
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
|
||||
|
||||
|
@ -94,6 +96,9 @@
|
|||
#define IWL3160_FW_PRE "iwlwifi-3160-"
|
||||
#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
#define IWL3165_FW_PRE "iwlwifi-3165-"
|
||||
#define IWL3165_MODULE_FIRMWARE(api) IWL3165_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
#define IWL7265_FW_PRE "iwlwifi-7265-"
|
||||
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
|
@ -126,7 +131,8 @@ static const struct iwl_ht_params iwl7000_ht_params = {
|
|||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.base_params = &iwl7000_base_params, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000
|
||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \
|
||||
.non_shared_ant = ANT_A
|
||||
|
||||
|
||||
const struct iwl_cfg iwl7260_2ac_cfg = {
|
||||
|
@ -215,11 +221,27 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
|
|||
{0},
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7265_ht_params = {
|
||||
.stbc = true,
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl3165_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 3165",
|
||||
.fw_name_pre = IWL3165_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL3165_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7265_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7265",
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
|
@ -229,7 +251,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
|
|||
.name = "Intel(R) Dual Band Wireless N 7265",
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
|
@ -239,7 +261,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
|
|||
.name = "Intel(R) Wireless N 7265",
|
||||
.fw_name_pre = IWL7265_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.ht_params = &iwl7265_ht_params,
|
||||
.nvm_ver = IWL7265_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
|
||||
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
|
||||
|
@ -247,4 +269,5 @@ const struct iwl_cfg iwl7265_n_cfg = {
|
|||
|
||||
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
|
||||
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
|
||||
MODULE_FIRMWARE(IWL3165_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
|
||||
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
|
||||
|
|
|
@ -103,6 +103,7 @@ static const struct iwl_base_params iwl8000_base_params = {
|
|||
};
|
||||
|
||||
static const struct iwl_ht_params iwl8000_ht_params = {
|
||||
.ldpc = true,
|
||||
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
|
@ -115,7 +116,17 @@ static const struct iwl_ht_params iwl8000_ht_params = {
|
|||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.base_params = &iwl8000_base_params, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000
|
||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
|
||||
.non_shared_ant = ANT_A
|
||||
|
||||
const struct iwl_cfg iwl8260_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 8260",
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8000,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8260_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 8260",
|
||||
|
@ -135,6 +146,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
|
|||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.disable_dummy_notification = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
|
||||
|
|
|
@ -120,6 +120,8 @@ enum iwl_led_mode {
|
|||
#define IWL_LONG_WD_TIMEOUT 10000
|
||||
#define IWL_MAX_WD_TIMEOUT 120000
|
||||
|
||||
#define IWL_DEFAULT_MAX_TX_POWER 22
|
||||
|
||||
/* Antenna presence definitions */
|
||||
#define ANT_NONE 0x0
|
||||
#define ANT_A BIT(0)
|
||||
|
@ -169,6 +171,7 @@ struct iwl_base_params {
|
|||
|
||||
/*
|
||||
* @stbc: support Tx STBC and 1*SS Rx STBC
|
||||
* @ldpc: support Tx/Rx with LDPC
|
||||
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
|
||||
* @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40
|
||||
*/
|
||||
|
@ -176,6 +179,7 @@ struct iwl_ht_params {
|
|||
enum ieee80211_smps_mode smps_mode;
|
||||
const bool ht_greenfield_support; /* if used set to true */
|
||||
const bool stbc;
|
||||
const bool ldpc;
|
||||
bool use_rts_for_aggregation;
|
||||
u8 ht40_bands;
|
||||
};
|
||||
|
@ -226,6 +230,7 @@ struct iwl_pwr_tx_backoff {
|
|||
* @max_data_size: The maximal length of the fw data section
|
||||
* @valid_tx_ant: valid transmit antenna
|
||||
* @valid_rx_ant: valid receive antenna
|
||||
* @non_shared_ant: the antenna that is for WiFi only
|
||||
* @nvm_ver: NVM version
|
||||
* @nvm_calib_ver: NVM calibration version
|
||||
* @lib: pointer to the lib ops
|
||||
|
@ -258,6 +263,7 @@ struct iwl_cfg {
|
|||
const u32 max_inst_size;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 non_shared_ant;
|
||||
bool bt_shared_single_ant;
|
||||
u16 nvm_ver;
|
||||
u16 nvm_calib_ver;
|
||||
|
@ -278,6 +284,7 @@ struct iwl_cfg {
|
|||
bool no_power_up_nic_in_init;
|
||||
const char *default_nvm_file;
|
||||
unsigned int max_rx_agg_size;
|
||||
bool disable_dummy_notification;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -335,9 +342,11 @@ extern const struct iwl_cfg iwl7260_n_cfg;
|
|||
extern const struct iwl_cfg iwl3160_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_n_cfg;
|
||||
extern const struct iwl_cfg iwl3165_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7265_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7265_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7265_n_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2n_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
|
|
@ -295,6 +295,16 @@
|
|||
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
|
||||
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
|
||||
|
||||
|
||||
/**
|
||||
* hw_rev values
|
||||
*/
|
||||
enum {
|
||||
SILICON_A_STEP = 0,
|
||||
SILICON_B_STEP,
|
||||
};
|
||||
|
||||
|
||||
#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
|
||||
#define CSR_HW_REV_TYPE_5300 (0x0000020)
|
||||
#define CSR_HW_REV_TYPE_5350 (0x0000030)
|
||||
|
|
|
@ -1363,7 +1363,7 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)")
|
|||
module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(antenna_coupling,
|
||||
"specify antenna coupling in dB (defualt: 0 dB)");
|
||||
"specify antenna coupling in dB (default: 0 dB)");
|
||||
|
||||
module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(wd_disable,
|
||||
|
|
|
@ -758,6 +758,9 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
|||
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
}
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ enum iwl_ucode_tlv_flag {
|
|||
* @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
|
||||
* @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
|
||||
* @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
|
||||
* @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.
|
||||
* @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
|
||||
* longer than the passive one, which is essential for fragmented scan.
|
||||
*/
|
||||
|
@ -137,6 +138,7 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
|
||||
IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5),
|
||||
IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6),
|
||||
IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7),
|
||||
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
|
||||
};
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ void iwl_force_nmi(struct iwl_trans *trans)
|
|||
* DEVICE_SET_NMI_8000B_REG - is used.
|
||||
*/
|
||||
if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) ||
|
||||
((trans->hw_rev & 0xc) == 0x0))
|
||||
(CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP))
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL);
|
||||
else
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG,
|
||||
|
|
|
@ -148,8 +148,6 @@ static const u8 iwl_nvm_channels_family_8000[] = {
|
|||
#define LAST_2GHZ_HT_PLUS 9
|
||||
#define LAST_5GHZ_HT 161
|
||||
|
||||
#define DEFAULT_MAX_TX_POWER 16
|
||||
|
||||
/* rate data (static) */
|
||||
static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
|
||||
|
@ -297,7 +295,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
|||
* Default value - highest tx power value. max_power
|
||||
* is not used in mvm, and is used for backwards compatibility
|
||||
*/
|
||||
channel->max_power = DEFAULT_MAX_TX_POWER;
|
||||
channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
|
||||
is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
|
@ -336,6 +334,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
|||
3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
|
||||
7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
|
||||
|
||||
if (cfg->ht_params->ldpc)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
|
||||
|
||||
if (num_tx_ants > 1)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
|
||||
else
|
||||
|
|
|
@ -377,6 +377,7 @@ enum iwl_trans_status {
|
|||
* if unset 4k will be the RX buffer size
|
||||
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
||||
* in DWORD (as opposed to bytes)
|
||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||
* @queue_watchdog_timeout: time (in ms) after which queues
|
||||
* are considered stuck and will trigger device restart
|
||||
* @command_names: array of command names, must be 256 entries
|
||||
|
@ -392,6 +393,7 @@ struct iwl_trans_config {
|
|||
|
||||
bool rx_buf_size_8k;
|
||||
bool bc_table_dword;
|
||||
bool scd_set_active;
|
||||
unsigned int queue_watchdog_timeout;
|
||||
const char *const *command_names;
|
||||
};
|
||||
|
@ -826,12 +828,6 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
|
|||
iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_trans_txq_enable_no_scd(struct iwl_trans *trans, int queue, u16 ssn)
|
||||
{
|
||||
iwl_trans_txq_enable_cfg(trans, queue, ssn, NULL);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
|
||||
u32 txq_bm)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
|
|||
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
|
||||
iwlmvm-y += scan.o time-event.o rs.o
|
||||
iwlmvm-y += power.o coex.o coex_legacy.o
|
||||
iwlmvm-y += tt.o offloading.o
|
||||
iwlmvm-y += tt.o offloading.o tdls.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
|
||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
|
|
@ -587,8 +587,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
|||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
|
||||
u32 mode;
|
||||
|
||||
switch (mvm->bt_force_ant_mode) {
|
||||
case BT_FORCE_ANT_BT:
|
||||
mode = BT_COEX_BT;
|
||||
|
@ -758,7 +756,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
struct iwl_bt_iterator_data *data = _data;
|
||||
struct iwl_mvm *mvm = data->mvm;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
/* default smps_mode is AUTOMATIC - only used for client modes */
|
||||
enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
u32 bt_activity_grading;
|
||||
int ave_rssi;
|
||||
|
||||
|
@ -766,8 +765,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/* default smps_mode for BSS / P2P client is AUTOMATIC */
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (!mvmvif->ap_ibss_active)
|
||||
|
@ -799,7 +796,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
else if (bt_activity_grading >= BT_LOW_TRAFFIC)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
|
||||
/* relax SMPS contraints for next association */
|
||||
/* relax SMPS constraints for next association */
|
||||
if (!vif->bss_conf.assoc)
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
|
@ -1149,6 +1146,10 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
|
|||
|
||||
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* there is no other antenna, shared antenna is always available */
|
||||
if (mvm->cfg->bt_shared_single_ant)
|
||||
return true;
|
||||
|
||||
if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
|
||||
return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
|
||||
|
||||
|
|
|
@ -65,12 +65,18 @@
|
|||
#ifndef __MVM_CONSTANTS_H
|
||||
#define __MVM_CONSTANTS_H
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
|
||||
#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20
|
||||
#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8
|
||||
#define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30
|
||||
|
@ -86,5 +92,7 @@
|
|||
#define IWL_MVM_BT_COEX_SYNC2SCO 1
|
||||
#define IWL_MVM_BT_COEX_CORUNNING 1
|
||||
#define IWL_MVM_BT_COEX_MPLUT 1
|
||||
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
|
||||
#define IWL_MVM_QUOTA_THRESHOLD 8
|
||||
|
||||
#endif /* __MVM_CONSTANTS_H */
|
||||
|
|
|
@ -76,8 +76,7 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
|
|||
|
||||
switch (param) {
|
||||
case MVM_DEBUGFS_PM_KEEP_ALIVE: {
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
int dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
int dtimper = vif->bss_conf.dtim_period ?: 1;
|
||||
int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
|
||||
IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
|
||||
|
|
|
@ -288,6 +288,9 @@ static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
|
|||
{
|
||||
int temperature;
|
||||
|
||||
if (!mvm->ucode_loaded && !mvm->temperature_test)
|
||||
return -EIO;
|
||||
|
||||
if (kstrtoint(buf, 10, &temperature))
|
||||
return -EINVAL;
|
||||
/* not a legal temperature */
|
||||
|
@ -1256,6 +1259,18 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
|
|||
PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_USER);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_TX);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_TX_AGG);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_ADD_IF);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_START_AP);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_BSS_CHANGED);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_PREPARE_TX);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_TDLS);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_CHECK_CTKILL);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_PRPH_READ);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_PRPH_WRITE);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_NMI);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
|
||||
PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
|
|
|
@ -205,6 +205,10 @@ enum {
|
|||
REPLY_SF_CFG_CMD = 0xd1,
|
||||
REPLY_BEACON_FILTERING_CMD = 0xd2,
|
||||
|
||||
/* DTS measurements */
|
||||
CMD_DTS_MEASUREMENT_TRIGGER = 0xdc,
|
||||
DTS_MEASUREMENT_NOTIFICATION = 0xdd,
|
||||
|
||||
REPLY_DEBUG_CMD = 0xf0,
|
||||
DEBUG_LOG_MSG = 0xf7,
|
||||
|
||||
|
@ -550,7 +554,7 @@ enum iwl_time_event_type {
|
|||
TE_WIDI_TX_SYNC,
|
||||
|
||||
/* Channel Switch NoA */
|
||||
TE_P2P_GO_CSA_NOA,
|
||||
TE_CHANNEL_SWITCH_PERIOD,
|
||||
|
||||
TE_MAX
|
||||
}; /* MAC_EVENT_TYPE_API_E_VER_1 */
|
||||
|
@ -1601,19 +1605,49 @@ enum iwl_sf_scenario {
|
|||
|
||||
#define SF_LONG_DELAY_AGING_TIMER 1000000 /* 1 Sec */
|
||||
|
||||
#define SF_CFG_DUMMY_NOTIF_OFF BIT(16)
|
||||
|
||||
/**
|
||||
* Smart Fifo configuration command.
|
||||
* @state: smart fifo state, types listed in iwl_sf_sate.
|
||||
* @state: smart fifo state, types listed in enum %iwl_sf_sate.
|
||||
* @watermark: Minimum allowed availabe free space in RXF for transient state.
|
||||
* @long_delay_timeouts: aging and idle timer values for each scenario
|
||||
* in long delay state.
|
||||
* @full_on_timeouts: timer values for each scenario in full on state.
|
||||
*/
|
||||
struct iwl_sf_cfg_cmd {
|
||||
enum iwl_sf_state state;
|
||||
__le32 state;
|
||||
__le32 watermark[SF_TRANSIENT_STATES_NUMBER];
|
||||
__le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
|
||||
__le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES];
|
||||
} __packed; /* SF_CFG_API_S_VER_2 */
|
||||
|
||||
/* DTS measurements */
|
||||
|
||||
enum iwl_dts_measurement_flags {
|
||||
DTS_TRIGGER_CMD_FLAGS_TEMP = BIT(0),
|
||||
DTS_TRIGGER_CMD_FLAGS_VOLT = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_dts_measurement_cmd - request DTS temperature and/or voltage measurements
|
||||
*
|
||||
* @flags: indicates which measurements we want as specified in &enum
|
||||
* iwl_dts_measurement_flags
|
||||
*/
|
||||
struct iwl_dts_measurement_cmd {
|
||||
__le32 flags;
|
||||
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */
|
||||
|
||||
/**
|
||||
* iwl_dts_measurement_notif - notification received with the measurements
|
||||
*
|
||||
* @temp: the measured temperature
|
||||
* @voltage: the measured voltage
|
||||
*/
|
||||
struct iwl_dts_measurement_notif {
|
||||
__le32 temp;
|
||||
__le32 voltage;
|
||||
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S */
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
|
|
@ -454,6 +454,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
|
||||
|
||||
/* reset quota debouncing buffer - 0xff will yield invalid data */
|
||||
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
|
||||
|
||||
/* Add auxiliary station for scanning */
|
||||
ret = iwl_mvm_add_aux_sta(mvm);
|
||||
if (ret)
|
||||
|
|
|
@ -727,11 +727,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
!force_assoc_off) {
|
||||
u32 dtim_offs;
|
||||
|
||||
/* Allow beacons to pass through as long as we are not
|
||||
* associated, or we do not have dtim period information.
|
||||
*/
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
|
||||
/*
|
||||
* The DTIM count counts down, so when it is N that means N
|
||||
* more beacon intervals happen until the DTIM TBTT. Therefore
|
||||
|
@ -765,6 +760,11 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
ctxt_sta->is_assoc = cpu_to_le32(1);
|
||||
} else {
|
||||
ctxt_sta->is_assoc = cpu_to_le32(0);
|
||||
|
||||
/* Allow beacons to pass through as long as we are not
|
||||
* associated, or we do not have dtim period information.
|
||||
*/
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
}
|
||||
|
||||
ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
|
@ -1234,11 +1234,11 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
|
|||
!iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
|
||||
u32 rel_time = (c + 1) *
|
||||
csa_vif->bss_conf.beacon_int -
|
||||
IWL_MVM_CHANNEL_SWITCH_TIME;
|
||||
IWL_MVM_CHANNEL_SWITCH_TIME_GO;
|
||||
u32 apply_time = gp2 + rel_time * 1024;
|
||||
|
||||
iwl_mvm_schedule_csa_noa(mvm, csa_vif,
|
||||
IWL_MVM_CHANNEL_SWITCH_TIME -
|
||||
iwl_mvm_schedule_csa_period(mvm, csa_vif,
|
||||
IWL_MVM_CHANNEL_SWITCH_TIME_GO -
|
||||
IWL_MVM_CHANNEL_SWITCH_MARGIN,
|
||||
apply_time);
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
|
||||
!iwlwifi_mod_params.uapsd_disable) {
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
|
||||
hw->uapsd_queues = IWL_UAPSD_AC_INFO;
|
||||
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
|
||||
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
|
||||
}
|
||||
|
||||
|
@ -398,12 +398,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
else
|
||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/* TODO: enable that only for firmwares that don't crash */
|
||||
/* hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; */
|
||||
if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) {
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
|
||||
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
|
||||
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
|
||||
/* we create the 802.11 header and zero length SSID IE. */
|
||||
hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
|
||||
hw->wiphy->max_sched_scan_ie_len =
|
||||
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
|
||||
}
|
||||
|
||||
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
|
||||
NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
|
@ -668,8 +670,9 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
{
|
||||
static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
|
||||
struct iwl_fw_error_dump_file *dump_file;
|
||||
struct iwl_fw_error_dump_data *dump_data;
|
||||
struct iwl_fw_error_dump_info *dump_info;
|
||||
|
@ -761,20 +764,16 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
|||
file_len += fw_error_dump->trans_ptr->len;
|
||||
dump_file->file_len = cpu_to_le32(file_len);
|
||||
mvm->fw_error_dump = fw_error_dump;
|
||||
|
||||
/* notify the userspace about the error we had */
|
||||
kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
|
||||
|
||||
iwl_mvm_fw_error_dump(mvm);
|
||||
|
||||
/* notify the userspace about the error we had */
|
||||
kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env);
|
||||
#endif
|
||||
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
|
||||
mvm->scan_status = IWL_MVM_SCAN_NONE;
|
||||
|
@ -813,12 +812,11 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
|||
mvm->rx_ba_sessions = 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
|
||||
int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Clean up some internal and mac80211 state on restart */
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||
|
@ -835,6 +833,16 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
|
|||
iwl_mvm_d0i3_enable_tx(mvm, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = __iwl_mvm_mac_start(mvm);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -860,14 +868,9 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
|
|||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
|
||||
void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
flush_work(&mvm->d0i3_exit_work);
|
||||
flush_work(&mvm->async_handlers_wk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* disallow low power states when the FW is down */
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||
|
@ -888,6 +891,19 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
|
|||
/* the fw is stopped, the aux sta is dead: clean up driver state */
|
||||
iwl_mvm_del_aux_sta(mvm);
|
||||
|
||||
mvm->ucode_loaded = false;
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
flush_work(&mvm->d0i3_exit_work);
|
||||
flush_work(&mvm->async_handlers_wk);
|
||||
flush_work(&mvm->fw_error_dump_wk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
__iwl_mvm_mac_stop(mvm);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
/*
|
||||
|
@ -1196,14 +1212,15 @@ static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
|
|||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mcast_filter_cmd *cmd;
|
||||
struct netdev_hw_addr *addr;
|
||||
int addr_count = netdev_hw_addr_list_count(mc_list);
|
||||
bool pass_all = false;
|
||||
int addr_count;
|
||||
bool pass_all;
|
||||
int len;
|
||||
|
||||
if (addr_count > MAX_MCAST_FILTERING_ADDRESSES) {
|
||||
pass_all = true;
|
||||
addr_count = netdev_hw_addr_list_count(mc_list);
|
||||
pass_all = addr_count > MAX_MCAST_FILTERING_ADDRESSES ||
|
||||
IWL_MVM_FW_MCAST_FILTER_PASS_ALL;
|
||||
if (pass_all)
|
||||
addr_count = 0;
|
||||
}
|
||||
|
||||
len = roundup(sizeof(*cmd) + addr_count * ETH_ALEN, 4);
|
||||
cmd = kzalloc(len, GFP_ATOMIC);
|
||||
|
@ -1403,28 +1420,6 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!sta || IS_ERR(sta) || !sta->tdls)
|
||||
continue;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
|
||||
NL80211_TDLS_TEARDOWN,
|
||||
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
|
@ -1544,11 +1539,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
*/
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif,
|
||||
&mvmvif->time_event_data);
|
||||
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
|
||||
BSS_CHANGED_QOS)) {
|
||||
ret = iwl_mvm_power_update_mac(mvm);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update power mode\n");
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INFO) {
|
||||
|
@ -1556,6 +1546,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
||||
}
|
||||
|
||||
if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) {
|
||||
ret = iwl_mvm_power_update_mac(mvm);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update power mode\n");
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_TXPOWER) {
|
||||
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
|
||||
bss_conf->txpower);
|
||||
|
@ -1721,7 +1717,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
|
|||
return;
|
||||
|
||||
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
|
||||
BSS_CHANGED_BANDWIDTH) &&
|
||||
BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS) &&
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL))
|
||||
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
|
||||
|
||||
|
@ -1952,48 +1948,6 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
|
|||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!sta || IS_ERR(sta) || !sta->tdls)
|
||||
continue;
|
||||
|
||||
if (vif) {
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
if (mvmsta->vif != vif)
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
bool sta_added)
|
||||
{
|
||||
int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
|
||||
|
||||
/*
|
||||
* Disable ps when the first TDLS sta is added and re-enable it
|
||||
* when the last TDLS sta is removed
|
||||
*/
|
||||
if ((tdls_sta_cnt == 1 && sta_added) ||
|
||||
(tdls_sta_cnt == 0 && !sta_added))
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -2167,27 +2121,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
|||
iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
|
||||
|
||||
/*
|
||||
* iwl_mvm_protect_session() reads directly from the device
|
||||
* (the system time), so make sure it is available.
|
||||
*/
|
||||
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
|
||||
return;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* Protect the session to hear the TDLS setup response on the channel */
|
||||
iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_sched_scan_request *req,
|
||||
|
|
|
@ -87,11 +87,11 @@
|
|||
/* A TimeUnit is 1024 microsecond */
|
||||
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
|
||||
|
||||
/*
|
||||
* The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
|
||||
* TBTT. This value should be big enough to ensure that we switch in time.
|
||||
/* This value represents the number of TUs before CSA "beacon 0" TBTT
|
||||
* when the CSA time-event needs to be scheduled to start. It must be
|
||||
* big enough to ensure that we switch in time.
|
||||
*/
|
||||
#define IWL_MVM_CHANNEL_SWITCH_TIME 40
|
||||
#define IWL_MVM_CHANNEL_SWITCH_TIME_GO 40
|
||||
|
||||
/*
|
||||
* This value (in TUs) is used to fine tune the CSA NoA end time which should
|
||||
|
@ -180,10 +180,6 @@ enum iwl_power_scheme {
|
|||
};
|
||||
|
||||
#define IWL_CONN_MAX_LISTEN_INTERVAL 10
|
||||
#define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
|
||||
#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -274,6 +270,8 @@ enum iwl_mvm_ref_type {
|
|||
IWL_MVM_REF_TM_CMD,
|
||||
IWL_MVM_REF_EXIT_WORK,
|
||||
|
||||
/* update debugfs.c when changing this */
|
||||
|
||||
IWL_MVM_REF_COUNT,
|
||||
};
|
||||
|
||||
|
@ -649,6 +647,7 @@ struct iwl_mvm {
|
|||
|
||||
/* -1 for always, 0 for never, >0 for that many times */
|
||||
s8 restart_fw;
|
||||
struct work_struct fw_error_dump_wk;
|
||||
struct iwl_mvm_dump_ptrs *fw_error_dump;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_LEDS
|
||||
|
@ -709,6 +708,8 @@ struct iwl_mvm {
|
|||
*/
|
||||
bool temperature_test; /* Debug test temperature is enabled */
|
||||
|
||||
struct iwl_time_quota_cmd last_quota_cmd;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
u32 noa_duration;
|
||||
struct ieee80211_vif *noa_vif;
|
||||
|
@ -788,6 +789,9 @@ struct iwl_rate_info {
|
|||
u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */
|
||||
};
|
||||
|
||||
void __iwl_mvm_mac_stop(struct iwl_mvm *mvm);
|
||||
int __iwl_mvm_mac_start(struct iwl_mvm *mvm);
|
||||
|
||||
/******************
|
||||
* MVM Methods
|
||||
******************/
|
||||
|
@ -1153,7 +1157,17 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
/* TDLS */
|
||||
int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool sta_added);
|
||||
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
|
||||
#else
|
||||
static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
|
||||
#endif
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
*****************************************************************************/
|
||||
#include <linux/firmware.h>
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-eeprom-read.h"
|
||||
|
@ -349,7 +350,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
|||
/* Maximal size depends on HW family and step */
|
||||
if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
|
||||
else if ((mvm->trans->hw_rev & 0xc) == 0) /* Family 8000 A-step */
|
||||
else if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
|
||||
max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE;
|
||||
else /* Family 8000 B-step */
|
||||
max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE;
|
||||
|
|
|
@ -332,6 +332,8 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
|
|||
CMD(BCAST_FILTER_CMD),
|
||||
CMD(REPLY_SF_CFG_CMD),
|
||||
CMD(REPLY_BEACON_FILTERING_CMD),
|
||||
CMD(CMD_DTS_MEASUREMENT_TRIGGER),
|
||||
CMD(DTS_MEASUREMENT_NOTIFICATION),
|
||||
CMD(REPLY_THERMAL_MNG_BACKOFF),
|
||||
CMD(MAC_PM_POWER_TABLE),
|
||||
CMD(BT_COEX_CI),
|
||||
|
@ -364,6 +366,8 @@ static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_fw_error_dump_wk(struct work_struct *work);
|
||||
|
||||
static struct iwl_op_mode *
|
||||
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
|
||||
|
@ -431,6 +435,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
|
||||
INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
|
||||
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
|
||||
INIT_WORK(&mvm->fw_error_dump_wk, iwl_mvm_fw_error_dump_wk);
|
||||
|
||||
spin_lock_init(&mvm->d0i3_tx_lock);
|
||||
spin_lock_init(&mvm->refs_lock);
|
||||
|
@ -460,6 +465,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
|
||||
trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
|
||||
trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
|
||||
trans_cfg.scd_set_active = true;
|
||||
|
||||
snprintf(mvm->hw->wiphy->fw_version,
|
||||
sizeof(mvm->hw->wiphy->fw_version),
|
||||
|
@ -781,6 +787,16 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
|
|||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(work, struct iwl_mvm, fw_error_dump_wk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_fw_error_dump(mvm);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
||||
{
|
||||
iwl_abort_notification_waits(&mvm->notif_wait);
|
||||
|
@ -846,6 +862,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
|||
if (fw_error && mvm->restart_fw > 0)
|
||||
mvm->restart_fw--;
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
} else if (fw_error) {
|
||||
schedule_work(&mvm->fw_error_dump_wk);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -286,13 +286,28 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
bool radar_detect = false;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->chanctx_conf);
|
||||
WARN_ON(!chanctx_conf);
|
||||
if (chanctx_conf) {
|
||||
chan = chanctx_conf->def.chan;
|
||||
radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return radar_detect;
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_power_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_channel *chan;
|
||||
int dtimper, dtimper_msec;
|
||||
int keep_alive;
|
||||
bool radar_detect = false;
|
||||
|
@ -301,7 +316,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|||
|
||||
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
dtimper = vif->bss_conf.dtim_period;
|
||||
|
||||
/*
|
||||
* Regardless of power management state the driver must set
|
||||
|
@ -321,7 +336,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
|
||||
!mvmvif->pm_enabled)
|
||||
!mvmvif->pm_enabled || iwl_mvm_tdls_sta_count(mvm, vif))
|
||||
return;
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
||||
|
@ -334,14 +349,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
/* Check if radar detection is required on current channel */
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->chanctx_conf);
|
||||
WARN_ON(!chanctx_conf);
|
||||
if (chanctx_conf) {
|
||||
chan = chanctx_conf->def.chan;
|
||||
radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
radar_detect = iwl_mvm_power_is_radar(vif);
|
||||
|
||||
/* Check skip over DTIM conditions */
|
||||
if (!radar_detect && (dtimper <= 10) &&
|
||||
|
@ -502,8 +510,6 @@ struct iwl_power_vifs {
|
|||
bool bss_active;
|
||||
bool ap_active;
|
||||
bool monitor_active;
|
||||
bool bss_tdls;
|
||||
bool p2p_tdls;
|
||||
};
|
||||
|
||||
static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
|
||||
|
@ -558,8 +564,6 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
|||
/* only a single MAC of the same type */
|
||||
WARN_ON(power_iterator->p2p_vif);
|
||||
power_iterator->p2p_vif = vif;
|
||||
power_iterator->p2p_tdls =
|
||||
!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->p2p_active = true;
|
||||
|
@ -569,8 +573,6 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
|||
/* only a single MAC of the same type */
|
||||
WARN_ON(power_iterator->bss_vif);
|
||||
power_iterator->bss_vif = vif;
|
||||
power_iterator->bss_tdls =
|
||||
!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->bss_active = true;
|
||||
|
@ -613,15 +615,13 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
|
|||
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
|
||||
|
||||
/* enable PM on bss if bss stand alone */
|
||||
if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active &&
|
||||
!vifs->bss_tdls) {
|
||||
if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
|
||||
bss_mvmvif->pm_enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable PM on p2p if p2p stand alone */
|
||||
if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active &&
|
||||
!vifs->p2p_tdls) {
|
||||
if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
|
||||
p2p_mvmvif->pm_enabled = true;
|
||||
return;
|
||||
|
@ -962,17 +962,22 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
|
|||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
if (enable) {
|
||||
/* configure skip over dtim up to 300 msec */
|
||||
int dtimper = mvm->hw->conf.ps_dtim_period ?: 1;
|
||||
int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
/* configure skip over dtim up to 306TU - 314 msec */
|
||||
int dtimper = vif->bss_conf.dtim_period ?: 1;
|
||||
int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
|
||||
bool radar_detect = iwl_mvm_power_is_radar(vif);
|
||||
|
||||
if (WARN_ON(!dtimper_msec))
|
||||
if (WARN_ON(!dtimper_tu))
|
||||
return 0;
|
||||
|
||||
cmd.skip_dtim_periods = 300 / dtimper_msec;
|
||||
/* Check skip over DTIM conditions */
|
||||
/* TODO: check that multicast wake lock is off */
|
||||
if (!radar_detect && (dtimper < 10)) {
|
||||
cmd.skip_dtim_periods = 306 / dtimper_tu;
|
||||
if (cmd.skip_dtim_periods)
|
||||
cmd.flags |=
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
cmd.flags |= cpu_to_le16(
|
||||
POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
}
|
||||
}
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
|
|
@ -175,12 +175,14 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
|
|||
struct ieee80211_vif *disabled_vif)
|
||||
{
|
||||
struct iwl_time_quota_cmd cmd = {};
|
||||
int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
|
||||
int i, idx, err, num_active_macs, quota, quota_rem, n_non_lowlat;
|
||||
struct iwl_mvm_quota_iterator_data data = {
|
||||
.n_interfaces = {},
|
||||
.colors = { -1, -1, -1, -1 },
|
||||
.disabled_vif = disabled_vif,
|
||||
};
|
||||
struct iwl_time_quota_cmd *last = &mvm->last_quota_cmd;
|
||||
bool send = false;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
|
@ -293,15 +295,33 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
|
|||
|
||||
/* check that we have non-zero quota for all valid bindings */
|
||||
for (i = 0; i < MAX_BINDINGS; i++) {
|
||||
if (cmd.quotas[i].id_and_color != last->quotas[i].id_and_color)
|
||||
send = true;
|
||||
if (cmd.quotas[i].max_duration != last->quotas[i].max_duration)
|
||||
send = true;
|
||||
if (abs((int)le32_to_cpu(cmd.quotas[i].quota) -
|
||||
(int)le32_to_cpu(last->quotas[i].quota))
|
||||
> IWL_MVM_QUOTA_THRESHOLD)
|
||||
send = true;
|
||||
if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
|
||||
continue;
|
||||
WARN_ONCE(cmd.quotas[i].quota == 0,
|
||||
"zero quota on binding %d\n", i);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
|
||||
return ret;
|
||||
if (!send) {
|
||||
/* don't send a practically unchanged command, the firmware has
|
||||
* to re-initialize a lot of state and that can have an adverse
|
||||
* impact on it
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
|
||||
|
||||
if (err)
|
||||
IWL_ERR(mvm, "Failed to send quota: %d\n", err);
|
||||
else
|
||||
mvm->last_quota_cmd = cmd;
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -505,10 +505,10 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
|
|||
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
|
||||
const char *prefix)
|
||||
{
|
||||
IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d\n",
|
||||
IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n",
|
||||
prefix, rs_pretty_lq_type(rate->type),
|
||||
rate->index, rs_pretty_ant(rate->ant),
|
||||
rate->bw, rate->sgi);
|
||||
rate->bw, rate->sgi, rate->ldpc);
|
||||
}
|
||||
|
||||
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
|
||||
|
@ -672,8 +672,10 @@ static int rs_collect_tx_data(struct iwl_lq_sta *lq_sta,
|
|||
return -EINVAL;
|
||||
|
||||
if (tbl->column != RS_COLUMN_INVALID) {
|
||||
lq_sta->tx_stats[tbl->column][scale_index].total += attempts;
|
||||
lq_sta->tx_stats[tbl->column][scale_index].success += successes;
|
||||
struct lq_sta_pers *pers = &lq_sta->pers;
|
||||
|
||||
pers->tx_stats[tbl->column][scale_index].total += attempts;
|
||||
pers->tx_stats[tbl->column][scale_index].success += successes;
|
||||
}
|
||||
|
||||
/* Select window for current tx bit rate */
|
||||
|
@ -742,6 +744,8 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
|
|||
ucode_rate |= rate->bw;
|
||||
if (rate->sgi)
|
||||
ucode_rate |= RATE_MCS_SGI_MSK;
|
||||
if (rate->ldpc)
|
||||
ucode_rate |= RATE_MCS_LDPC_MSK;
|
||||
|
||||
return ucode_rate;
|
||||
}
|
||||
|
@ -779,6 +783,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
/* HT or VHT */
|
||||
if (ucode_rate & RATE_MCS_SGI_MSK)
|
||||
rate->sgi = true;
|
||||
if (ucode_rate & RATE_MCS_LDPC_MSK)
|
||||
rate->ldpc = true;
|
||||
|
||||
rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
|
||||
|
||||
|
@ -965,13 +971,13 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
|
|||
rate->index > IWL_RATE_MCS_9_INDEX);
|
||||
|
||||
rate->index = rs_ht_to_legacy[rate->index];
|
||||
rate->ldpc = false;
|
||||
} else {
|
||||
/* Downgrade to SISO with same MCS if in MIMO */
|
||||
rate->type = is_vht_mimo2(rate) ?
|
||||
LQ_VHT_SISO : LQ_HT_SISO;
|
||||
}
|
||||
|
||||
|
||||
if (num_of_ant(rate->ant) > 1)
|
||||
rate->ant = first_antenna(mvm->fw->valid_tx_ant);
|
||||
|
||||
|
@ -1621,6 +1627,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
rate->bw = rs_bw_from_sta_bw(sta);
|
||||
rate->ldpc = lq_sta->ldpc;
|
||||
search_tbl->column = col_id;
|
||||
rs_set_expected_tpt_table(lq_sta, search_tbl);
|
||||
|
||||
|
@ -2031,18 +2038,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
|||
return;
|
||||
}
|
||||
|
||||
/* force user max rate if set by user */
|
||||
if ((lq_sta->max_rate_idx != -1) &&
|
||||
(lq_sta->max_rate_idx < index)) {
|
||||
index = lq_sta->max_rate_idx;
|
||||
update_lq = 1;
|
||||
window = &(tbl->win[index]);
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Forcing user max rate %d\n",
|
||||
index);
|
||||
goto lq_update;
|
||||
}
|
||||
|
||||
/* TODO: handle rate_idx_mask and rate_idx_mcs_mask */
|
||||
window = &(tbl->win[index]);
|
||||
|
||||
/*
|
||||
|
@ -2130,10 +2126,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
|||
low = high_low & 0xff;
|
||||
high = (high_low >> 8) & 0xff;
|
||||
|
||||
/* If user set max rate, dont allow higher than user constrain */
|
||||
if ((lq_sta->max_rate_idx != -1) &&
|
||||
(lq_sta->max_rate_idx < high))
|
||||
high = IWL_RATE_INVALID;
|
||||
/* TODO: handle rate_idx_mask and rate_idx_mcs_mask */
|
||||
|
||||
sr = window->success_ratio;
|
||||
|
||||
|
@ -2342,6 +2335,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
|
|||
rate->index = i;
|
||||
rate->ant = first_antenna(valid_tx_ant);
|
||||
rate->sgi = false;
|
||||
rate->ldpc = false;
|
||||
rate->bw = RATE_MCS_CHAN_WIDTH_20;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
rate->type = LQ_LEGACY_A;
|
||||
|
@ -2364,23 +2358,13 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
|
|||
struct ieee80211_tx_rate_control *txrc)
|
||||
{
|
||||
struct sk_buff *skb = txrc->skb;
|
||||
struct ieee80211_supported_band *sband = txrc->sband;
|
||||
struct iwl_op_mode *op_mode __maybe_unused =
|
||||
(struct iwl_op_mode *)mvm_r;
|
||||
struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_lq_sta *lq_sta = mvm_sta;
|
||||
|
||||
/* Get max rate if user set max rate */
|
||||
if (lq_sta) {
|
||||
lq_sta->max_rate_idx = txrc->max_rate_idx;
|
||||
if ((sband->band == IEEE80211_BAND_5GHZ) &&
|
||||
(lq_sta->max_rate_idx != -1))
|
||||
lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
|
||||
if ((lq_sta->max_rate_idx < 0) ||
|
||||
(lq_sta->max_rate_idx >= IWL_RATE_COUNT))
|
||||
lq_sta->max_rate_idx = -1;
|
||||
}
|
||||
/* TODO: handle rate_idx_mask and rate_idx_mcs_mask */
|
||||
|
||||
/* Treat uninitialized rate scaling data same as non-existing. */
|
||||
if (lq_sta && !lq_sta->pers.drv) {
|
||||
|
@ -2581,7 +2565,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
* previous packets? Need to have IEEE 802.1X auth succeed immediately
|
||||
* after assoc.. */
|
||||
|
||||
lq_sta->max_rate_idx = -1;
|
||||
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
|
||||
lq_sta->band = sband->band;
|
||||
/*
|
||||
|
@ -2610,9 +2593,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
|
||||
|
||||
lq_sta->is_vht = false;
|
||||
if (mvm->cfg->ht_params->ldpc &&
|
||||
(ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
|
||||
lq_sta->ldpc = true;
|
||||
} else {
|
||||
rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
|
||||
lq_sta->is_vht = true;
|
||||
|
||||
if (mvm->cfg->ht_params->ldpc &&
|
||||
(vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
|
||||
lq_sta->ldpc = true;
|
||||
}
|
||||
|
||||
lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
|
||||
|
@ -2622,11 +2612,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate,
|
||||
BITS_PER_LONG);
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n",
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n",
|
||||
lq_sta->active_legacy_rate,
|
||||
lq_sta->active_siso_rate,
|
||||
lq_sta->active_mimo2_rate,
|
||||
lq_sta->is_vht);
|
||||
lq_sta->is_vht, lq_sta->ldpc);
|
||||
IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
|
||||
lq_sta->max_legacy_rate_idx,
|
||||
lq_sta->max_siso_rate_idx,
|
||||
|
@ -3032,8 +3023,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
|
|||
(is_ht20(rate)) ? "20MHz" :
|
||||
(is_ht40(rate)) ? "40MHz" :
|
||||
(is_ht80(rate)) ? "80Mhz" : "BAD BW");
|
||||
desc += sprintf(buff+desc, " %s %s\n",
|
||||
desc += sprintf(buff+desc, " %s %s %s\n",
|
||||
(rate->sgi) ? "SGI" : "NGI",
|
||||
(rate->ldpc) ? "LDPC" : "BCC",
|
||||
(lq_sta->is_agg) ? "AGG on" : "");
|
||||
}
|
||||
desc += sprintf(buff+desc, "last tx rate=0x%X\n",
|
||||
|
@ -3181,7 +3173,7 @@ static ssize_t rs_sta_dbgfs_drv_tx_stats_read(struct file *file,
|
|||
"%s,", column_name[col]);
|
||||
|
||||
for (rate = 0; rate < IWL_RATE_COUNT; rate++) {
|
||||
stats = &(lq_sta->tx_stats[col][rate]);
|
||||
stats = &(lq_sta->pers.tx_stats[col][rate]);
|
||||
pos += scnprintf(pos, endpos - pos,
|
||||
"%llu/%llu,",
|
||||
stats->success,
|
||||
|
@ -3200,7 +3192,7 @@ static ssize_t rs_sta_dbgfs_drv_tx_stats_write(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_lq_sta *lq_sta = file->private_data;
|
||||
memset(lq_sta->tx_stats, 0, sizeof(lq_sta->tx_stats));
|
||||
memset(lq_sta->pers.tx_stats, 0, sizeof(lq_sta->pers.tx_stats));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -207,6 +207,7 @@ struct rs_rate {
|
|||
u8 ant;
|
||||
u32 bw;
|
||||
bool sgi;
|
||||
bool ldpc;
|
||||
};
|
||||
|
||||
|
||||
|
@ -329,10 +330,9 @@ struct iwl_lq_sta {
|
|||
*/
|
||||
u64 last_tx;
|
||||
bool is_vht;
|
||||
bool ldpc; /* LDPC Rx is supported by the STA */
|
||||
enum ieee80211_band band;
|
||||
|
||||
struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
|
||||
|
||||
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
|
||||
unsigned long active_legacy_rate;
|
||||
unsigned long active_siso_rate;
|
||||
|
@ -343,7 +343,6 @@ struct iwl_lq_sta {
|
|||
u8 max_siso_rate_idx;
|
||||
u8 max_mimo2_rate_idx;
|
||||
|
||||
s8 max_rate_idx; /* Max rate set by user */
|
||||
u8 missed_rate_counter;
|
||||
|
||||
struct iwl_lq_cmd lq;
|
||||
|
@ -361,11 +360,14 @@ struct iwl_lq_sta {
|
|||
int tpc_reduce;
|
||||
|
||||
/* persistent fields - initialized only once - keep last! */
|
||||
struct {
|
||||
struct lq_sta_pers {
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
u32 dbg_fixed_rate;
|
||||
u8 dbg_fixed_txp_reduction;
|
||||
#endif
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
|
||||
struct iwl_mvm *drv;
|
||||
} pers;
|
||||
};
|
||||
|
|
|
@ -151,13 +151,13 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
|
|||
le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
|
||||
energy_a = (val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
|
||||
IWL_RX_INFO_ENERGY_ANT_A_POS;
|
||||
energy_a = energy_a ? -energy_a : -256;
|
||||
energy_a = energy_a ? -energy_a : S8_MIN;
|
||||
energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
|
||||
IWL_RX_INFO_ENERGY_ANT_B_POS;
|
||||
energy_b = energy_b ? -energy_b : -256;
|
||||
energy_b = energy_b ? -energy_b : S8_MIN;
|
||||
energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
|
||||
IWL_RX_INFO_ENERGY_ANT_C_POS;
|
||||
energy_c = energy_c ? -energy_c : -256;
|
||||
energy_c = energy_c ? -energy_c : S8_MIN;
|
||||
max_energy = max(energy_a, energy_b);
|
||||
max_energy = max(max_energy, energy_c);
|
||||
|
||||
|
|
|
@ -160,8 +160,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid,
|
|||
static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids)
|
||||
{
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
return 30 + 3 * (n_ssids + 1);
|
||||
return 20 + 2 * (n_ssids + 1);
|
||||
return 20 + 3 * (n_ssids + 1);
|
||||
return 10 + 2 * (n_ssids + 1);
|
||||
}
|
||||
|
||||
static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band)
|
||||
|
|
|
@ -174,11 +174,15 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
|
|||
enum iwl_sf_state new_state)
|
||||
{
|
||||
struct iwl_sf_cfg_cmd sf_cmd = {
|
||||
.state = new_state,
|
||||
.state = cpu_to_le32(new_state),
|
||||
};
|
||||
struct ieee80211_sta *sta;
|
||||
int ret = 0;
|
||||
|
||||
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF &&
|
||||
mvm->cfg->disable_dummy_notification)
|
||||
sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF);
|
||||
|
||||
/*
|
||||
* If an associated AP sta changed its antenna configuration, the state
|
||||
* will remain FULL_ON but SF parameters need to be reconsidered.
|
||||
|
|
|
@ -948,8 +948,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
tid_data->ssn = 0xffff;
|
||||
tid_data->state = IWL_AGG_OFF;
|
||||
mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE;
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
|
||||
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
|
||||
|
||||
iwl_trans_txq_disable(mvm->trans, txq_id, true);
|
||||
/* fall through */
|
||||
return 0;
|
||||
case IWL_AGG_STARTING:
|
||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||
/*
|
||||
|
@ -1003,6 +1011,8 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
|
||||
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
|
||||
|
||||
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
|
||||
|
||||
iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2014 Intel Mobile Communications GmbH
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2014 Intel Mobile Communications GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "mvm.h"
|
||||
#include "time-event.h"
|
||||
|
||||
void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!sta || IS_ERR(sta) || !sta->tdls)
|
||||
continue;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
|
||||
NL80211_TDLS_TEARDOWN,
|
||||
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (!sta || IS_ERR(sta) || !sta->tdls)
|
||||
continue;
|
||||
|
||||
if (vif) {
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
if (mvmsta->vif != vif)
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
bool sta_added)
|
||||
{
|
||||
int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
|
||||
|
||||
/*
|
||||
* Disable ps when the first TDLS sta is added and re-enable it
|
||||
* when the last TDLS sta is removed
|
||||
*/
|
||||
if ((tdls_sta_cnt == 1 && sta_added) ||
|
||||
(tdls_sta_cnt == 0 && !sta_added))
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
}
|
||||
|
||||
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
|
||||
|
||||
/*
|
||||
* iwl_mvm_protect_session() reads directly from the device
|
||||
* (the system time), so make sure it is available.
|
||||
*/
|
||||
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
|
||||
return;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* Protect the session to hear the TDLS setup response on the channel */
|
||||
iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
|
||||
}
|
|
@ -700,7 +700,7 @@ void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
|
|||
iwl_mvm_roc_finished(mvm);
|
||||
}
|
||||
|
||||
int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
|
||||
int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 duration, u32 apply_time)
|
||||
{
|
||||
|
@ -711,14 +711,14 @@ int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
|
|||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (te_data->running) {
|
||||
IWL_DEBUG_TE(mvm, "CS NOA is already scheduled\n");
|
||||
IWL_DEBUG_TE(mvm, "CS period is already scheduled\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
time_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
|
||||
time_cmd.id = cpu_to_le32(TE_P2P_GO_CSA_NOA);
|
||||
time_cmd.id = cpu_to_le32(TE_CHANNEL_SWITCH_PERIOD);
|
||||
time_cmd.apply_time = cpu_to_le32(apply_time);
|
||||
time_cmd.max_frags = TE_V2_FRAG_NONE;
|
||||
time_cmd.duration = cpu_to_le32(duration);
|
||||
|
|
|
@ -219,7 +219,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
|
|||
void iwl_mvm_roc_done_wk(struct work_struct *wk);
|
||||
|
||||
/**
|
||||
* iwl_mvm_schedule_csa_noa - request NoA for channel switch
|
||||
* iwl_mvm_schedule_csa_period - request channel switch absence period
|
||||
* @mvm: the mvm component
|
||||
* @vif: the virtual interface for which the channel switch is issued
|
||||
* @duration: the duration of the NoA in TU.
|
||||
|
@ -228,7 +228,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk);
|
|||
* This function is used to schedule NoA time event and is used to perform
|
||||
* the channel switch flow.
|
||||
*/
|
||||
int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
|
||||
int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 duration, u32 apply_time);
|
||||
|
||||
|
|
|
@ -69,248 +69,7 @@
|
|||
#include "iwl-csr.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
#define OTP_DTS_DIODE_DEVIATION 96 /*in words*/
|
||||
/* VBG - Voltage Band Gap error data (temperature offset) */
|
||||
#define OTP_WP_DTS_VBG (OTP_DTS_DIODE_DEVIATION + 2)
|
||||
#define MEAS_VBG_MIN_VAL 2300
|
||||
#define MEAS_VBG_MAX_VAL 3000
|
||||
#define MEAS_VBG_DEFAULT_VAL 2700
|
||||
#define DTS_DIODE_VALID(flags) (flags & DTS_DIODE_REG_FLAGS_PASS_ONCE)
|
||||
#define MIN_TEMPERATURE 0
|
||||
#define MAX_TEMPERATURE 125
|
||||
#define TEMPERATURE_ERROR (MAX_TEMPERATURE + 1)
|
||||
#define PTAT_DIGITAL_VALUE_MIN_VALUE 0
|
||||
#define PTAT_DIGITAL_VALUE_MAX_VALUE 0xFF
|
||||
#define DTS_VREFS_NUM 5
|
||||
static inline u32 DTS_DIODE_GET_VREFS_ID(u32 flags)
|
||||
{
|
||||
return (flags & DTS_DIODE_REG_FLAGS_VREFS_ID) >>
|
||||
DTS_DIODE_REG_FLAGS_VREFS_ID_POS;
|
||||
}
|
||||
|
||||
#define CALC_VREFS_MIN_DIFF 43
|
||||
#define CALC_VREFS_MAX_DIFF 51
|
||||
#define CALC_LUT_SIZE (1 + CALC_VREFS_MAX_DIFF - CALC_VREFS_MIN_DIFF)
|
||||
#define CALC_LUT_INDEX_OFFSET CALC_VREFS_MIN_DIFF
|
||||
#define CALC_TEMPERATURE_RESULT_SHIFT_OFFSET 23
|
||||
|
||||
/*
|
||||
* @digital_value: The diode's digital-value sampled (temperature/voltage)
|
||||
* @vref_low: The lower voltage-reference (the vref just below the diode's
|
||||
* sampled digital-value)
|
||||
* @vref_high: The higher voltage-reference (the vref just above the diode's
|
||||
* sampled digital-value)
|
||||
* @flags: bits[1:0]: The ID of the Vrefs pair (lowVref,highVref)
|
||||
* bits[6:2]: Reserved.
|
||||
* bits[7:7]: Indicates completion of at least 1 successful sample
|
||||
* since last DTS reset.
|
||||
*/
|
||||
struct iwl_mvm_dts_diode_bits {
|
||||
u8 digital_value;
|
||||
u8 vref_low;
|
||||
u8 vref_high;
|
||||
u8 flags;
|
||||
} __packed;
|
||||
|
||||
union dts_diode_results {
|
||||
u32 reg_value;
|
||||
struct iwl_mvm_dts_diode_bits bits;
|
||||
} __packed;
|
||||
|
||||
static s16 iwl_mvm_dts_get_volt_band_gap(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_nvm_section calib_sec;
|
||||
const __le16 *calib;
|
||||
u16 vbg;
|
||||
|
||||
/* TODO: move parsing to NVM code */
|
||||
calib_sec = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION];
|
||||
calib = (__le16 *)calib_sec.data;
|
||||
|
||||
vbg = le16_to_cpu(calib[OTP_WP_DTS_VBG]);
|
||||
|
||||
if (vbg < MEAS_VBG_MIN_VAL || vbg > MEAS_VBG_MAX_VAL)
|
||||
vbg = MEAS_VBG_DEFAULT_VAL;
|
||||
|
||||
return vbg;
|
||||
}
|
||||
|
||||
static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
|
||||
{
|
||||
const u8 *calib;
|
||||
u8 ptat, pa1, pa2, median;
|
||||
|
||||
/* TODO: move parsing to NVM code */
|
||||
calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
|
||||
ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
|
||||
pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
|
||||
pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
|
||||
|
||||
/* get the median: */
|
||||
if (ptat > pa1) {
|
||||
if (ptat > pa2)
|
||||
median = (pa1 > pa2) ? pa1 : pa2;
|
||||
else
|
||||
median = ptat;
|
||||
} else {
|
||||
if (pa1 > pa2)
|
||||
median = (ptat > pa2) ? ptat : pa2;
|
||||
else
|
||||
median = pa1;
|
||||
}
|
||||
|
||||
return ptat - median;
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_dts_calibrate_ptat_deviation(struct iwl_mvm *mvm, u8 value)
|
||||
{
|
||||
/* Calibrate the PTAT digital value, based on PTAT deviation data: */
|
||||
s16 new_val = value - iwl_mvm_dts_get_ptat_deviation_offset(mvm);
|
||||
|
||||
if (new_val > PTAT_DIGITAL_VALUE_MAX_VALUE)
|
||||
new_val = PTAT_DIGITAL_VALUE_MAX_VALUE;
|
||||
else if (new_val < PTAT_DIGITAL_VALUE_MIN_VALUE)
|
||||
new_val = PTAT_DIGITAL_VALUE_MIN_VALUE;
|
||||
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static bool dts_get_adjacent_vrefs(struct iwl_mvm *mvm,
|
||||
union dts_diode_results *avg_ptat)
|
||||
{
|
||||
u8 vrefs_results[DTS_VREFS_NUM];
|
||||
u8 low_vref_index = 0, flags;
|
||||
u32 reg;
|
||||
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_VREF_AVG);
|
||||
memcpy(vrefs_results, ®, sizeof(reg));
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_VREF5_AVG);
|
||||
vrefs_results[4] = reg & 0xff;
|
||||
|
||||
if (avg_ptat->bits.digital_value < vrefs_results[0] ||
|
||||
avg_ptat->bits.digital_value > vrefs_results[4])
|
||||
return false;
|
||||
|
||||
if (avg_ptat->bits.digital_value > vrefs_results[3])
|
||||
low_vref_index = 3;
|
||||
else if (avg_ptat->bits.digital_value > vrefs_results[2])
|
||||
low_vref_index = 2;
|
||||
else if (avg_ptat->bits.digital_value > vrefs_results[1])
|
||||
low_vref_index = 1;
|
||||
|
||||
avg_ptat->bits.vref_low = vrefs_results[low_vref_index];
|
||||
avg_ptat->bits.vref_high = vrefs_results[low_vref_index + 1];
|
||||
flags = avg_ptat->bits.flags;
|
||||
avg_ptat->bits.flags =
|
||||
(flags & ~DTS_DIODE_REG_FLAGS_VREFS_ID) |
|
||||
(low_vref_index & DTS_DIODE_REG_FLAGS_VREFS_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* return true it the results are valid, and false otherwise.
|
||||
*/
|
||||
static bool dts_read_ptat_avg_results(struct iwl_mvm *mvm,
|
||||
union dts_diode_results *avg_ptat)
|
||||
{
|
||||
u32 reg;
|
||||
u8 tmp;
|
||||
|
||||
/* fill the diode value and pass_once with avg-reg results */
|
||||
reg = iwl_read_prph(mvm->trans, DTSC_PTAT_AVG);
|
||||
reg &= DTS_DIODE_REG_DIG_VAL | DTS_DIODE_REG_PASS_ONCE;
|
||||
avg_ptat->reg_value = reg;
|
||||
|
||||
/* calibrate the PTAT digital value */
|
||||
tmp = avg_ptat->bits.digital_value;
|
||||
tmp = iwl_mvm_dts_calibrate_ptat_deviation(mvm, tmp);
|
||||
avg_ptat->bits.digital_value = tmp;
|
||||
|
||||
/*
|
||||
* fill vrefs fields, based on the avgVrefs results
|
||||
* and the diode value
|
||||
*/
|
||||
return dts_get_adjacent_vrefs(mvm, avg_ptat) &&
|
||||
DTS_DIODE_VALID(avg_ptat->bits.flags);
|
||||
}
|
||||
|
||||
static s32 calculate_nic_temperature(union dts_diode_results avg_ptat,
|
||||
u16 volt_band_gap)
|
||||
{
|
||||
u32 tmp_result;
|
||||
u8 vrefs_diff;
|
||||
/*
|
||||
* For temperature calculation (at the end, shift right by 23)
|
||||
* LUT[(D2-D1)] = ROUND{ 2^23 / ((D2-D1)*9*10) }
|
||||
* (D2-D1) == 43 44 45 46 47 48 49 50 51
|
||||
*/
|
||||
static const u16 calc_lut[CALC_LUT_SIZE] = {
|
||||
2168, 2118, 2071, 2026, 1983, 1942, 1902, 1864, 1828,
|
||||
};
|
||||
|
||||
/*
|
||||
* The diff between the high and low voltage-references is assumed
|
||||
* to be strictly be in range of [60,68]
|
||||
*/
|
||||
vrefs_diff = avg_ptat.bits.vref_high - avg_ptat.bits.vref_low;
|
||||
|
||||
if (vrefs_diff < CALC_VREFS_MIN_DIFF ||
|
||||
vrefs_diff > CALC_VREFS_MAX_DIFF)
|
||||
return TEMPERATURE_ERROR;
|
||||
|
||||
/* calculate the result: */
|
||||
tmp_result =
|
||||
vrefs_diff * (DTS_DIODE_GET_VREFS_ID(avg_ptat.bits.flags) + 9);
|
||||
tmp_result += avg_ptat.bits.digital_value;
|
||||
tmp_result -= avg_ptat.bits.vref_high;
|
||||
|
||||
/* multiply by the LUT value (based on the diff) */
|
||||
tmp_result *= calc_lut[vrefs_diff - CALC_LUT_INDEX_OFFSET];
|
||||
|
||||
/*
|
||||
* Get the BandGap (the voltage refereces source) error data
|
||||
* (temperature offset)
|
||||
*/
|
||||
tmp_result *= volt_band_gap;
|
||||
|
||||
/*
|
||||
* here, tmp_result value can be up to 32-bits. We want to right-shift
|
||||
* it *without* sign-extend.
|
||||
*/
|
||||
tmp_result = tmp_result >> CALC_TEMPERATURE_RESULT_SHIFT_OFFSET;
|
||||
|
||||
/*
|
||||
* at this point, tmp_result should be in the range:
|
||||
* 200 <= tmp_result <= 365
|
||||
*/
|
||||
return (s16)tmp_result - 240;
|
||||
}
|
||||
|
||||
static s32 check_nic_temperature(struct iwl_mvm *mvm)
|
||||
{
|
||||
u16 volt_band_gap;
|
||||
union dts_diode_results avg_ptat;
|
||||
|
||||
volt_band_gap = iwl_mvm_dts_get_volt_band_gap(mvm);
|
||||
|
||||
/* disable DTS */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0);
|
||||
|
||||
/* SV initialization */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 1);
|
||||
iwl_write_prph(mvm->trans, DTSC_CFG_MODE,
|
||||
DTSC_CFG_MODE_PERIODIC);
|
||||
|
||||
/* wait for results */
|
||||
msleep(100);
|
||||
if (!dts_read_ptat_avg_results(mvm, &avg_ptat))
|
||||
return TEMPERATURE_ERROR;
|
||||
|
||||
/* disable DTS */
|
||||
iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0);
|
||||
|
||||
return calculate_nic_temperature(avg_ptat, volt_band_gap);
|
||||
}
|
||||
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
|
||||
|
||||
static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
@ -340,6 +99,71 @@ static void iwl_mvm_exit_ctkill(struct iwl_mvm *mvm)
|
|||
iwl_mvm_set_hw_ctkill_state(mvm, false);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_temp_notif(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(notif_wait, struct iwl_mvm, notif_wait);
|
||||
int *temp = data;
|
||||
struct iwl_dts_measurement_notif *notif;
|
||||
int len = iwl_rx_packet_payload_len(pkt);
|
||||
|
||||
if (WARN_ON_ONCE(len != sizeof(*notif))) {
|
||||
IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
notif = (void *)pkt->data;
|
||||
|
||||
*temp = le32_to_cpu(notif->temp);
|
||||
|
||||
/* shouldn't be negative, but since it's s32, make sure it isn't */
|
||||
if (WARN_ON_ONCE(*temp < 0))
|
||||
*temp = 0;
|
||||
|
||||
IWL_DEBUG_TEMP(mvm, "DTS_MEASUREMENT_NOTIFICATION - %d\n", *temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_dts_measurement_cmd cmd = {
|
||||
.flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP),
|
||||
};
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, CMD_DTS_MEASUREMENT_TRIGGER, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_temp(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_notification_wait wait_temp_notif;
|
||||
static const u8 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION };
|
||||
int ret, temp;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif,
|
||||
temp_notif, ARRAY_SIZE(temp_notif),
|
||||
iwl_mvm_temp_notif, &temp);
|
||||
|
||||
ret = iwl_mvm_get_temp_cmd(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to get the temperature (err=%d)\n", ret);
|
||||
iwl_remove_notification(&mvm->notif_wait, &wait_temp_notif);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_temp_notif,
|
||||
IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Getting the temperature timed out\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void check_exit_ctkill(struct work_struct *work)
|
||||
{
|
||||
struct iwl_mvm_tt_mgmt *tt;
|
||||
|
@ -352,28 +176,36 @@ static void check_exit_ctkill(struct work_struct *work)
|
|||
|
||||
duration = tt->params->ct_kill_duration;
|
||||
|
||||
/* make sure the device is available for direct read/writes */
|
||||
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (__iwl_mvm_mac_start(mvm))
|
||||
goto reschedule;
|
||||
|
||||
iwl_trans_start_hw(mvm->trans);
|
||||
temp = check_nic_temperature(mvm);
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
/* make sure the device is available for direct read/writes */
|
||||
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL)) {
|
||||
__iwl_mvm_mac_stop(mvm);
|
||||
goto reschedule;
|
||||
}
|
||||
|
||||
temp = iwl_mvm_get_temp(mvm);
|
||||
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
|
||||
|
||||
if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
|
||||
IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
|
||||
__iwl_mvm_mac_stop(mvm);
|
||||
|
||||
if (temp < 0)
|
||||
goto reschedule;
|
||||
}
|
||||
|
||||
IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp);
|
||||
|
||||
if (temp <= tt->params->ct_kill_exit) {
|
||||
mutex_unlock(&mvm->mutex);
|
||||
iwl_mvm_exit_ctkill(mvm);
|
||||
return;
|
||||
}
|
||||
|
||||
reschedule:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit,
|
||||
round_jiffies(duration * HZ));
|
||||
}
|
||||
|
|
|
@ -170,10 +170,14 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
|
|||
|
||||
/*
|
||||
* for data packets, rate info comes from the table inside the fw. This
|
||||
* table is controlled by LINK_QUALITY commands
|
||||
* table is controlled by LINK_QUALITY commands. Exclude ctrl port
|
||||
* frames like EAPOLs which should be treated as mgmt frames. This
|
||||
* avoids them being sent initially in high rates which increases the
|
||||
* chances for completion of the 4-Way handshake.
|
||||
*/
|
||||
|
||||
if (ieee80211_is_data(fc) && sta) {
|
||||
if (ieee80211_is_data(fc) && sta &&
|
||||
!(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
|
||||
tx_cmd->initial_rate_index = 0;
|
||||
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
|
||||
return;
|
||||
|
@ -209,7 +213,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
|
|||
|
||||
if (info->band == IEEE80211_BAND_2GHZ &&
|
||||
!iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
|
||||
rate_flags = BIT(ANT_A) << RATE_MCS_ANT_POS;
|
||||
rate_flags = BIT(mvm->cfg->non_shared_ant) << RATE_MCS_ANT_POS;
|
||||
else
|
||||
rate_flags =
|
||||
BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
|
||||
|
|
|
@ -354,11 +354,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B4, 0x8370, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B4, 0x8272, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)},
|
||||
|
||||
/* 3165 Series */
|
||||
{IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x3165, 0x4210, iwl3165_2ac_cfg)},
|
||||
|
||||
/* 7265 Series */
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
|
||||
|
@ -380,6 +386,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x900A, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
|
||||
|
@ -398,6 +405,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
|
||||
/* 8000 Series */
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)},
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
|
|
|
@ -257,6 +257,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
|
|||
* @cmd_queue - command queue number
|
||||
* @rx_buf_size_8k: 8 kB RX buffer size
|
||||
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
|
||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||
* @rx_page_order: page order for receive buffer size
|
||||
* @wd_timeout: queue watchdog timeout (jiffies)
|
||||
* @reg_lock: protect hw register access
|
||||
|
@ -306,6 +307,7 @@ struct iwl_trans_pcie {
|
|||
|
||||
bool rx_buf_size_8k;
|
||||
bool bc_table_dword;
|
||||
bool scd_set_active;
|
||||
u32 rx_page_order;
|
||||
|
||||
const char *const *command_names;
|
||||
|
|
|
@ -640,7 +640,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
|||
err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
|
||||
|
||||
if (reclaim) {
|
||||
kfree(txq->entries[cmd_index].free_buf);
|
||||
kzfree(txq->entries[cmd_index].free_buf);
|
||||
txq->entries[cmd_index].free_buf = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1171,6 +1171,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
|||
|
||||
trans_pcie->command_names = trans_cfg->command_names;
|
||||
trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
|
||||
trans_pcie->scd_set_active = trans_cfg->scd_set_active;
|
||||
|
||||
/* Initialize NAPI here - it should be before registering to mac80211
|
||||
* in the opmode but after the HW struct is allocated.
|
||||
|
@ -2189,7 +2190,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
*/
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
trans->hw_rev = (trans->hw_rev & 0xfff0) |
|
||||
((trans->hw_rev << 2) & 0xc);
|
||||
(CSR_HW_REV_STEP(trans->hw_rev << 2));
|
||||
|
||||
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
|
||||
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
|
||||
|
|
|
@ -620,8 +620,8 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
|
|||
/* De-alloc array of command/tx buffers */
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < txq->q.n_window; i++) {
|
||||
kfree(txq->entries[i].cmd);
|
||||
kfree(txq->entries[i].free_buf);
|
||||
kzfree(txq->entries[i].cmd);
|
||||
kzfree(txq->entries[i].free_buf);
|
||||
}
|
||||
|
||||
/* De-alloc circular buffer of TFDs */
|
||||
|
@ -1080,7 +1080,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
|
|||
fifo = cfg->fifo;
|
||||
|
||||
/* Disable the scheduler prior configuring the cmd queue */
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
if (txq_id == trans_pcie->cmd_queue &&
|
||||
trans_pcie->scd_set_active)
|
||||
iwl_scd_enable_set_active(trans, 0);
|
||||
|
||||
/* Stop this Tx queue before configuring it */
|
||||
|
@ -1142,7 +1143,8 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
|
|||
SCD_QUEUE_STTS_REG_MSK);
|
||||
|
||||
/* enable the scheduler for this queue (only) */
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
if (txq_id == trans_pcie->cmd_queue &&
|
||||
trans_pcie->scd_set_active)
|
||||
iwl_scd_enable_set_active(trans, BIT(txq_id));
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1409,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
|||
|
||||
out_meta->flags = cmd->flags;
|
||||
if (WARN_ON_ONCE(txq->entries[idx].free_buf))
|
||||
kfree(txq->entries[idx].free_buf);
|
||||
kzfree(txq->entries[idx].free_buf);
|
||||
txq->entries[idx].free_buf = dup_buf;
|
||||
|
||||
trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
|
||||
|
|
Loading…
Reference in New Issue