Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
204162296e
@ -4362,7 +4362,7 @@ F: drivers/net/wireless/iwlegacy/
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Johannes Berg <johannes.berg@intel.com>
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
|
@ -127,20 +127,3 @@ config IWLWIFI_DEVICE_TRACING
|
||||
If unsure, say Y so we can help you better when problems
|
||||
occur.
|
||||
endmenu
|
||||
|
||||
config IWLWIFI_P2P
|
||||
def_bool y
|
||||
bool "iwlwifi experimental P2P support"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This option enables experimental P2P support for some devices
|
||||
based on microcode support. Since P2P support is still under
|
||||
development, this option may even enable it for some devices
|
||||
now that turn out to not support it in the future due to
|
||||
microcode restrictions.
|
||||
|
||||
To determine if your microcode supports the experimental P2P
|
||||
offered by this option, check if the driver advertises AP
|
||||
support when it is loaded.
|
||||
|
||||
Say Y only if you want to experiment with P2P.
|
||||
|
@ -106,7 +106,6 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
|
||||
#define STATUS_CHANNEL_SWITCH_PENDING 11
|
||||
#define STATUS_SCAN_COMPLETE 12
|
||||
#define STATUS_POWER_PMI 13
|
||||
#define STATUS_SCAN_ROC_EXPIRED 14
|
||||
|
||||
struct iwl_ucode_capabilities;
|
||||
|
||||
@ -250,7 +249,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
/* scan */
|
||||
void iwlagn_post_scan(struct iwl_priv *priv);
|
||||
void iwlagn_disable_roc(struct iwl_priv *priv);
|
||||
int iwl_force_rf_reset(struct iwl_priv *priv, bool external);
|
||||
void iwl_init_scan_params(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel(struct iwl_priv *priv);
|
||||
@ -265,10 +263,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
enum iwl_scan_type scan_type,
|
||||
enum ieee80211_band band);
|
||||
|
||||
void iwl_scan_roc_expired(struct iwl_priv *priv);
|
||||
void iwl_scan_offchannel_skb(struct iwl_priv *priv);
|
||||
void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
|
||||
|
||||
/* For faster active scanning, scan will move to the next channel if fewer than
|
||||
* PLCP_QUIET_THRESH packets are heard on this channel within
|
||||
* ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
|
||||
|
@ -69,19 +69,7 @@
|
||||
} while (0)
|
||||
|
||||
/* file operation */
|
||||
#define DEBUGFS_READ_FUNC(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_WRITE_FUNC(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
|
||||
#define DEBUGFS_READ_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
.open = simple_open, \
|
||||
@ -89,7 +77,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
};
|
||||
|
||||
#define DEBUGFS_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.open = simple_open, \
|
||||
@ -98,8 +85,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
|
||||
|
||||
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
|
@ -540,7 +540,6 @@ struct iwl_rxon_context {
|
||||
enum iwl_scan_type {
|
||||
IWL_SCAN_NORMAL,
|
||||
IWL_SCAN_RADIO_RESET,
|
||||
IWL_SCAN_ROC,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -825,12 +824,6 @@ struct iwl_priv {
|
||||
struct reply_tx_error_statistics reply_tx_stats;
|
||||
struct reply_agg_tx_error_statistics reply_agg_tx_stats;
|
||||
|
||||
/* remain-on-channel offload support */
|
||||
struct ieee80211_channel *hw_roc_channel;
|
||||
struct delayed_work hw_roc_disable_work;
|
||||
int hw_roc_duration;
|
||||
bool hw_roc_setup, hw_roc_start_notified;
|
||||
|
||||
/* bt coex */
|
||||
u8 bt_enable_flag;
|
||||
u8 bt_status;
|
||||
|
@ -76,29 +76,6 @@ static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_STATION),
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION),
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination
|
||||
iwlagn_iface_combinations_dualmode[] = {
|
||||
{ .num_different_channels = 1,
|
||||
@ -114,21 +91,6 @@ iwlagn_iface_combinations_dualmode[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination
|
||||
iwlagn_iface_combinations_p2p[] = {
|
||||
{ .num_different_channels = 1,
|
||||
.max_interfaces = 2,
|
||||
.beacon_int_infra_match = true,
|
||||
.limits = iwlagn_p2p_sta_go_limits,
|
||||
.n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
|
||||
},
|
||||
{ .num_different_channels = 1,
|
||||
.max_interfaces = 2,
|
||||
.limits = iwlagn_p2p_2sta_limits,
|
||||
.n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Not a mac80211 entry point function, but it fits in with all the
|
||||
* other mac80211 functions grouped here.
|
||||
@ -186,19 +148,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
|
||||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
|
||||
if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
|
||||
hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
|
||||
hw->wiphy->n_iface_combinations =
|
||||
ARRAY_SIZE(iwlagn_iface_combinations_p2p);
|
||||
} else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
|
||||
if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
|
||||
hw->wiphy->iface_combinations =
|
||||
iwlagn_iface_combinations_dualmode;
|
||||
hw->wiphy->n_iface_combinations =
|
||||
ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
|
||||
}
|
||||
|
||||
hw->wiphy->max_remain_on_channel_duration = 500;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
WIPHY_FLAG_IBSS_RSN;
|
||||
@ -1156,126 +1112,6 @@ done:
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *channel,
|
||||
int duration,
|
||||
enum ieee80211_roc_type type)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
|
||||
int err = 0;
|
||||
|
||||
if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
/* mac80211 should not scan while ROC or ROC while scanning */
|
||||
if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
priv->hw_roc_channel = channel;
|
||||
/* convert from ms to TU */
|
||||
priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
|
||||
priv->hw_roc_start_notified = false;
|
||||
cancel_delayed_work(&priv->hw_roc_disable_work);
|
||||
|
||||
if (!ctx->is_active) {
|
||||
static const struct iwl_qos_info default_qos_data = {
|
||||
.def_qos_parm = {
|
||||
.ac[0] = {
|
||||
.cw_min = cpu_to_le16(3),
|
||||
.cw_max = cpu_to_le16(7),
|
||||
.aifsn = 2,
|
||||
.edca_txop = cpu_to_le16(1504),
|
||||
},
|
||||
.ac[1] = {
|
||||
.cw_min = cpu_to_le16(7),
|
||||
.cw_max = cpu_to_le16(15),
|
||||
.aifsn = 2,
|
||||
.edca_txop = cpu_to_le16(3008),
|
||||
},
|
||||
.ac[2] = {
|
||||
.cw_min = cpu_to_le16(15),
|
||||
.cw_max = cpu_to_le16(1023),
|
||||
.aifsn = 3,
|
||||
},
|
||||
.ac[3] = {
|
||||
.cw_min = cpu_to_le16(15),
|
||||
.cw_max = cpu_to_le16(1023),
|
||||
.aifsn = 7,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
ctx->is_active = true;
|
||||
ctx->qos_data = default_qos_data;
|
||||
ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
|
||||
memcpy(ctx->staging.node_addr,
|
||||
priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
|
||||
ETH_ALEN);
|
||||
memcpy(ctx->staging.bssid_addr,
|
||||
priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
|
||||
ETH_ALEN);
|
||||
err = iwlagn_commit_rxon(priv, ctx);
|
||||
if (err)
|
||||
goto out;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK |
|
||||
RXON_FILTER_PROMISC_MSK |
|
||||
RXON_FILTER_CTL2HOST_MSK;
|
||||
|
||||
err = iwlagn_commit_rxon(priv, ctx);
|
||||
if (err) {
|
||||
iwlagn_disable_roc(priv);
|
||||
goto out;
|
||||
}
|
||||
priv->hw_roc_setup = true;
|
||||
}
|
||||
|
||||
err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band);
|
||||
if (err)
|
||||
iwlagn_disable_roc(priv);
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
|
||||
iwlagn_disable_roc(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_rssi_event rssi_event)
|
||||
@ -1431,12 +1267,8 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
|
||||
viftype, vif->addr);
|
||||
|
||||
cancel_delayed_work_sync(&priv->hw_roc_disable_work);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
iwlagn_disable_roc(priv);
|
||||
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_WARN(priv, "Try to add interface when device not ready\n");
|
||||
err = -EINVAL;
|
||||
@ -1763,8 +1595,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.channel_switch = iwlagn_mac_channel_switch,
|
||||
.flush = iwlagn_mac_flush,
|
||||
.tx_last_beacon = iwlagn_mac_tx_last_beacon,
|
||||
.remain_on_channel = iwlagn_mac_remain_on_channel,
|
||||
.cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel,
|
||||
.rssi_callback = iwlagn_mac_rssi_callback,
|
||||
.set_tim = iwlagn_mac_set_tim,
|
||||
};
|
||||
|
@ -587,11 +587,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
||||
priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P)
|
||||
priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
|
||||
priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
|
||||
@ -854,14 +849,6 @@ void iwl_down(struct iwl_priv *priv)
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
/*
|
||||
* If active, scanning won't cancel it, so say it expired.
|
||||
* No race since we hold the mutex here and a new one
|
||||
* can't come in at this time.
|
||||
*/
|
||||
if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
|
||||
exit_pending =
|
||||
test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
@ -1002,41 +989,6 @@ static void iwl_bg_restart(struct work_struct *data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void iwlagn_disable_roc(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->hw_roc_setup)
|
||||
return;
|
||||
|
||||
ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
priv->hw_roc_channel = NULL;
|
||||
|
||||
memset(ctx->staging.node_addr, 0, ETH_ALEN);
|
||||
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
ctx->is_active = false;
|
||||
priv->hw_roc_setup = false;
|
||||
}
|
||||
|
||||
static void iwlagn_disable_roc_work(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
hw_roc_disable_work.work);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
iwlagn_disable_roc(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* driver setup and teardown
|
||||
@ -1053,8 +1005,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
|
||||
INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
|
||||
INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
|
||||
INIT_DELAYED_WORK(&priv->hw_roc_disable_work,
|
||||
iwlagn_disable_roc_work);
|
||||
|
||||
iwl_setup_scan_deferred_work(priv);
|
||||
|
||||
@ -1082,7 +1032,6 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
|
||||
cancel_work_sync(&priv->bt_full_concurrency);
|
||||
cancel_work_sync(&priv->bt_runtime_config);
|
||||
cancel_delayed_work_sync(&priv->hw_roc_disable_work);
|
||||
|
||||
del_timer_sync(&priv->statistics_periodic);
|
||||
del_timer_sync(&priv->ucode_trace);
|
||||
@ -1169,12 +1118,6 @@ static void iwl_option_config(struct iwl_priv *priv)
|
||||
#else
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_P2P
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
|
||||
#else
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||
@ -1315,10 +1258,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
|
||||
ucode_flags = fw->ucode_capa.flags;
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_P2P
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
|
||||
#endif
|
||||
|
||||
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
|
||||
trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
@ -1413,7 +1352,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
* if not PAN, then don't support P2P -- might be a uCode
|
||||
* packaging bug or due to the eeprom check above
|
||||
*/
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
|
||||
|
@ -2826,9 +2826,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
|
||||
|
||||
lq_sta->flush_timer = 0;
|
||||
lq_sta->supp_rates = sta->supp_rates[sband->band];
|
||||
for (j = 0; j < LQ_SIZE; j++)
|
||||
for (i = 0; i < IWL_RATE_COUNT; i++)
|
||||
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
|
||||
|
||||
IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n",
|
||||
sta_id);
|
||||
|
@ -564,11 +564,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
cmd.slots[0].type = 0; /* BSS */
|
||||
cmd.slots[1].type = 1; /* PAN */
|
||||
|
||||
if (priv->hw_roc_setup) {
|
||||
/* both contexts must be used for this to happen */
|
||||
slot1 = IWL_MIN_SLOT_TIME;
|
||||
slot0 = 3000;
|
||||
} else if (ctx_bss->vif && ctx_pan->vif) {
|
||||
if (ctx_bss->vif && ctx_pan->vif) {
|
||||
int bcnint = ctx_pan->beacon_int;
|
||||
int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
|
||||
|
||||
|
@ -100,9 +100,6 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
|
||||
ieee80211_scan_completed(priv->hw, aborted);
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC)
|
||||
iwl_scan_roc_expired(priv);
|
||||
|
||||
priv->scan_type = IWL_SCAN_NORMAL;
|
||||
priv->scan_vif = NULL;
|
||||
priv->scan_request = NULL;
|
||||
@ -130,9 +127,6 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
||||
goto out_settings;
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC)
|
||||
iwl_scan_roc_expired(priv);
|
||||
|
||||
if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
|
||||
int err;
|
||||
|
||||
@ -284,12 +278,6 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
le32_to_cpu(notif->tsf_low),
|
||||
notif->status, notif->beacon_timer);
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC &&
|
||||
!priv->hw_roc_start_notified) {
|
||||
ieee80211_ready_on_channel(priv->hw);
|
||||
priv->hw_roc_start_notified = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -697,8 +685,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
|
||||
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
|
||||
|
||||
if (priv->scan_type != IWL_SCAN_ROC &&
|
||||
iwl_is_any_associated(priv)) {
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
u16 interval = 0;
|
||||
u32 extra;
|
||||
u32 suspend_time = 100;
|
||||
@ -706,9 +693,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_ROC:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
interval = 0;
|
||||
break;
|
||||
@ -728,11 +712,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
scan->suspend_time = cpu_to_le32(scan_suspend_time);
|
||||
IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
|
||||
scan_suspend_time, interval);
|
||||
} else if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
scan->suspend_time = 0;
|
||||
scan->max_out_time = 0;
|
||||
scan->quiet_time = 0;
|
||||
scan->quiet_plcp_th = 0;
|
||||
}
|
||||
|
||||
switch (priv->scan_type) {
|
||||
@ -774,9 +753,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
} else
|
||||
IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
|
||||
break;
|
||||
case IWL_SCAN_ROC:
|
||||
IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
@ -898,7 +874,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
scan_cmd_size - sizeof(*scan));
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
case IWL_SCAN_ROC:
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
cmd_len = iwl_fill_probe_req(
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
@ -926,46 +901,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
is_active, n_probes,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_ROC: {
|
||||
struct iwl_scan_channel *scan_ch;
|
||||
int n_chan, i;
|
||||
u16 dwell;
|
||||
|
||||
dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
|
||||
n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
|
||||
|
||||
scan->channel_count = n_chan;
|
||||
|
||||
scan_ch = (void *)&scan->data[cmd_len];
|
||||
|
||||
for (i = 0; i < n_chan; i++) {
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
scan_ch->channel =
|
||||
cpu_to_le16(priv->hw_roc_channel->hw_value);
|
||||
|
||||
if (i == n_chan - 1)
|
||||
dwell = priv->hw_roc_duration - i * dwell;
|
||||
|
||||
scan_ch->active_dwell =
|
||||
scan_ch->passive_dwell = cpu_to_le16(dwell);
|
||||
|
||||
/* Set txpower levels to defaults */
|
||||
scan_ch->dsp_atten = 110;
|
||||
|
||||
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
|
||||
* power level:
|
||||
* scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
|
||||
*/
|
||||
if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
|
||||
|
||||
scan_ch++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
@ -1035,7 +970,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
|
||||
scan_type == IWL_SCAN_NORMAL ? "" :
|
||||
scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
|
||||
"internal short ");
|
||||
|
||||
set_bit(STATUS_SCANNING, &priv->status);
|
||||
@ -1149,40 +1083,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_scan_roc_expired(struct iwl_priv *priv)
|
||||
{
|
||||
/*
|
||||
* The status bit should be set here, to prevent a race
|
||||
* where the atomic_read returns 1, but before the execution continues
|
||||
* iwl_scan_offchannel_skb_status() checks if the status bit is set
|
||||
*/
|
||||
set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
|
||||
|
||||
if (atomic_read(&priv->num_aux_in_flight) == 0) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work,
|
||||
10 * HZ);
|
||||
|
||||
clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
|
||||
} else {
|
||||
IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n",
|
||||
atomic_read(&priv->num_aux_in_flight));
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_scan_offchannel_skb(struct iwl_priv *priv)
|
||||
{
|
||||
WARN_ON(!priv->hw_roc_start_notified);
|
||||
atomic_inc(&priv->num_aux_in_flight);
|
||||
}
|
||||
|
||||
void iwl_scan_offchannel_skb_status(struct iwl_priv *priv)
|
||||
{
|
||||
if (atomic_dec_return(&priv->num_aux_in_flight) == 0 &&
|
||||
test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n");
|
||||
iwl_scan_roc_expired(priv);
|
||||
}
|
||||
}
|
||||
|
@ -478,9 +478,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
|
||||
if (sta_priv && sta_priv->client && !is_agg)
|
||||
atomic_inc(&sta_priv->pending_frames);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
iwl_scan_offchannel_skb(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
drop_unlock_sta:
|
||||
@ -1158,7 +1155,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct sk_buff *skb;
|
||||
struct iwl_rxon_context *ctx;
|
||||
bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
|
||||
bool is_offchannel_skb;
|
||||
|
||||
tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
|
||||
IWLAGN_TX_RES_TID_POS;
|
||||
@ -1178,8 +1174,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
|
||||
__skb_queue_head_init(&skbs);
|
||||
|
||||
is_offchannel_skb = false;
|
||||
|
||||
if (tx_resp->frame_count == 1) {
|
||||
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
|
||||
next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10);
|
||||
@ -1256,8 +1250,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
if (!is_agg)
|
||||
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
|
||||
|
||||
is_offchannel_skb =
|
||||
(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
|
||||
freed++;
|
||||
}
|
||||
|
||||
@ -1271,14 +1263,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
if (!is_agg && freed != 1)
|
||||
IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
|
||||
|
||||
/*
|
||||
* An offchannel frame can be send only on the AUX queue, where
|
||||
* there is no aggregation (and reordering) so it only is single
|
||||
* skb is expected to be processed.
|
||||
*/
|
||||
if (is_offchannel_skb && freed != 1)
|
||||
IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id,
|
||||
iwl_get_tx_fail_reason(status), status);
|
||||
|
||||
@ -1298,9 +1282,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
ieee80211_tx_status_ni(priv->hw, skb);
|
||||
}
|
||||
|
||||
if (is_offchannel_skb)
|
||||
iwl_scan_offchannel_skb_status(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,7 @@ static const struct iwl_base_params iwl7000_base_params = {
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7000_ht_params = {
|
||||
@ -126,6 +127,16 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
|
||||
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
IWL_DEVICE_7000,
|
||||
.ht_params = &iwl7000_ht_params,
|
||||
.nvm_ver = IWL7260_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
|
||||
.high_temp = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl7260_2n_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless N 7260",
|
||||
.fw_name_pre = IWL7260_FW_PRE,
|
||||
|
@ -152,6 +152,7 @@ struct iwl_base_params {
|
||||
unsigned int wd_timeout;
|
||||
u32 max_event_log_size;
|
||||
const bool shadow_reg_enable;
|
||||
const bool pcie_l1_allowed;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -205,6 +206,7 @@ struct iwl_eeprom_params {
|
||||
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||
* @high_temp: Is this NIC is designated to be in high temperature.
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
@ -233,6 +235,7 @@ struct iwl_cfg {
|
||||
enum iwl_led_mode led_mode;
|
||||
const bool rx_with_siso_diversity;
|
||||
const bool internal_wimax_coex;
|
||||
bool high_temp;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -283,6 +286,7 @@ extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
#endif /* CONFIG_IWLDVM */
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
|
||||
extern const struct iwl_cfg iwl7260_2n_cfg;
|
||||
extern const struct iwl_cfg iwl7260_n_cfg;
|
||||
extern const struct iwl_cfg iwl3160_2ac_cfg;
|
||||
|
@ -74,13 +74,22 @@
|
||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
|
||||
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
|
||||
* @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
|
||||
* @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
|
||||
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
|
||||
* (rather than two) IPv6 addresses
|
||||
* @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
|
||||
*/
|
||||
enum iwl_ucode_tlv_flag {
|
||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
|
||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
|
||||
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
|
||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
|
||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
|
||||
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
|
||||
IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6),
|
||||
IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8),
|
||||
IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
|
||||
IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11),
|
||||
};
|
||||
|
||||
/* The default calibrate table size if not specified by firmware file */
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-csr.h"
|
||||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
@ -166,3 +168,68 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
|
||||
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
|
||||
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#undef IWL_CMD
|
||||
}
|
||||
|
||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf)
|
||||
{
|
||||
int i;
|
||||
static const u32 fh_tbl[] = {
|
||||
FH_RSCSR_CHNL0_STTS_WPTR_REG,
|
||||
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
|
||||
FH_RSCSR_CHNL0_WPTR,
|
||||
FH_MEM_RCSR_CHNL0_CONFIG_REG,
|
||||
FH_MEM_RSSR_SHARED_CTRL_REG,
|
||||
FH_MEM_RSSR_RX_STATUS_REG,
|
||||
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (buf) {
|
||||
int pos = 0;
|
||||
size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
|
||||
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"FH register values:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
" %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
IWL_ERR(trans, "FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
IWL_ERR(trans, " %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,4 +77,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask);
|
||||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
|
||||
/* Error handling */
|
||||
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
|
||||
|
||||
#endif
|
||||
|
@ -118,6 +118,7 @@ static const u8 iwl_nvm_channels[] = {
|
||||
#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[] = {
|
||||
@ -232,8 +233,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
|
||||
/* Initialize regulatory-based run-time data */
|
||||
|
||||
/* TODO: read the real value from the NVM */
|
||||
channel->max_power = 0;
|
||||
/*
|
||||
* 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;
|
||||
is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
|
||||
|
@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
|
||||
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
|
||||
iwlmvm-y += scan.o time-event.o rs.o
|
||||
iwlmvm-y += power.o bt-coex.o
|
||||
iwlmvm-y += power.o power_legacy.o bt-coex.o
|
||||
iwlmvm-y += led.o tt.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
@ -220,45 +220,15 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
|
||||
|
||||
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_bt_coex_cmd cmd = {
|
||||
.max_kill = 5,
|
||||
.bt3_time_t7_value = 1,
|
||||
.bt3_prio_sample_time = 2,
|
||||
.bt3_timer_t2_value = 0xc,
|
||||
struct iwl_bt_coex_cmd *bt_cmd;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = BT_CONFIG,
|
||||
.len = { sizeof(*bt_cmd), },
|
||||
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
int ret;
|
||||
|
||||
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
|
||||
BT_COEX_NW : BT_COEX_DISABLE;
|
||||
cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
|
||||
|
||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
|
||||
BT_VALID_BT_PRIO_BOOST |
|
||||
BT_VALID_MAX_KILL |
|
||||
BT_VALID_3W_TMRS |
|
||||
BT_VALID_KILL_ACK |
|
||||
BT_VALID_KILL_CTS |
|
||||
BT_VALID_REDUCED_TX_POWER |
|
||||
BT_VALID_LUT);
|
||||
|
||||
if (mvm->cfg->bt_shared_single_ant)
|
||||
memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup,
|
||||
sizeof(iwl_single_shared_ant_lookup));
|
||||
else if (is_loose_coex())
|
||||
memcpy(&cmd.decision_lut, iwl_loose_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
else
|
||||
memcpy(&cmd.decision_lut, iwl_tight_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
|
||||
cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
|
||||
cmd.kill_ack_msk =
|
||||
cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
cmd.kill_cts_msk =
|
||||
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
|
||||
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
|
||||
|
||||
/* go to CALIB state in internal BT-Coex state machine */
|
||||
ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
@ -270,16 +240,67 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
|
||||
if (!bt_cmd)
|
||||
return -ENOMEM;
|
||||
cmd.data[0] = bt_cmd;
|
||||
|
||||
bt_cmd->max_kill = 5;
|
||||
bt_cmd->bt3_time_t7_value = 1;
|
||||
bt_cmd->bt3_prio_sample_time = 2;
|
||||
bt_cmd->bt3_timer_t2_value = 0xc;
|
||||
|
||||
bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ?
|
||||
BT_COEX_NW : BT_COEX_DISABLE;
|
||||
bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
|
||||
|
||||
bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
|
||||
BT_VALID_BT_PRIO_BOOST |
|
||||
BT_VALID_MAX_KILL |
|
||||
BT_VALID_3W_TMRS |
|
||||
BT_VALID_KILL_ACK |
|
||||
BT_VALID_KILL_CTS |
|
||||
BT_VALID_REDUCED_TX_POWER |
|
||||
BT_VALID_LUT);
|
||||
|
||||
if (mvm->cfg->bt_shared_single_ant)
|
||||
memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup,
|
||||
sizeof(iwl_single_shared_ant_lookup));
|
||||
else if (is_loose_coex())
|
||||
memcpy(&bt_cmd->decision_lut, iwl_loose_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
else
|
||||
memcpy(&bt_cmd->decision_lut, iwl_tight_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
|
||||
bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
|
||||
bt_cmd->kill_ack_msk =
|
||||
cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
bt_cmd->kill_cts_msk =
|
||||
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
|
||||
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
|
||||
kfree(bt_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
|
||||
bool reduced_tx_power)
|
||||
{
|
||||
enum iwl_bt_kill_msk bt_kill_msk;
|
||||
struct iwl_bt_coex_cmd cmd = {};
|
||||
struct iwl_bt_coex_cmd *bt_cmd;
|
||||
struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = BT_CONFIG,
|
||||
.data[0] = &bt_cmd,
|
||||
.len = { sizeof(*bt_cmd), },
|
||||
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
|
||||
return 0;
|
||||
|
||||
mvm->bt_kill_msk = bt_kill_msk;
|
||||
cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
|
||||
cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
|
||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
|
||||
|
||||
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
|
||||
if (!bt_cmd)
|
||||
return -ENOMEM;
|
||||
cmd.data[0] = bt_cmd;
|
||||
|
||||
bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
|
||||
bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
|
||||
bt_cmd->valid_bit_msk =
|
||||
cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
|
||||
|
||||
IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
|
||||
kfree(bt_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
||||
bool enable)
|
||||
{
|
||||
struct iwl_bt_coex_cmd cmd = {
|
||||
.valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
|
||||
.bt_reduced_tx_power = sta_id,
|
||||
struct iwl_bt_coex_cmd *bt_cmd;
|
||||
/* Send ASYNC since this can be sent from an atomic context */
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = BT_CONFIG,
|
||||
.len = { sizeof(*bt_cmd), },
|
||||
.dataflags = { IWL_HCMD_DFL_DUP, },
|
||||
.flags = CMD_ASYNC,
|
||||
};
|
||||
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
int ret;
|
||||
|
||||
/* This can happen if the station has been removed right now */
|
||||
if (sta_id == IWL_MVM_STATION_COUNT)
|
||||
@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
|
||||
if (mvmsta->bt_reduced_txpower == enable)
|
||||
return 0;
|
||||
|
||||
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
|
||||
if (!bt_cmd)
|
||||
return -ENOMEM;
|
||||
cmd.data[0] = bt_cmd;
|
||||
|
||||
bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
|
||||
bt_cmd->bt_reduced_tx_power = sta_id;
|
||||
|
||||
if (enable)
|
||||
cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
|
||||
bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
|
||||
|
||||
IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
|
||||
enable ? "en" : "dis", sta_id);
|
||||
|
||||
mvmsta->bt_reduced_txpower = enable;
|
||||
|
||||
/* Send ASYNC since this can be sent from an atomic context */
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
|
||||
kfree(bt_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iwl_bt_iterator_data {
|
||||
@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
/* non associated BSSes aren't to be considered */
|
||||
if (!vif->bss_conf.assoc)
|
||||
return;
|
||||
|
||||
if (band != IEEE80211_BAND_2GHZ) {
|
||||
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
|
||||
smps_mode);
|
||||
@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
mvmsta = (void *)sta->drv_priv;
|
||||
|
||||
data->num_bss_ifaces++;
|
||||
|
||||
/*
|
||||
* This interface doesn't support reduced Tx power (because of low
|
||||
* RSSI probably), then set bt_kill_msk to default values.
|
||||
@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
enum ieee80211_band band;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->chanctx_conf);
|
||||
if (chanctx_conf && chanctx_conf->def.chan)
|
||||
band = chanctx_conf->def.chan->band;
|
||||
else
|
||||
band = -1;
|
||||
rcu_read_unlock();
|
||||
|
||||
/* if we are in 2GHz we will get a notification from the fw */
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
return;
|
||||
|
||||
/* else, we can remove all the constraints */
|
||||
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
|
||||
|
||||
iwl_mvm_bt_coex_notif_handle(mvm);
|
||||
}
|
||||
|
71
drivers/net/wireless/iwlwifi/mvm/constants.h
Normal file
71
drivers/net/wireless/iwlwifi/mvm/constants.h
Normal file
@ -0,0 +1,71 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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) 2013 Intel Corporation. All rights reserved.
|
||||
* 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.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __MVM_CONSTANTS_H
|
||||
#define __MVM_CONSTANTS_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)
|
||||
|
||||
#endif /* __MVM_CONSTANTS_H */
|
@ -105,7 +105,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
mvmvif->target_ipv6_addrs[idx] = ifa->addr;
|
||||
idx++;
|
||||
if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS)
|
||||
if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
|
||||
break;
|
||||
}
|
||||
read_unlock_bh(&idev->lock);
|
||||
@ -373,36 +373,68 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
|
||||
static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_proto_offload_cmd cmd = {};
|
||||
union {
|
||||
struct iwl_proto_offload_cmd_v1 v1;
|
||||
struct iwl_proto_offload_cmd_v2 v2;
|
||||
} cmd = {};
|
||||
struct iwl_proto_offload_cmd_common *common;
|
||||
u32 enabled = 0, size;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int i;
|
||||
|
||||
if (mvmvif->num_target_ipv6_addrs) {
|
||||
cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS);
|
||||
memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN);
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
|
||||
if (mvmvif->num_target_ipv6_addrs) {
|
||||
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
|
||||
memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) !=
|
||||
sizeof(mvmvif->target_ipv6_addrs[0]));
|
||||
|
||||
for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
|
||||
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++)
|
||||
memcpy(cmd.v2.target_ipv6_addr[i],
|
||||
&mvmvif->target_ipv6_addrs[i],
|
||||
sizeof(cmd.v2.target_ipv6_addr[i]));
|
||||
} else {
|
||||
if (mvmvif->num_target_ipv6_addrs) {
|
||||
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
|
||||
memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) !=
|
||||
sizeof(mvmvif->target_ipv6_addrs[0]));
|
||||
|
||||
for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
|
||||
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++)
|
||||
memcpy(cmd.v1.target_ipv6_addr[i],
|
||||
&mvmvif->target_ipv6_addrs[i],
|
||||
sizeof(cmd.v1.target_ipv6_addr[i]));
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) !=
|
||||
sizeof(mvmvif->target_ipv6_addrs[i]));
|
||||
|
||||
for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++)
|
||||
memcpy(cmd.target_ipv6_addr[i],
|
||||
&mvmvif->target_ipv6_addrs[i],
|
||||
sizeof(cmd.target_ipv6_addr[i]));
|
||||
#endif
|
||||
|
||||
if (vif->bss_conf.arp_addr_cnt) {
|
||||
cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP);
|
||||
cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
|
||||
memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN);
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
|
||||
common = &cmd.v2.common;
|
||||
size = sizeof(cmd.v2);
|
||||
} else {
|
||||
common = &cmd.v1.common;
|
||||
size = sizeof(cmd.v1);
|
||||
}
|
||||
|
||||
if (!cmd.enabled)
|
||||
if (vif->bss_conf.arp_addr_cnt) {
|
||||
enabled |= IWL_D3_PROTO_OFFLOAD_ARP;
|
||||
common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
|
||||
memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
return 0;
|
||||
|
||||
common->enabled = cpu_to_le32(enabled);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
size, &cmd);
|
||||
}
|
||||
|
||||
enum iwl_mvm_tcp_packet_type {
|
||||
|
@ -424,40 +424,11 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->dbgfs_data;
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
char buf[256];
|
||||
int bufsz = sizeof(buf);
|
||||
int pos = 0;
|
||||
int pos;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
|
||||
0 : 1);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
|
||||
le32_to_cpu(cmd.skip_dtim_periods));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
|
||||
iwlmvm_mod_params.power_scheme);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
|
||||
le16_to_cpu(cmd.flags));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
|
||||
cmd.keep_alive_seconds);
|
||||
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
|
||||
1 : 0);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.rx_data_timeout));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.tx_data_timeout));
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
||||
pos += scnprintf(buf+pos, bufsz-pos,
|
||||
"lprx_rssi_threshold = %d\n",
|
||||
le32_to_cpu(cmd.lprx_rssi_threshold));
|
||||
}
|
||||
pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
@ -626,20 +597,19 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
bool restart_fw = iwlwifi_mod_params.restart_fw;
|
||||
int ret;
|
||||
|
||||
iwlwifi_mod_params.restart_fw = true;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
/* allow one more restart that we're provoking here */
|
||||
if (mvm->restart_fw >= 0)
|
||||
mvm->restart_fw++;
|
||||
|
||||
/* take the return value to make compiler happy - it will fail anyway */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwlwifi_mod_params.restart_fw = restart_fw;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -661,8 +631,14 @@ static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
|
||||
case MVM_DEBUGFS_BF_ROAMING_STATE:
|
||||
dbgfs_bf->bf_roaming_state = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_TEMPERATURE_DELTA:
|
||||
dbgfs_bf->bf_temperature_delta = value;
|
||||
case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
|
||||
dbgfs_bf->bf_temp_threshold = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
|
||||
dbgfs_bf->bf_temp_fast_filter = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
|
||||
dbgfs_bf->bf_temp_slow_filter = value;
|
||||
break;
|
||||
case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
|
||||
dbgfs_bf->bf_enable_beacon_filter = value;
|
||||
@ -721,13 +697,27 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
|
||||
value > IWL_BF_ROAMING_STATE_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_ROAMING_STATE;
|
||||
} else if (!strncmp("bf_temperature_delta=", buf, 21)) {
|
||||
if (sscanf(buf+21, "%d", &value) != 1)
|
||||
} else if (!strncmp("bf_temp_threshold=", buf, 18)) {
|
||||
if (sscanf(buf+18, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_TEMPERATURE_DELTA_MIN ||
|
||||
value > IWL_BF_TEMPERATURE_DELTA_MAX)
|
||||
if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
|
||||
value > IWL_BF_TEMP_THRESHOLD_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA;
|
||||
param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
|
||||
} else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
|
||||
if (sscanf(buf+20, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
|
||||
value > IWL_BF_TEMP_FAST_FILTER_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
|
||||
} else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
|
||||
if (sscanf(buf+20, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
|
||||
value > IWL_BF_TEMP_SLOW_FILTER_MAX)
|
||||
return -EINVAL;
|
||||
param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
|
||||
} else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
|
||||
if (sscanf(buf+24, "%d", &value) != 1)
|
||||
return -EINVAL;
|
||||
@ -789,41 +779,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,
|
||||
.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,
|
||||
.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,
|
||||
.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,
|
||||
.bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT,
|
||||
.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
|
||||
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
|
||||
.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
|
||||
.ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter =
|
||||
cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
|
||||
.ba_enable_beacon_abort =
|
||||
cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
|
||||
};
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
if (mvmvif->bf_enabled)
|
||||
cmd.bf_enable_beacon_filter = 1;
|
||||
cmd.bf_enable_beacon_filter = cpu_to_le32(1);
|
||||
else
|
||||
cmd.bf_enable_beacon_filter = 0;
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
|
||||
cmd.bf_energy_delta);
|
||||
le32_to_cpu(cmd.bf_energy_delta));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
|
||||
cmd.bf_roaming_energy_delta);
|
||||
le32_to_cpu(cmd.bf_roaming_energy_delta));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
|
||||
cmd.bf_roaming_state);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n",
|
||||
cmd.bf_temperature_delta);
|
||||
le32_to_cpu(cmd.bf_roaming_state));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
|
||||
le32_to_cpu(cmd.bf_temp_threshold));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
|
||||
le32_to_cpu(cmd.bf_temp_fast_filter));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
|
||||
le32_to_cpu(cmd.bf_temp_slow_filter));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
|
||||
cmd.bf_enable_beacon_filter);
|
||||
le32_to_cpu(cmd.bf_enable_beacon_filter));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
|
||||
cmd.bf_debug_flag);
|
||||
le32_to_cpu(cmd.bf_debug_flag));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
|
||||
cmd.bf_escape_timer);
|
||||
le32_to_cpu(cmd.bf_escape_timer));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
|
||||
cmd.ba_escape_timer);
|
||||
le32_to_cpu(cmd.ba_escape_timer));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
|
||||
cmd.ba_enable_beacon_abort);
|
||||
le32_to_cpu(cmd.ba_enable_beacon_abort));
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
@ -98,34 +98,63 @@ enum iwl_proto_offloads {
|
||||
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
|
||||
};
|
||||
|
||||
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2
|
||||
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
|
||||
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6
|
||||
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6
|
||||
|
||||
/**
|
||||
* struct iwl_proto_offload_cmd - ARP/NS offload configuration
|
||||
* struct iwl_proto_offload_cmd_common - ARP/NS offload common part
|
||||
* @enabled: enable flags
|
||||
* @remote_ipv4_addr: remote address to answer to (or zero if all)
|
||||
* @host_ipv4_addr: our IPv4 address to respond to queries for
|
||||
* @arp_mac_addr: our MAC address for ARP responses
|
||||
* @reserved: unused
|
||||
*/
|
||||
struct iwl_proto_offload_cmd_common {
|
||||
__le32 enabled;
|
||||
__be32 remote_ipv4_addr;
|
||||
__be32 host_ipv4_addr;
|
||||
u8 arp_mac_addr[ETH_ALEN];
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration
|
||||
* @common: common/IPv4 configuration
|
||||
* @remote_ipv6_addr: remote address to answer to (or zero if all)
|
||||
* @solicited_node_ipv6_addr: broken -- solicited node address exists
|
||||
* for each target address
|
||||
* @target_ipv6_addr: our target addresses
|
||||
* @ndp_mac_addr: neighbor soliciation response MAC address
|
||||
*/
|
||||
struct iwl_proto_offload_cmd {
|
||||
__le32 enabled;
|
||||
__be32 remote_ipv4_addr;
|
||||
__be32 host_ipv4_addr;
|
||||
u8 arp_mac_addr[ETH_ALEN];
|
||||
__le16 reserved1;
|
||||
|
||||
struct iwl_proto_offload_cmd_v1 {
|
||||
struct iwl_proto_offload_cmd_common common;
|
||||
u8 remote_ipv6_addr[16];
|
||||
u8 solicited_node_ipv6_addr[16];
|
||||
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16];
|
||||
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16];
|
||||
u8 ndp_mac_addr[ETH_ALEN];
|
||||
__le16 reserved2;
|
||||
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration
|
||||
* @common: common/IPv4 configuration
|
||||
* @remote_ipv6_addr: remote address to answer to (or zero if all)
|
||||
* @solicited_node_ipv6_addr: broken -- solicited node address exists
|
||||
* for each target address
|
||||
* @target_ipv6_addr: our target addresses
|
||||
* @ndp_mac_addr: neighbor soliciation response MAC address
|
||||
*/
|
||||
struct iwl_proto_offload_cmd_v2 {
|
||||
struct iwl_proto_offload_cmd_common common;
|
||||
u8 remote_ipv6_addr[16];
|
||||
u8 solicited_node_ipv6_addr[16];
|
||||
u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
|
||||
u8 ndp_mac_addr[ETH_ALEN];
|
||||
u8 numValidIPv6Addresses;
|
||||
u8 reserved2[3];
|
||||
} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
|
||||
|
||||
|
||||
/*
|
||||
* WOWLAN_PATTERNS
|
||||
|
@ -79,6 +79,10 @@
|
||||
* '1' Driver enables PM (use rest of parameters)
|
||||
* @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
|
||||
* '1' PM could sleep over DTIM till listen Interval.
|
||||
* @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
|
||||
* access categories are both delivery and trigger enabled.
|
||||
* @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
|
||||
* PBW Snoozing enabled
|
||||
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
|
||||
* @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
|
||||
*/
|
||||
@ -86,6 +90,8 @@ enum iwl_power_flags {
|
||||
POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
|
||||
POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
|
||||
POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
|
||||
POWER_FLAGS_SNOOZE_ENA_MSK = BIT(5),
|
||||
POWER_FLAGS_BT_SCO_ENA = BIT(8),
|
||||
POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
|
||||
POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
|
||||
};
|
||||
@ -93,7 +99,8 @@ enum iwl_power_flags {
|
||||
#define IWL_POWER_VEC_SIZE 5
|
||||
|
||||
/**
|
||||
* struct iwl_powertable_cmd - Power Table Command
|
||||
* struct iwl_powertable_cmd - legacy power command. Beside old API support this
|
||||
* is used also with a new power API for device wide power settings.
|
||||
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
|
||||
*
|
||||
* @flags: Power table command flags from POWER_FLAGS_*
|
||||
@ -124,6 +131,72 @@ struct iwl_powertable_cmd {
|
||||
__le32 lprx_rssi_threshold;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mac_power_cmd - New power command containing uAPSD support
|
||||
* MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
|
||||
* @id_and_color: MAC contex identifier
|
||||
* @flags: Power table command flags from POWER_FLAGS_*
|
||||
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
|
||||
* Minimum allowed:- 3 * DTIM. Keep alive period must be
|
||||
* set regardless of power scheme or current power state.
|
||||
* FW use this value also when PM is disabled.
|
||||
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
|
||||
* PSM transition - legacy PM
|
||||
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
|
||||
* PSM transition - legacy PM
|
||||
* @sleep_interval: not in use
|
||||
* @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
|
||||
* is set. For example, if it is required to skip over
|
||||
* one DTIM, this value need to be set to 2 (DTIM periods).
|
||||
* @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
|
||||
* PSM transition - uAPSD
|
||||
* @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
|
||||
* PSM transition - uAPSD
|
||||
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
|
||||
* Default: 80dbm
|
||||
* @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
|
||||
* @snooze_interval: TBD
|
||||
* @snooze_window: TBD
|
||||
* @snooze_step: TBD
|
||||
* @qndp_tid: TID client shall use for uAPSD QNDP triggers
|
||||
* @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for
|
||||
* each corresponding AC.
|
||||
* Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
|
||||
* @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
|
||||
* values.
|
||||
* @heavy_traffic_thr_tx_pkts: TX threshold measured in number of packets
|
||||
* @heavy_traffic_thr_rx_pkts: RX threshold measured in number of packets
|
||||
* @heavy_traffic_thr_tx_load: TX threshold measured in load's percentage
|
||||
* @heavy_traffic_thr_rx_load: RX threshold measured in load's percentage
|
||||
* @limited_ps_threshold:
|
||||
*/
|
||||
struct iwl_mac_power_cmd {
|
||||
/* CONTEXT_DESC_API_T_VER_1 */
|
||||
__le32 id_and_color;
|
||||
|
||||
/* CLIENT_PM_POWER_TABLE_S_VER_1 */
|
||||
__le16 flags;
|
||||
__le16 keep_alive_seconds;
|
||||
__le32 rx_data_timeout;
|
||||
__le32 tx_data_timeout;
|
||||
__le32 rx_data_timeout_uapsd;
|
||||
__le32 tx_data_timeout_uapsd;
|
||||
u8 lprx_rssi_threshold;
|
||||
u8 skip_dtim_periods;
|
||||
__le16 snooze_interval;
|
||||
__le16 snooze_window;
|
||||
u8 snooze_step;
|
||||
u8 qndp_tid;
|
||||
u8 uapsd_ac_flags;
|
||||
u8 uapsd_max_sp;
|
||||
u8 heavy_traffic_threshold_tx_packets;
|
||||
u8 heavy_traffic_threshold_rx_packets;
|
||||
u8 heavy_traffic_threshold_tx_percentage;
|
||||
u8 heavy_traffic_threshold_rx_percentage;
|
||||
u8 limited_ps_threshold;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_cmd
|
||||
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
|
||||
@ -143,11 +216,21 @@ struct iwl_powertable_cmd {
|
||||
* calculated for current beacon is less than the threshold, use
|
||||
* Roaming Energy Delta Threshold, otherwise use normal Energy Delta
|
||||
* Threshold. Typical energy threshold is -72dBm.
|
||||
* @bf_temperature_delta: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature changeis ignored for
|
||||
* @bf_temp_threshold: This threshold determines the type of temperature
|
||||
* filtering (Slow or Fast) that is selected (Units are in Celsuis):
|
||||
* If the current temperature is above this threshold - Fast filter
|
||||
* will be used, If the current temperature is below this threshold -
|
||||
* Slow filter will be used.
|
||||
* @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature change is ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature change is ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
|
||||
* @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
|
||||
* for a specific period of time. Units: Beacons.
|
||||
@ -156,17 +239,17 @@ struct iwl_powertable_cmd {
|
||||
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
|
||||
*/
|
||||
struct iwl_beacon_filter_cmd {
|
||||
u8 bf_energy_delta;
|
||||
u8 bf_roaming_energy_delta;
|
||||
u8 bf_roaming_state;
|
||||
u8 bf_temperature_delta;
|
||||
u8 bf_enable_beacon_filter;
|
||||
u8 bf_debug_flag;
|
||||
__le16 reserved1;
|
||||
__le32 bf_energy_delta;
|
||||
__le32 bf_roaming_energy_delta;
|
||||
__le32 bf_roaming_state;
|
||||
__le32 bf_temp_threshold;
|
||||
__le32 bf_temp_fast_filter;
|
||||
__le32 bf_temp_slow_filter;
|
||||
__le32 bf_enable_beacon_filter;
|
||||
__le32 bf_debug_flag;
|
||||
__le32 bf_escape_timer;
|
||||
__le32 ba_escape_timer;
|
||||
u8 ba_enable_beacon_abort;
|
||||
u8 reserved2[3];
|
||||
__le32 ba_enable_beacon_abort;
|
||||
} __packed;
|
||||
|
||||
/* Beacon filtering and beacon abort */
|
||||
@ -182,9 +265,17 @@ struct iwl_beacon_filter_cmd {
|
||||
#define IWL_BF_ROAMING_STATE_MAX 255
|
||||
#define IWL_BF_ROAMING_STATE_MIN 0
|
||||
|
||||
#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MAX 255
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MIN 0
|
||||
#define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
|
||||
#define IWL_BF_TEMP_THRESHOLD_MAX 255
|
||||
#define IWL_BF_TEMP_THRESHOLD_MIN 0
|
||||
|
||||
#define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
|
||||
#define IWL_BF_TEMP_FAST_FILTER_MAX 255
|
||||
#define IWL_BF_TEMP_FAST_FILTER_MIN 0
|
||||
|
||||
#define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
|
||||
#define IWL_BF_TEMP_SLOW_FILTER_MAX 255
|
||||
#define IWL_BF_TEMP_SLOW_FILTER_MIN 0
|
||||
|
||||
#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
|
||||
|
||||
@ -194,19 +285,23 @@ struct iwl_beacon_filter_cmd {
|
||||
#define IWL_BF_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BF_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ESCAPE_TIMER_DEFAULT 3
|
||||
#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
|
||||
#define IWL_BA_ESCAPE_TIMER_D3 6
|
||||
#define IWL_BA_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BA_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
|
||||
|
||||
#define IWL_BF_CMD_CONFIG_DEFAULTS \
|
||||
.bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \
|
||||
.bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \
|
||||
.bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \
|
||||
.bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \
|
||||
.bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \
|
||||
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
|
||||
#define IWL_BF_CMD_CONFIG_DEFAULTS \
|
||||
.bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT), \
|
||||
.bf_roaming_energy_delta = \
|
||||
cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT), \
|
||||
.bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT), \
|
||||
.bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT), \
|
||||
.bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \
|
||||
.bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \
|
||||
.bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT), \
|
||||
.bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
|
||||
.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
|
||||
|
||||
#endif
|
||||
|
@ -138,6 +138,8 @@ struct iwl_ssid_ie {
|
||||
*@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
|
||||
*@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
|
||||
*@SCAN_FLAGS_FRAGMENTED_SCAN:
|
||||
*@SCAN_FLAGS_PASSIVE2ACTIVE: use active scan on channels that was active
|
||||
* in the past hour, even if they are marked as passive.
|
||||
*/
|
||||
enum iwl_scan_flags {
|
||||
SCAN_FLAGS_PERIODIC_SCAN = BIT(0),
|
||||
@ -145,6 +147,7 @@ enum iwl_scan_flags {
|
||||
SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2),
|
||||
SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3),
|
||||
SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4),
|
||||
SCAN_FLAGS_PASSIVE2ACTIVE = BIT(5),
|
||||
};
|
||||
|
||||
/**
|
||||
@ -179,7 +182,7 @@ enum iwl_scan_type {
|
||||
* @quiet_time: in msecs, dwell this time for active scan on quiet channels
|
||||
* @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
|
||||
* this number of packets were received (typically 1)
|
||||
* @passive2active: is auto switching from passive to active allowed (0 or 1)
|
||||
* @passive2active: is auto switching from passive to active during scan allowed
|
||||
* @rxchain_sel_flags: RXON_RX_CHAIN_*
|
||||
* @max_out_time: in usecs, max out of serving channel time
|
||||
* @suspend_time: how long to pause scan when returning to service channel:
|
||||
|
@ -91,7 +91,6 @@
|
||||
* @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
|
||||
* @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration
|
||||
* @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
|
||||
* @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that
|
||||
* @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
|
||||
* @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
|
||||
* @TX_CMD_FLG_EXEC_PAPD: execute PAPD
|
||||
@ -120,7 +119,6 @@ enum iwl_tx_flags {
|
||||
TX_CMD_FLG_RESP_TO_DRV = BIT(21),
|
||||
TX_CMD_FLG_CCMP_AGG = BIT(22),
|
||||
TX_CMD_FLG_TKIP_MIC_DONE = BIT(23),
|
||||
TX_CMD_FLG_CTS_ONLY = BIT(24),
|
||||
TX_CMD_FLG_DUR = BIT(25),
|
||||
TX_CMD_FLG_FW_DROP = BIT(26),
|
||||
TX_CMD_FLG_EXEC_PAPD = BIT(27),
|
||||
|
@ -136,7 +136,7 @@ enum {
|
||||
CALIB_RES_NOTIF_PHY_DB = 0x6b,
|
||||
/* PHY_DB_CMD = 0x6c, */
|
||||
|
||||
/* Power */
|
||||
/* Power - legacy power table command */
|
||||
POWER_TABLE_CMD = 0x77,
|
||||
|
||||
/* Thermal Throttling*/
|
||||
@ -159,6 +159,7 @@ enum {
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||
BT_CONFIG = 0x9b,
|
||||
STATISTICS_NOTIFICATION = 0x9d,
|
||||
REDUCE_TX_POWER_CMD = 0x9f,
|
||||
|
||||
/* RF-KILL commands and notifications */
|
||||
CARD_STATE_CMD = 0xa0,
|
||||
@ -166,6 +167,9 @@ enum {
|
||||
|
||||
MISSED_BEACONS_NOTIFICATION = 0xa2,
|
||||
|
||||
/* Power - new power table command */
|
||||
MAC_PM_POWER_TABLE = 0xa9,
|
||||
|
||||
REPLY_RX_PHY_CMD = 0xc0,
|
||||
REPLY_RX_MPDU_CMD = 0xc1,
|
||||
BA_NOTIF = 0xc5,
|
||||
@ -223,6 +227,19 @@ struct iwl_tx_ant_cfg_cmd {
|
||||
__le32 valid;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_reduce_tx_power_cmd - TX power reduction command
|
||||
* REDUCE_TX_POWER_CMD = 0x9f
|
||||
* @flags: (reserved for future implementation)
|
||||
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
|
||||
* @pwr_restriction: TX power restriction in dBms.
|
||||
*/
|
||||
struct iwl_reduce_tx_power_cmd {
|
||||
u8 flags;
|
||||
u8 mac_context_id;
|
||||
__le16 pwr_restriction;
|
||||
} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
|
||||
|
||||
/*
|
||||
* Calibration control struct.
|
||||
* Sent as part of the phy configuration command.
|
||||
@ -765,6 +782,14 @@ struct iwl_phy_context_cmd {
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
|
||||
|
||||
#define IWL_RX_INFO_PHY_CNT 8
|
||||
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
|
||||
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
|
||||
#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
|
||||
#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
|
||||
#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
|
||||
#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
|
||||
#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
|
||||
|
||||
#define IWL_RX_INFO_AGC_IDX 1
|
||||
#define IWL_RX_INFO_RSSI_AB_IDX 2
|
||||
#define IWL_OFDM_AGC_A_MSK 0x0000007f
|
||||
|
@ -78,22 +78,6 @@
|
||||
|
||||
#define UCODE_VALID_OK cpu_to_le32(0x1)
|
||||
|
||||
/* Default calibration values for WkP - set to INIT image w/o running */
|
||||
static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
|
||||
static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
|
||||
struct iwl_calib_default_data {
|
||||
u16 size;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
|
||||
|
||||
static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
|
||||
[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
|
||||
[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
|
||||
};
|
||||
|
||||
struct iwl_mvm_alive_data {
|
||||
bool valid;
|
||||
u32 scd_base_addr;
|
||||
@ -248,40 +232,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
|
||||
}
|
||||
|
||||
static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_raw[16]; /* holds the variable size commands */
|
||||
struct iwl_set_calib_default_cmd *cmd =
|
||||
(struct iwl_set_calib_default_cmd *)cmd_raw;
|
||||
int ret, i;
|
||||
|
||||
/* Setting default values for calibrations we don't run */
|
||||
for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
|
||||
u16 cmd_len;
|
||||
|
||||
if (wkp_calib_default_data[i].size == 0)
|
||||
continue;
|
||||
|
||||
memset(cmd_raw, 0, sizeof(cmd_raw));
|
||||
cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
|
||||
cmd->calib_index = cpu_to_le16(i);
|
||||
cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
|
||||
if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
|
||||
"Need to enlarge cmd_raw to %d\n", cmd_len))
|
||||
break;
|
||||
memcpy(cmd->data, wkp_calib_default_data[i].data,
|
||||
wkp_calib_default_data[i].size);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
|
||||
sizeof(*cmd) +
|
||||
wkp_calib_default_data[i].size,
|
||||
cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
{
|
||||
struct iwl_notification_wait calib_wait;
|
||||
@ -342,11 +292,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* need to set default values */
|
||||
ret = iwl_set_default_calibrations(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Send phy configurations command to init uCode
|
||||
* to start the 16.0 uCode init image internal calibrations.
|
||||
|
@ -264,7 +264,8 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
|
||||
return 0;
|
||||
|
||||
/* Therefore, in recovery, we can't get here */
|
||||
WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
|
||||
if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
|
||||
return -EBUSY;
|
||||
|
||||
mvmvif->id = find_first_bit(data.available_mac_ids,
|
||||
NUM_MAC_INDEX_DRIVER);
|
||||
|
@ -153,7 +153,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TIMING_BEACON_ONLY |
|
||||
IEEE80211_HW_CONNECTION_MONITOR;
|
||||
IEEE80211_HW_CONNECTION_MONITOR |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
||||
|
||||
hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
|
||||
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
|
||||
@ -531,6 +533,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@ -567,7 +570,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
/* beacon filtering */
|
||||
if (!mvm->bf_allowed_vif &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p){
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
|
||||
mvm->bf_allowed_vif = mvmvif;
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
}
|
||||
@ -719,6 +723,20 @@ out_release:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
s8 tx_power)
|
||||
{
|
||||
/* FW is in charge of regulatory enforcement */
|
||||
struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
|
||||
.mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
|
||||
.pwr_restriction = cpu_to_le16(tx_power),
|
||||
};
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
|
||||
sizeof(reduce_txpwr_cmd),
|
||||
&reduce_txpwr_cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
return 0;
|
||||
@ -766,7 +784,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
IWL_ERR(mvm, "failed to update quotas\n");
|
||||
return;
|
||||
}
|
||||
iwl_mvm_bt_coex_vif_assoc(mvm, vif);
|
||||
iwl_mvm_configure_mcast_filter(mvm, vif);
|
||||
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
||||
/* remove AP station now that the MAC is unassoc */
|
||||
@ -779,9 +796,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update quotas\n");
|
||||
}
|
||||
ret = iwl_mvm_power_update_mode(mvm, vif);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update power mode\n");
|
||||
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) {
|
||||
/* Workaround for FW bug, otherwise FW disables device
|
||||
* power save upon disassociation
|
||||
*/
|
||||
ret = iwl_mvm_power_update_mode(mvm, vif);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update power mode\n");
|
||||
}
|
||||
iwl_mvm_bt_coex_vif_assoc(mvm, vif);
|
||||
} else if (changes & BSS_CHANGED_BEACON_INFO) {
|
||||
/*
|
||||
* We received a beacon _after_ association so
|
||||
@ -794,6 +817,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *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);
|
||||
iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "iwl-trans.h"
|
||||
#include "sta.h"
|
||||
#include "fw-api.h"
|
||||
#include "constants.h"
|
||||
|
||||
#define IWL_INVALID_MAC80211_QUEUE 0xff
|
||||
#define IWL_MVM_MAX_ADDRESSES 5
|
||||
@ -91,6 +92,9 @@ enum iwl_mvm_tx_fifo {
|
||||
};
|
||||
|
||||
extern struct ieee80211_ops iwl_mvm_hw_ops;
|
||||
extern const struct iwl_mvm_power_ops pm_legacy_ops;
|
||||
extern const struct iwl_mvm_power_ops pm_mac_ops;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_mod_params - module parameters for iwlmvm
|
||||
* @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted.
|
||||
@ -150,6 +154,17 @@ enum iwl_power_scheme {
|
||||
|
||||
#define IWL_CONN_MAX_LISTEN_INTERVAL 70
|
||||
|
||||
struct iwl_mvm_power_ops {
|
||||
int (*power_update_mode)(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
char *buf, int bufsz);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
enum iwl_dbgfs_pm_mask {
|
||||
MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
|
||||
@ -163,7 +178,7 @@ enum iwl_dbgfs_pm_mask {
|
||||
};
|
||||
|
||||
struct iwl_dbgfs_pm {
|
||||
u8 keep_alive_seconds;
|
||||
u16 keep_alive_seconds;
|
||||
u32 rx_data_timeout;
|
||||
u32 tx_data_timeout;
|
||||
bool skip_over_dtim;
|
||||
@ -180,24 +195,28 @@ enum iwl_dbgfs_bf_mask {
|
||||
MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0),
|
||||
MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1),
|
||||
MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2),
|
||||
MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3),
|
||||
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4),
|
||||
MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5),
|
||||
MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6),
|
||||
MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7),
|
||||
MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8),
|
||||
MVM_DEBUGFS_BF_TEMP_THRESHOLD = BIT(3),
|
||||
MVM_DEBUGFS_BF_TEMP_FAST_FILTER = BIT(4),
|
||||
MVM_DEBUGFS_BF_TEMP_SLOW_FILTER = BIT(5),
|
||||
MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(6),
|
||||
MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(7),
|
||||
MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(8),
|
||||
MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(9),
|
||||
MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(10),
|
||||
};
|
||||
|
||||
struct iwl_dbgfs_bf {
|
||||
u8 bf_energy_delta;
|
||||
u8 bf_roaming_energy_delta;
|
||||
u8 bf_roaming_state;
|
||||
u8 bf_temperature_delta;
|
||||
u8 bf_enable_beacon_filter;
|
||||
u8 bf_debug_flag;
|
||||
u32 bf_energy_delta;
|
||||
u32 bf_roaming_energy_delta;
|
||||
u32 bf_roaming_state;
|
||||
u32 bf_temp_threshold;
|
||||
u32 bf_temp_fast_filter;
|
||||
u32 bf_temp_slow_filter;
|
||||
u32 bf_enable_beacon_filter;
|
||||
u32 bf_debug_flag;
|
||||
u32 bf_escape_timer;
|
||||
u32 ba_escape_timer;
|
||||
u8 ba_enable_beacon_abort;
|
||||
u32 ba_enable_beacon_abort;
|
||||
int mask;
|
||||
};
|
||||
#endif
|
||||
@ -268,7 +287,7 @@ struct iwl_mvm_vif {
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
/* IPv6 addresses for WoWLAN */
|
||||
struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS];
|
||||
struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
|
||||
int num_target_ipv6_addrs;
|
||||
#endif
|
||||
#endif
|
||||
@ -459,6 +478,9 @@ struct iwl_mvm {
|
||||
*/
|
||||
u8 vif_count;
|
||||
|
||||
/* -1 for always, 0 for never, >0 for that many times */
|
||||
s8 restart_fw;
|
||||
|
||||
struct led_classdev led;
|
||||
|
||||
struct ieee80211_vif *p2p_device_vif;
|
||||
@ -482,6 +504,8 @@ struct iwl_mvm {
|
||||
/* Thermal Throttling and CTkill */
|
||||
struct iwl_mvm_tt_mgmt thermal_throttle;
|
||||
s32 temperature; /* Celsius */
|
||||
|
||||
const struct iwl_mvm_power_ops *pm_ops;
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
@ -525,6 +549,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||
enum ieee80211_band band);
|
||||
u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
|
||||
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
|
||||
u8 first_antenna(u8 mask);
|
||||
u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
|
||||
|
||||
@ -660,10 +685,26 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
||||
u8 flags, bool init);
|
||||
|
||||
/* power managment */
|
||||
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_powertable_cmd *cmd);
|
||||
static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
return mvm->pm_ops->power_update_mode(mvm, vif);
|
||||
}
|
||||
|
||||
static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
return mvm->pm_ops->power_disable(mvm, vif);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
char *buf, int bufsz)
|
||||
{
|
||||
return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
|
||||
}
|
||||
#endif
|
||||
|
||||
int iwl_mvm_leds_init(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
|
||||
@ -707,6 +748,10 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_beacon_filter_cmd *cmd);
|
||||
int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
|
||||
/* SMPS */
|
||||
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
||||
CMD(BEACON_NOTIFICATION),
|
||||
CMD(BEACON_TEMPLATE_CMD),
|
||||
CMD(STATISTICS_NOTIFICATION),
|
||||
CMD(REDUCE_TX_POWER_CMD),
|
||||
CMD(TX_ANT_CONFIGURATION_CMD),
|
||||
CMD(D3_CONFIG_CMD),
|
||||
CMD(PROT_OFFLOAD_CONFIG_CMD),
|
||||
@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
||||
CMD(MCAST_FILTER_CMD),
|
||||
CMD(REPLY_BEACON_FILTERING_CMD),
|
||||
CMD(REPLY_THERMAL_MNG_BACKOFF),
|
||||
CMD(MAC_PM_POWER_TABLE),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
mvm->fw = fw;
|
||||
mvm->hw = hw;
|
||||
|
||||
mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
|
||||
|
||||
mutex_init(&mvm->mutex);
|
||||
spin_lock_init(&mvm->async_handlers_lock);
|
||||
INIT_LIST_HEAD(&mvm->time_event_list);
|
||||
@ -431,6 +435,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
if (err)
|
||||
goto out_unregister;
|
||||
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)
|
||||
mvm->pm_ops = &pm_mac_ops;
|
||||
else
|
||||
mvm->pm_ops = &pm_legacy_ops;
|
||||
|
||||
return op_mode;
|
||||
|
||||
out_unregister:
|
||||
@ -638,6 +647,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
ieee80211_free_txskb(mvm->hw, skb);
|
||||
}
|
||||
|
||||
struct iwl_mvm_reprobe {
|
||||
struct device *dev;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static void iwl_mvm_reprobe_wk(struct work_struct *wk)
|
||||
{
|
||||
struct iwl_mvm_reprobe *reprobe;
|
||||
|
||||
reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
|
||||
if (device_reprobe(reprobe->dev))
|
||||
dev_err(reprobe->dev, "reprobe failed!\n");
|
||||
kfree(reprobe);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_abort_notification_waits(&mvm->notif_wait);
|
||||
@ -649,9 +674,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
|
||||
* can't recover this since we're already half suspended.
|
||||
*/
|
||||
if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n");
|
||||
} else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
|
||||
iwlwifi_mod_params.restart_fw) {
|
||||
struct iwl_mvm_reprobe *reprobe;
|
||||
|
||||
IWL_ERR(mvm,
|
||||
"Firmware error during reconfiguration - reprobe!\n");
|
||||
|
||||
/*
|
||||
* get a module reference to avoid doing this while unloading
|
||||
* anyway and to avoid scheduling a work with code that's
|
||||
* being removed.
|
||||
*/
|
||||
if (!try_module_get(THIS_MODULE)) {
|
||||
IWL_ERR(mvm, "Module is being unloaded - abort\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC);
|
||||
if (!reprobe) {
|
||||
module_put(THIS_MODULE);
|
||||
return;
|
||||
}
|
||||
reprobe->dev = mvm->trans->dev;
|
||||
INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
|
||||
schedule_work(&reprobe->work);
|
||||
} else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
|
||||
/*
|
||||
* This is a bit racy, but worst case we tell mac80211 about
|
||||
* a stopped/aborted (sched) scan when that was already done
|
||||
@ -669,6 +715,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mvm->restart_fw > 0)
|
||||
mvm->restart_fw--;
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
}
|
||||
}
|
||||
@ -678,6 +726,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
iwl_mvm_dump_nic_error_log(mvm);
|
||||
if (!mvm->restart_fw)
|
||||
iwl_mvm_dump_sram(mvm);
|
||||
|
||||
iwl_mvm_nic_restart(mvm);
|
||||
}
|
||||
|
@ -75,8 +75,8 @@
|
||||
|
||||
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
|
||||
|
||||
static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -85,52 +85,60 @@ static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
|
||||
|
||||
if (!ret) {
|
||||
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
|
||||
cmd->ba_enable_beacon_abort);
|
||||
le32_to_cpu(cmd->ba_enable_beacon_abort));
|
||||
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
|
||||
cmd->ba_escape_timer);
|
||||
le32_to_cpu(cmd->ba_escape_timer));
|
||||
IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
|
||||
cmd->bf_debug_flag);
|
||||
le32_to_cpu(cmd->bf_debug_flag));
|
||||
IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
|
||||
cmd->bf_enable_beacon_filter);
|
||||
le32_to_cpu(cmd->bf_enable_beacon_filter));
|
||||
IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
|
||||
cmd->bf_energy_delta);
|
||||
le32_to_cpu(cmd->bf_energy_delta));
|
||||
IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
|
||||
cmd->bf_escape_timer);
|
||||
le32_to_cpu(cmd->bf_escape_timer));
|
||||
IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
|
||||
cmd->bf_roaming_energy_delta);
|
||||
le32_to_cpu(cmd->bf_roaming_energy_delta));
|
||||
IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
|
||||
cmd->bf_roaming_state);
|
||||
IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
|
||||
cmd->bf_temperature_delta);
|
||||
le32_to_cpu(cmd->bf_roaming_state));
|
||||
IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
|
||||
le32_to_cpu(cmd->bf_temp_threshold));
|
||||
IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
|
||||
le32_to_cpu(cmd->bf_temp_fast_filter));
|
||||
IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
|
||||
le32_to_cpu(cmd->bf_temp_slow_filter));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter = 1,
|
||||
.ba_enable_beacon_abort = enable,
|
||||
.bf_enable_beacon_filter = cpu_to_le32(1),
|
||||
.ba_enable_beacon_abort = cpu_to_le32(enable),
|
||||
};
|
||||
|
||||
if (!mvmvif->bf_enabled)
|
||||
return 0;
|
||||
|
||||
if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
|
||||
cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
|
||||
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
|
||||
return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
||||
struct iwl_powertable_cmd *cmd)
|
||||
struct iwl_mac_power_cmd *cmd)
|
||||
{
|
||||
IWL_DEBUG_POWER(mvm,
|
||||
"Sending power table command for power level %d, flags = 0x%X\n",
|
||||
iwlmvm_mod_params.power_scheme,
|
||||
"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
|
||||
cmd->id_and_color, iwlmvm_mod_params.power_scheme,
|
||||
le16_to_cpu(cmd->flags));
|
||||
IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
|
||||
IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
|
||||
le16_to_cpu(cmd->keep_alive_seconds));
|
||||
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
|
||||
@ -139,15 +147,16 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
||||
le32_to_cpu(cmd->tx_data_timeout));
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
|
||||
IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
|
||||
le32_to_cpu(cmd->skip_dtim_periods));
|
||||
cmd->skip_dtim_periods);
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
||||
IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
|
||||
le32_to_cpu(cmd->lprx_rssi_threshold));
|
||||
cmd->lprx_rssi_threshold);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_powertable_cmd *cmd)
|
||||
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;
|
||||
@ -158,19 +167,26 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
/*
|
||||
* Regardless of power management state the driver must set
|
||||
* keep alive period. FW will use it for sending keep alive NDPs
|
||||
* immediately after association.
|
||||
* immediately after association. Check that keep alive period
|
||||
* is at least 3 * DTIM
|
||||
*/
|
||||
cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
|
||||
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
keep_alive = max_t(int, 3 * dtimper_msec,
|
||||
MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
|
||||
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
|
||||
cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
|
||||
|
||||
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
|
||||
return;
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
if (!vif->bss_conf.assoc)
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
|
||||
@ -186,12 +202,9 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
(vif->bss_conf.beacon_rate->bitrate == 10 ||
|
||||
vif->bss_conf.beacon_rate->bitrate == 60)) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
||||
cmd->lprx_rssi_threshold =
|
||||
cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
|
||||
cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
|
||||
}
|
||||
|
||||
dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
/* Check if radar detection is required on current channel */
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->chanctx_conf);
|
||||
@ -207,27 +220,25 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
|
||||
mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
cmd->skip_dtim_periods = cpu_to_le32(3);
|
||||
cmd->skip_dtim_periods = 3;
|
||||
}
|
||||
|
||||
/* Check that keep alive period is at least 3 * DTIM */
|
||||
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
keep_alive = max_t(int, 3 * dtimper_msec,
|
||||
MSEC_PER_SEC * cmd->keep_alive_seconds);
|
||||
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
|
||||
cmd->keep_alive_seconds = keep_alive;
|
||||
|
||||
if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
|
||||
cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
|
||||
} else {
|
||||
cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
|
||||
cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
|
||||
cmd->keep_alive_seconds =
|
||||
cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
|
||||
if (mvmvif->dbgfs_pm.skip_over_dtim)
|
||||
cmd->flags |=
|
||||
@ -243,8 +254,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
|
||||
cmd->skip_dtim_periods =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
|
||||
cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
|
||||
if (mvmvif->dbgfs_pm.lprx_ena)
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
||||
@ -252,16 +262,16 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
|
||||
}
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
|
||||
cmd->lprx_rssi_threshold =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
|
||||
cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
}
|
||||
|
||||
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret;
|
||||
bool ba_enable;
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
struct iwl_mac_power_cmd cmd = {};
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
@ -280,7 +290,7 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -291,15 +301,19 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
|
||||
}
|
||||
|
||||
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
struct iwl_mac_power_cmd cmd = {};
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color));
|
||||
|
||||
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
|
||||
cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
@ -310,11 +324,50 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
#endif
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
|
||||
return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, char *buf,
|
||||
int bufsz)
|
||||
{
|
||||
struct iwl_mac_power_cmd cmd = {};
|
||||
int pos = 0;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
|
||||
0 : 1);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
|
||||
cmd.skip_dtim_periods);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
|
||||
iwlmvm_mod_params.power_scheme);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
|
||||
le16_to_cpu(cmd.flags));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
|
||||
le16_to_cpu(cmd.keep_alive_seconds));
|
||||
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
|
||||
1 : 0);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.rx_data_timeout));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.tx_data_timeout));
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
||||
pos += scnprintf(buf+pos, bufsz-pos,
|
||||
"lprx_rssi_threshold = %d\n",
|
||||
cmd.lprx_rssi_threshold);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
void
|
||||
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
||||
struct iwl_beacon_filter_cmd *cmd)
|
||||
@ -323,22 +376,30 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
|
||||
struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
|
||||
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
|
||||
cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta;
|
||||
cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
|
||||
cmd->bf_roaming_energy_delta =
|
||||
dbgfs_bf->bf_roaming_energy_delta;
|
||||
cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
|
||||
cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state;
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA)
|
||||
cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta;
|
||||
cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
|
||||
cmd->bf_temp_threshold =
|
||||
cpu_to_le32(dbgfs_bf->bf_temp_threshold);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
|
||||
cmd->bf_temp_fast_filter =
|
||||
cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
|
||||
cmd->bf_temp_slow_filter =
|
||||
cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
|
||||
cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag;
|
||||
cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
|
||||
cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
|
||||
cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
|
||||
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
|
||||
cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort;
|
||||
cmd->ba_enable_beacon_abort =
|
||||
cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -348,7 +409,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_beacon_filter_cmd cmd = {
|
||||
IWL_BF_CMD_CONFIG_DEFAULTS,
|
||||
.bf_enable_beacon_filter = 1,
|
||||
.bf_enable_beacon_filter = cpu_to_le32(1),
|
||||
};
|
||||
int ret;
|
||||
|
||||
@ -372,7 +433,8 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) ||
|
||||
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
@ -382,3 +444,11 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct iwl_mvm_power_ops pm_mac_ops = {
|
||||
.power_update_mode = iwl_mvm_power_mac_update_mode,
|
||||
.power_disable = iwl_mvm_power_mac_disable,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
.power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
|
||||
#endif
|
||||
};
|
||||
|
319
drivers/net/wireless/iwlwifi/mvm/power_legacy.c
Normal file
319
drivers/net/wireless/iwlwifi/mvm/power_legacy.c
Normal file
@ -0,0 +1,319 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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) 2012 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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) 2012 - 2013 Intel Corporation. All rights reserved.
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-debug.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "fw-api-power.h"
|
||||
|
||||
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
|
||||
|
||||
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
|
||||
struct iwl_powertable_cmd *cmd)
|
||||
{
|
||||
IWL_DEBUG_POWER(mvm,
|
||||
"Sending power table command for power level %d, flags = 0x%X\n",
|
||||
iwlmvm_mod_params.power_scheme,
|
||||
le16_to_cpu(cmd->flags));
|
||||
IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
|
||||
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
|
||||
le32_to_cpu(cmd->rx_data_timeout));
|
||||
IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
|
||||
le32_to_cpu(cmd->tx_data_timeout));
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
|
||||
IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
|
||||
le32_to_cpu(cmd->skip_dtim_periods));
|
||||
if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
||||
IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
|
||||
le32_to_cpu(cmd->lprx_rssi_threshold));
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_powertable_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;
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
/*
|
||||
* Regardless of power management state the driver must set
|
||||
* keep alive period. FW will use it for sending keep alive NDPs
|
||||
* immediately after association.
|
||||
*/
|
||||
cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
|
||||
|
||||
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
|
||||
return;
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
if (!vif->bss_conf.assoc)
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
|
||||
mvmvif->dbgfs_pm.disable_power_off)
|
||||
cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
#endif
|
||||
if (!vif->bss_conf.ps)
|
||||
return;
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
||||
|
||||
if (vif->bss_conf.beacon_rate &&
|
||||
(vif->bss_conf.beacon_rate->bitrate == 10 ||
|
||||
vif->bss_conf.beacon_rate->bitrate == 60)) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
||||
cmd->lprx_rssi_threshold =
|
||||
cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
|
||||
}
|
||||
|
||||
dtimper = hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
/* 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();
|
||||
|
||||
/* Check skip over DTIM conditions */
|
||||
if (!radar_detect && (dtimper <= 10) &&
|
||||
(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
|
||||
mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
cmd->skip_dtim_periods = cpu_to_le32(3);
|
||||
}
|
||||
|
||||
/* Check that keep alive period is at least 3 * DTIM */
|
||||
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
|
||||
keep_alive = max_t(int, 3 * dtimper_msec,
|
||||
MSEC_PER_SEC * cmd->keep_alive_seconds);
|
||||
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
|
||||
cmd->keep_alive_seconds = keep_alive;
|
||||
|
||||
if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
|
||||
cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
|
||||
} else {
|
||||
cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
|
||||
cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
|
||||
if (mvmvif->dbgfs_pm.skip_over_dtim)
|
||||
cmd->flags |=
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
else
|
||||
cmd->flags &=
|
||||
cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
|
||||
}
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
|
||||
cmd->skip_dtim_periods =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
|
||||
if (mvmvif->dbgfs_pm.lprx_ena)
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
|
||||
else
|
||||
cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
|
||||
}
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
|
||||
cmd->lprx_rssi_threshold =
|
||||
cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
}
|
||||
|
||||
static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret;
|
||||
bool ba_enable;
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* TODO: The following vif_count verification is temporary condition.
|
||||
* Avoid power mode update if more than one interface is currently
|
||||
* active. Remove this condition when FW will support power management
|
||||
* on multiple MACs.
|
||||
*/
|
||||
IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
|
||||
mvm->vif_count);
|
||||
if (mvm->vif_count > 1)
|
||||
return 0;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ba_enable = !!(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
|
||||
|
||||
return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
|
||||
}
|
||||
|
||||
static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
struct iwl_mvm_vif *mvmvif __maybe_unused =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
|
||||
cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
|
||||
mvmvif->dbgfs_pm.disable_power_off)
|
||||
cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
#endif
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, char *buf,
|
||||
int bufsz)
|
||||
{
|
||||
struct iwl_powertable_cmd cmd = {};
|
||||
int pos = 0;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
|
||||
0 : 1);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
|
||||
le32_to_cpu(cmd.skip_dtim_periods));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
|
||||
iwlmvm_mod_params.power_scheme);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
|
||||
le16_to_cpu(cmd.flags));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
|
||||
cmd.keep_alive_seconds);
|
||||
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
|
||||
(cmd.flags &
|
||||
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
|
||||
1 : 0);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.rx_data_timeout));
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
|
||||
le32_to_cpu(cmd.tx_data_timeout));
|
||||
if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
|
||||
pos += scnprintf(buf+pos, bufsz-pos,
|
||||
"lprx_rssi_threshold = %d\n",
|
||||
le32_to_cpu(cmd.lprx_rssi_threshold));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct iwl_mvm_power_ops pm_legacy_ops = {
|
||||
.power_update_mode = iwl_mvm_power_legacy_update_mode,
|
||||
.power_disable = iwl_mvm_power_legacy_disable,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
.power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
|
||||
#endif
|
||||
};
|
@ -132,7 +132,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
|
||||
int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
|
||||
{
|
||||
struct iwl_time_quota_cmd cmd;
|
||||
int i, idx, ret, num_active_bindings, quota, quota_rem;
|
||||
int i, idx, ret, num_active_macs, quota, quota_rem;
|
||||
struct iwl_mvm_quota_iterator_data data = {
|
||||
.n_interfaces = {},
|
||||
.colors = { -1, -1, -1, -1 },
|
||||
@ -162,18 +162,17 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
|
||||
* IWL_MVM_MAX_QUOTA fragments. Divide these fragments
|
||||
* equally between all the bindings that require quota
|
||||
*/
|
||||
num_active_bindings = 0;
|
||||
num_active_macs = 0;
|
||||
for (i = 0; i < MAX_BINDINGS; i++) {
|
||||
cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
|
||||
if (data.n_interfaces[i] > 0)
|
||||
num_active_bindings++;
|
||||
num_active_macs += data.n_interfaces[i];
|
||||
}
|
||||
|
||||
quota = 0;
|
||||
quota_rem = 0;
|
||||
if (num_active_bindings) {
|
||||
quota = IWL_MVM_MAX_QUOTA / num_active_bindings;
|
||||
quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings;
|
||||
if (num_active_macs) {
|
||||
quota = IWL_MVM_MAX_QUOTA / num_active_macs;
|
||||
quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
|
||||
}
|
||||
|
||||
for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
|
||||
@ -187,7 +186,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
|
||||
cmd.quotas[idx].quota = cpu_to_le32(0);
|
||||
cmd.quotas[idx].max_duration = cpu_to_le32(0);
|
||||
} else {
|
||||
cmd.quotas[idx].quota = cpu_to_le32(quota);
|
||||
cmd.quotas[idx].quota =
|
||||
cpu_to_le32(quota * data.n_interfaces[i]);
|
||||
cmd.quotas[idx].max_duration =
|
||||
cpu_to_le32(IWL_MVM_MAX_QUOTA);
|
||||
}
|
||||
|
@ -2688,9 +2688,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
|
||||
lq_sta->flush_timer = 0;
|
||||
lq_sta->supp_rates = sta->supp_rates[sband->band];
|
||||
for (j = 0; j < LQ_SIZE; j++)
|
||||
for (i = 0; i < IWL_RATE_COUNT; i++)
|
||||
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
|
||||
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"LQ: *** rate scale station global init for station %d ***\n",
|
||||
@ -3194,13 +3191,14 @@ void iwl_mvm_rate_control_unregister(void)
|
||||
* iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
|
||||
* Tx protection, according to this rquest and previous requests,
|
||||
* and send the LQ command.
|
||||
* @lq: The LQ command
|
||||
* @mvmsta: The station
|
||||
* @enable: Enable Tx protection?
|
||||
*/
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
||||
struct iwl_mvm_sta *mvmsta, bool enable)
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool enable)
|
||||
{
|
||||
struct iwl_lq_cmd *lq = &mvmsta->lq_sta.lq;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (enable) {
|
||||
|
@ -404,7 +404,7 @@ extern void iwl_mvm_rate_control_unregister(void);
|
||||
|
||||
struct iwl_mvm_sta;
|
||||
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
|
||||
struct iwl_mvm_sta *mvmsta, bool enable);
|
||||
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool enable);
|
||||
|
||||
#endif /* __rs__ */
|
||||
|
@ -124,24 +124,15 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||
ieee80211_rx_ni(mvm->hw, skb);
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_mvm_calc_rssi - calculate the rssi in dBm
|
||||
* @phy_info: the phy information for the coming packet
|
||||
*/
|
||||
static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_phy_info *phy_info)
|
||||
static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_phy_info *phy_info,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
|
||||
int rssi_all_band_a, rssi_all_band_b;
|
||||
u32 agc_a, agc_b, max_agc;
|
||||
u32 val;
|
||||
|
||||
/* Find max rssi among 2 possible receivers.
|
||||
* These values are measured by the Digital Signal Processor (DSP).
|
||||
* They should stay fairly constant even as the signal strength varies,
|
||||
* if the radio's Automatic Gain Control (AGC) is working right.
|
||||
* AGC value (see below) will provide the "interesting" info.
|
||||
*/
|
||||
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
|
||||
agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
|
||||
agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
|
||||
@ -166,7 +157,45 @@ static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
|
||||
IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
|
||||
rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
|
||||
|
||||
return max_rssi_dbm;
|
||||
rx_status->signal = max_rssi_dbm;
|
||||
rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
|
||||
RX_RES_PHY_FLAGS_ANTENNA)
|
||||
>> RX_RES_PHY_FLAGS_ANTENNA_POS;
|
||||
rx_status->chain_signal[0] = rssi_a_dbm;
|
||||
rx_status->chain_signal[1] = rssi_b_dbm;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_mvm_get_signal_strength - use new rx PHY INFO API
|
||||
*/
|
||||
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_phy_info *phy_info,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
int energy_a, energy_b, energy_c, max_energy;
|
||||
u32 val;
|
||||
|
||||
val =
|
||||
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_b = -((val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
|
||||
IWL_RX_INFO_ENERGY_ANT_B_POS);
|
||||
energy_c = -((val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
|
||||
IWL_RX_INFO_ENERGY_ANT_C_POS);
|
||||
max_energy = max(energy_a, energy_b);
|
||||
max_energy = max(max_energy, energy_c);
|
||||
|
||||
IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n",
|
||||
energy_a, energy_b, energy_c, max_energy);
|
||||
|
||||
rx_status->signal = max_energy;
|
||||
rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
|
||||
RX_RES_PHY_FLAGS_ANTENNA)
|
||||
>> RX_RES_PHY_FLAGS_ANTENNA_POS;
|
||||
rx_status->chain_signal[0] = energy_a;
|
||||
rx_status->chain_signal[1] = energy_b;
|
||||
rx_status->chain_signal[2] = energy_c;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -289,29 +318,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
*/
|
||||
/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
|
||||
|
||||
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
|
||||
rx_status.signal = iwl_mvm_calc_rssi(mvm, phy_info);
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API)
|
||||
iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
|
||||
else
|
||||
iwl_mvm_calc_rssi(mvm, phy_info, &rx_status);
|
||||
|
||||
IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
|
||||
(unsigned long long)rx_status.mactime);
|
||||
|
||||
/*
|
||||
* "antenna number"
|
||||
*
|
||||
* It seems that the antenna field in the phy flags value
|
||||
* is actually a bit field. This is undefined by radiotap,
|
||||
* it wants an actual antenna number but I always get "7"
|
||||
* for most legacy frames I receive indicating that the
|
||||
* same frame was received on all three RX chains.
|
||||
*
|
||||
* I think this field should be removed in favor of a
|
||||
* new 802.11n radiotap field "RX chains" that is defined
|
||||
* as a bitmask.
|
||||
*/
|
||||
rx_status.antenna = (le16_to_cpu(phy_info->phy_flags) &
|
||||
RX_RES_PHY_FLAGS_ANTENNA)
|
||||
>> RX_RES_PHY_FLAGS_ANTENNA_POS;
|
||||
|
||||
/* set the preamble flag if appropriate */
|
||||
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
|
||||
rx_status.flag |= RX_FLAG_SHORTPRE;
|
||||
|
@ -308,10 +308,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
|
||||
*/
|
||||
if (req->n_ssids > 0) {
|
||||
cmd->passive2active = cpu_to_le16(1);
|
||||
cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE;
|
||||
ssid = req->ssids[0].ssid;
|
||||
ssid_len = req->ssids[0].ssid_len;
|
||||
} else {
|
||||
cmd->passive2active = 0;
|
||||
cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
|
||||
}
|
||||
|
||||
iwl_mvm_scan_fill_ssids(cmd, req);
|
||||
|
@ -826,8 +826,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
* method for HT traffic
|
||||
* this function also sends the LQ command
|
||||
*/
|
||||
return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
|
||||
mvmsta, true);
|
||||
return iwl_mvm_tx_protection(mvm, mvmsta, true);
|
||||
/*
|
||||
* TODO: remove the TLC_RTS flag when we tear down the last
|
||||
* AGG session (agg_tids_count in DVM)
|
||||
|
@ -391,8 +391,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
|
||||
mvmsta = (void *)sta->drv_priv;
|
||||
if (enable == mvmsta->tt_tx_protection)
|
||||
continue;
|
||||
err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
|
||||
mvmsta, enable);
|
||||
err = iwl_mvm_tx_protection(mvm, mvmsta, enable);
|
||||
if (err) {
|
||||
IWL_ERR(mvm, "Failed to %s Tx protection\n",
|
||||
enable ? "enable" : "disable");
|
||||
@ -513,12 +512,39 @@ static const struct iwl_tt_params iwl7000_tt_params = {
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
|
||||
.ct_kill_entry = 118,
|
||||
.ct_kill_exit = 96,
|
||||
.ct_kill_duration = 5,
|
||||
.dynamic_smps_entry = 114,
|
||||
.dynamic_smps_exit = 110,
|
||||
.tx_protection_entry = 114,
|
||||
.tx_protection_exit = 108,
|
||||
.tx_backoff = {
|
||||
{.temperature = 112, .backoff = 300},
|
||||
{.temperature = 113, .backoff = 800},
|
||||
{.temperature = 114, .backoff = 1500},
|
||||
{.temperature = 115, .backoff = 3000},
|
||||
{.temperature = 116, .backoff = 5000},
|
||||
{.temperature = 117, .backoff = 10000},
|
||||
},
|
||||
.support_ct_kill = true,
|
||||
.support_dynamic_smps = true,
|
||||
.support_tx_protection = true,
|
||||
.support_tx_backoff = true,
|
||||
};
|
||||
|
||||
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
|
||||
|
||||
IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
|
||||
tt->params = &iwl7000_tt_params;
|
||||
|
||||
if (mvm->cfg->high_temp)
|
||||
tt->params = &iwl7000_high_temp_tt_params;
|
||||
else
|
||||
tt->params = &iwl7000_tt_params;
|
||||
|
||||
tt->throttle = false;
|
||||
INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
|
||||
}
|
||||
|
@ -123,6 +123,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
* it
|
||||
*/
|
||||
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
|
||||
} else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
|
||||
tx_cmd->pm_frame_timeout = cpu_to_le16(2);
|
||||
} else {
|
||||
tx_cmd->pm_frame_timeout = 0;
|
||||
}
|
||||
|
@ -453,6 +453,29 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
|
||||
}
|
||||
|
||||
void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
|
||||
{
|
||||
const struct fw_img *img;
|
||||
int ofs, len = 0;
|
||||
u8 *buf;
|
||||
|
||||
if (!mvm->ucode_loaded)
|
||||
return;
|
||||
|
||||
img = &mvm->fw->img[mvm->cur_ucode];
|
||||
ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
|
||||
len = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len);
|
||||
iwl_print_hex_error(mvm->trans, buf, len);
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_send_lq_cmd() - Send link quality command
|
||||
* @init: This command is sent as part of station initialization right
|
||||
|
@ -272,9 +272,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
|
||||
|
@ -392,7 +392,6 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
|
||||
/*****************************************************
|
||||
* Error handling
|
||||
******************************************************/
|
||||
int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf);
|
||||
void iwl_pcie_dump_csr(struct iwl_trans *trans);
|
||||
|
||||
/*****************************************************
|
||||
|
@ -793,7 +793,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
iwl_pcie_dump_csr(trans);
|
||||
iwl_pcie_dump_fh(trans, NULL);
|
||||
iwl_dump_fh(trans, NULL);
|
||||
|
||||
set_bit(STATUS_FW_ERROR, &trans_pcie->status);
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
|
||||
|
@ -1033,71 +1033,6 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
|
||||
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
|
||||
}
|
||||
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
|
||||
IWL_CMD(FH_RSCSR_CHNL0_WPTR);
|
||||
IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
|
||||
IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
|
||||
IWL_CMD(FH_TSSR_TX_STATUS_REG);
|
||||
IWL_CMD(FH_TSSR_TX_ERROR_REG);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#undef IWL_CMD
|
||||
}
|
||||
|
||||
int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf)
|
||||
{
|
||||
int i;
|
||||
static const u32 fh_tbl[] = {
|
||||
FH_RSCSR_CHNL0_STTS_WPTR_REG,
|
||||
FH_RSCSR_CHNL0_RBDCB_BASE_REG,
|
||||
FH_RSCSR_CHNL0_WPTR,
|
||||
FH_MEM_RCSR_CHNL0_CONFIG_REG,
|
||||
FH_MEM_RSSR_SHARED_CTRL_REG,
|
||||
FH_MEM_RSSR_RX_STATUS_REG,
|
||||
FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
|
||||
FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_ERROR_REG
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (buf) {
|
||||
int pos = 0;
|
||||
size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
|
||||
|
||||
*buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
"FH register values:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
pos += scnprintf(*buf + pos, bufsz - pos,
|
||||
" %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
IWL_ERR(trans, "FH register values:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
|
||||
IWL_ERR(trans, " %34s: 0X%08x\n",
|
||||
get_fh_string(fh_tbl[i]),
|
||||
iwl_read_direct32(trans, fh_tbl[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_csr_string(int cmd)
|
||||
{
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
@ -1178,18 +1113,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans)
|
||||
} while (0)
|
||||
|
||||
/* file operation */
|
||||
#define DEBUGFS_READ_FUNC(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_WRITE_FUNC(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_READ_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
.open = simple_open, \
|
||||
@ -1197,7 +1121,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
};
|
||||
|
||||
#define DEBUGFS_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.open = simple_open, \
|
||||
@ -1205,8 +1128,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
};
|
||||
|
||||
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
@ -1390,7 +1311,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
|
||||
int pos = 0;
|
||||
ssize_t ret = -EFAULT;
|
||||
|
||||
ret = pos = iwl_pcie_dump_fh(trans, &buf);
|
||||
ret = pos = iwl_dump_fh(trans, &buf);
|
||||
if (buf) {
|
||||
ret = simple_read_from_buffer(user_buf,
|
||||
count, ppos, buf, pos);
|
||||
@ -1497,10 +1418,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
spin_lock_init(&trans_pcie->reg_lock);
|
||||
init_waitqueue_head(&trans_pcie->ucode_write_waitq);
|
||||
|
||||
/* W/A - seems to solve weird behavior. We need to remove this if we
|
||||
* don't want to stay in L1 all the time. This wastes a lot of power */
|
||||
pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
|
||||
PCIE_LINK_STATE_CLKPM);
|
||||
if (!cfg->base_params->pcie_l1_allowed) {
|
||||
/*
|
||||
* W/A - seems to solve weird behavior. We need to remove this
|
||||
* if we don't want to stay in L1 all the time. This wastes a
|
||||
* lot of power.
|
||||
*/
|
||||
pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
|
||||
PCIE_LINK_STATE_L1 |
|
||||
PCIE_LINK_STATE_CLKPM);
|
||||
}
|
||||
|
||||
if (pci_enable_device(pdev)) {
|
||||
err = -ENODEV;
|
||||
|
@ -1619,10 +1619,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
txq = &trans_pcie->txq[txq_id];
|
||||
q = &txq->q;
|
||||
|
||||
if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
|
||||
WARN_ON_ONCE(1);
|
||||
if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
|
||||
"TX on unused queue %d\n", txq_id))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user