summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c177
1 files changed, 59 insertions, 118 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index af6644b7e95f..0f056a6641bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -70,7 +70,7 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
};
static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
- .max_peers = IWL_MVM_TOF_MAX_APS,
+ .max_peers = IWL_TOF_MAX_APS,
.report_ap_tsf = 1,
.randomize_mac_addr = 1,
@@ -146,7 +146,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
MCC_UPDATE_CMD, 0);
IWL_DEBUG_LAR(mvm, "MCC update response version: %d\n", resp_ver);
- regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
+ regd = iwl_parse_nvm_mcc_info(mvm->trans,
__le32_to_cpu(resp->n_channels),
resp->channels,
__le16_to_cpu(resp->mcc),
@@ -272,9 +272,10 @@ static const u8 tm_if_types_ext_capa_sta[] = {
__bf_shf(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY) | \
IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US << \
__bf_shf(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY))
-#define IWL_MVM_MLD_CAPA_OPS FIELD_PREP_CONST( \
+#define IWL_MVM_MLD_CAPA_OPS (FIELD_PREP_CONST( \
IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP, \
- IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME)
+ IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME) | \
+ IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT)
static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
{
@@ -310,8 +311,8 @@ int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/* This has been tested on those devices only */
- if (mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
- mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22000)
+ if (mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_9000 &&
+ mvm->trans->mac_cfg->device_family != IWL_DEVICE_FAMILY_22000)
return -EOPNOTSUPP;
if (!mvm->nvm_data)
@@ -390,7 +391,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
* for older devices. We also don't see this issue on any newer
* devices.
*/
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
@@ -401,7 +402,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
/* We want to use the mac80211's reorder buffer for 9000 */
if (iwl_mvm_has_new_rx_api(mvm) &&
- mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_9000)
+ mvm->trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
if (fw_has_capa(&mvm->fw->ucode_capa,
@@ -416,10 +417,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
return -EINVAL;
}
- if (mvm->trans->num_rx_queues > 1)
+ if (mvm->trans->info.num_rxqs > 1)
ieee80211_hw_set(hw, USES_RSS);
- if (mvm->trans->max_skb_frags)
+ if (mvm->trans->info.max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->queues = IEEE80211_NUM_ACS;
@@ -440,7 +441,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
- hw->max_tx_fragments = mvm->trans->max_skb_frags;
+ hw->max_tx_fragments = mvm->trans->info.max_skb_frags;
BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 6);
memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers));
@@ -543,7 +544,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
REGULATORY_DISABLE_BEACON_HINTS;
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+ if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_DFS_CONCURRENT);
@@ -609,7 +610,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->bands[NL80211_BAND_6GHZ] =
&mvm->nvm_data->bands[NL80211_BAND_6GHZ];
- hw->wiphy->hw_version = mvm->trans->hw_id;
+ hw->wiphy->hw_version = mvm->trans->info.hw_id;
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -730,8 +731,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
- ieee80211_hw_set(hw, DISALLOW_PUNCTURING_5GHZ);
-
#ifdef CONFIG_PM_SLEEP
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
device_can_wakeup(mvm->trans->dev)) {
@@ -770,7 +769,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
}
- hw->netdev_features |= mvm->cfg->features;
+ hw->netdev_features |= mvm->trans->mac_cfg->base->features;
if (!iwl_mvm_is_csum_supported(mvm))
hw->netdev_features &= ~IWL_CSUM_NETIF_FLAGS_MASK;
@@ -1378,7 +1377,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend)
iwl_mvm_rm_aux_sta(mvm);
if (suspend &&
- mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
iwl_mvm_fast_suspend(mvm);
/* From this point on, we won't touch the device */
iwl_mvm_mei_device_state(mvm, false);
@@ -1987,15 +1986,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
* interface is be handled as part of the stop_ap flow.
*/
if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC) {
-#ifdef CONFIG_NL80211_TESTMODE
- if (vif == mvm->noa_vif) {
- mvm->noa_vif = NULL;
- mvm->noa_duration = 0;
- }
-#endif
+ vif->type == NL80211_IFTYPE_ADHOC)
goto out;
- }
iwl_mvm_power_update_mac(mvm);
@@ -3058,7 +3050,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
* context. For the newer, the beacon is a resource that belongs to a
* MAC, so need to send beacon template after adding the mac.
*/
- if (mvm->trans->trans_cfg->device_family > IWL_DEVICE_FAMILY_22000) {
+ if (mvm->trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_22000) {
/* Add the mac context */
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
@@ -4099,6 +4091,21 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
return 0;
}
+void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ bool update)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ if (!iwl_mvm_has_rlc_offload(mvm) ||
+ iwl_fw_lookup_cmd_ver(mvm->fw, MAC_PM_POWER_TABLE, 0) >= 2)
+ return;
+
+ mvmvif->ps_disabled = !vif->cfg.ps;
+
+ if (update)
+ iwl_mvm_power_update_mac(mvm);
+}
+
/* Common part for MLD and non-MLD modes */
int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -4191,6 +4198,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_AUTHORIZED) {
ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta,
callbacks);
+ iwl_mvm_smps_workaround(mvm, vif, true);
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta,
@@ -4379,7 +4387,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
- if (!mvm->trans->trans_cfg->gen2) {
+ if (!mvm->trans->mac_cfg->gen2) {
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
} else if (vif->type == NL80211_IFTYPE_STATION) {
@@ -4496,7 +4504,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
WARN_ON(rcu_access_pointer(mvmsta->ptk_pn[keyidx]));
ptk_pn = kzalloc(struct_size(ptk_pn, q,
- mvm->trans->num_rx_queues),
+ mvm->trans->info.num_rxqs),
GFP_KERNEL);
if (!ptk_pn) {
ret = -ENOMEM;
@@ -4505,7 +4513,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
ieee80211_get_key_rx_seq(key, tid, &seq);
- for (q = 0; q < mvm->trans->num_rx_queues; q++)
+ for (q = 0; q < mvm->trans->info.num_rxqs; q++)
memcpy(ptk_pn->q[q].pn[tid],
seq.ccmp.pn,
IEEE80211_CCMP_PN_LEN);
@@ -5509,70 +5517,6 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
&mvm_sta->vif->bss_conf);
}
-#ifdef CONFIG_NL80211_TESTMODE
-static const struct nla_policy iwl_mvm_tm_policy[IWL_MVM_TM_ATTR_MAX + 1] = {
- [IWL_MVM_TM_ATTR_CMD] = { .type = NLA_U32 },
- [IWL_MVM_TM_ATTR_NOA_DURATION] = { .type = NLA_U32 },
- [IWL_MVM_TM_ATTR_BEACON_FILTER_STATE] = { .type = NLA_U32 },
-};
-
-static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- void *data, int len)
-{
- struct nlattr *tb[IWL_MVM_TM_ATTR_MAX + 1];
- int err;
- u32 noa_duration;
-
- err = nla_parse_deprecated(tb, IWL_MVM_TM_ATTR_MAX, data, len,
- iwl_mvm_tm_policy, NULL);
- if (err)
- return err;
-
- if (!tb[IWL_MVM_TM_ATTR_CMD])
- return -EINVAL;
-
- switch (nla_get_u32(tb[IWL_MVM_TM_ATTR_CMD])) {
- case IWL_MVM_TM_CMD_SET_NOA:
- if (!vif || vif->type != NL80211_IFTYPE_AP || !vif->p2p ||
- !vif->bss_conf.enable_beacon ||
- !tb[IWL_MVM_TM_ATTR_NOA_DURATION])
- return -EINVAL;
-
- noa_duration = nla_get_u32(tb[IWL_MVM_TM_ATTR_NOA_DURATION]);
- if (noa_duration >= vif->bss_conf.beacon_int)
- return -EINVAL;
-
- mvm->noa_duration = noa_duration;
- mvm->noa_vif = vif;
-
- return iwl_mvm_update_quotas(mvm, true, NULL);
- case IWL_MVM_TM_CMD_SET_BEACON_FILTER:
- /* must be associated client vif - ignore authorized */
- if (!vif || vif->type != NL80211_IFTYPE_STATION ||
- !vif->cfg.assoc || !vif->bss_conf.dtim_period ||
- !tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])
- return -EINVAL;
-
- if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]))
- return iwl_mvm_enable_beacon_filter(mvm, vif);
- return iwl_mvm_disable_beacon_filter(mvm, vif);
- }
-
- return -EOPNOTSUPP;
-}
-
-int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- void *data, int len)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-
- guard(mvm)(mvm);
- return __iwl_mvm_mac_testmode_cmd(mvm, vif, data, len);
-}
-#endif
-
void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
{
@@ -6124,12 +6068,12 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
break;
}
- if (format == RATE_MCS_CCK_MSK ||
- format == RATE_MCS_LEGACY_OFDM_MSK) {
+ if (format == RATE_MCS_MOD_TYPE_CCK ||
+ format == RATE_MCS_MOD_TYPE_LEGACY_OFDM) {
int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK);
/* add the offset needed to get to the legacy ofdm indices */
- if (format == RATE_MCS_LEGACY_OFDM_MSK)
+ if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
rate += IWL_FIRST_OFDM_RATE;
switch (rate) {
@@ -6174,7 +6118,7 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
rinfo->nss = u32_get_bits(rate_n_flags,
RATE_MCS_NSS_MSK) + 1;
- rinfo->mcs = format == RATE_MCS_HT_MSK ?
+ rinfo->mcs = format == RATE_MCS_MOD_TYPE_HT ?
RATE_HT_MCS_INDEX(rate_n_flags) :
u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK);
@@ -6182,11 +6126,11 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
switch (format) {
- case RATE_MCS_EHT_MSK:
+ case RATE_MCS_MOD_TYPE_EHT:
/* TODO: GI/LTF/RU. How does the firmware encode them? */
rinfo->flags |= RATE_INFO_FLAGS_EHT_MCS;
break;
- case RATE_MCS_HE_MSK:
+ case RATE_MCS_MOD_TYPE_HE:
gi_ltf = u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK);
rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
@@ -6227,10 +6171,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
rinfo->he_dcm = 1;
break;
- case RATE_MCS_HT_MSK:
+ case RATE_MCS_MOD_TYPE_HT:
rinfo->flags |= RATE_INFO_FLAGS_MCS;
break;
- case RATE_MCS_VHT_MSK:
+ case RATE_MCS_MOD_TYPE_VHT:
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
break;
}
@@ -6410,17 +6354,10 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
bool sync,
const void *data, u32 size)
{
- struct {
- struct iwl_rxq_sync_cmd cmd;
- struct iwl_mvm_internal_rxq_notif notif;
- } __packed cmd = {
- .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1),
- .cmd.count =
- cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
- size),
- .notif.type = type,
- .notif.sync = sync,
- };
+ DEFINE_RAW_FLEX(struct iwl_rxq_sync_cmd, cmd, payload,
+ sizeof(struct iwl_mvm_internal_rxq_notif));
+ struct iwl_mvm_internal_rxq_notif *notif =
+ (struct iwl_mvm_internal_rxq_notif *)cmd->payload;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
.data[0] = &cmd,
@@ -6431,16 +6368,22 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
};
int ret;
+ cmd->rxq_mask = cpu_to_le32(BIT(mvm->trans->info.num_rxqs) - 1);
+ cmd->count = cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) +
+ size);
+ notif->type = type;
+ notif->sync = sync;
+
/* size must be a multiple of DWORD */
- if (WARN_ON(cmd.cmd.count & cpu_to_le32(3)))
+ if (WARN_ON(cmd->count & cpu_to_le32(3)))
return;
if (!iwl_mvm_has_new_rx_api(mvm))
return;
if (sync) {
- cmd.notif.cookie = mvm->queue_sync_cookie;
- mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
+ notif->cookie = mvm->queue_sync_cookie;
+ mvm->queue_sync_state = (1 << mvm->trans->info.num_rxqs) - 1;
}
ret = iwl_mvm_send_cmd(mvm, &hcmd);
@@ -6633,8 +6576,6 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.sync_rx_queues = iwl_mvm_sync_rx_queues,
- CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
-
#ifdef CONFIG_PM_SLEEP
/* look at d3.c */
.suspend = iwl_mvm_suspend,