mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
wifi: iwlwifi: mld: support NPCA capability for UHR devices
UHR devices have NPCA capability, so implement the necessary configuration and set the capability bit. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Link: https://patch.msgid.link/20260513084215.8c88bf84af91.If59ceaa49c2431e08941bcba3b2e75bb93aaad63@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
This commit is contained in:
committed by
Miri Korenblit
parent
ba3b38d38a
commit
7f7a450ed8
@@ -549,12 +549,14 @@ enum iwl_link_ctx_protection_flags {
|
||||
* radar pulses).
|
||||
* @LINK_FLG_NDP_FEEDBACK_ENABLED: mark support for NDP feedback and change
|
||||
* of threshold
|
||||
* @LINK_FLG_NPCA: NPCA enabled
|
||||
*/
|
||||
enum iwl_link_ctx_flags {
|
||||
LINK_FLG_BSS_COLOR_DIS = BIT(0),
|
||||
LINK_FLG_MU_EDCA_CW = BIT(1),
|
||||
LINK_FLG_RU_2MHZ_BLOCK = BIT(2),
|
||||
LINK_FLG_NDP_FEEDBACK_ENABLED = BIT(3),
|
||||
LINK_FLG_NPCA = BIT(4),
|
||||
}; /* LINK_CONTEXT_FLAG_E_VER_1 */
|
||||
|
||||
/**
|
||||
@@ -591,7 +593,7 @@ enum iwl_npca_flags {
|
||||
* @initial_qsrc: Indicates the value that is used to initialize the
|
||||
* EDCAF QSRC[AC] variables
|
||||
* @min_dur_threshold: minimum PPDU time to switch to the non-primary
|
||||
* NPCA channel (usec)
|
||||
* NPCA channel (spec representation)
|
||||
* @flags: NPCA flags, see &enum iwl_npca_flags
|
||||
* @reserved: reserved for alignment purposes
|
||||
*/
|
||||
|
||||
@@ -695,6 +695,9 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = {
|
||||
.has_uhr = true,
|
||||
.phy.cap = IEEE80211_UHR_PHY_CAP_ELR_RX |
|
||||
IEEE80211_UHR_PHY_CAP_ELR_TX,
|
||||
.mac.mac_cap = {
|
||||
[0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -374,6 +374,21 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
|
||||
if (WARN_ON(changes & LINK_CONTEXT_MODIFY_EHT_PARAMS))
|
||||
changes &= ~LINK_CONTEXT_MODIFY_EHT_PARAMS;
|
||||
|
||||
if (link->uhr_support && link->npca.enabled) {
|
||||
flags |= LINK_FLG_NPCA;
|
||||
if (link->npca.moplen)
|
||||
cmd.npca_params.flags |= IWL_NPCA_FLAG_MAC_HDR_BASED;
|
||||
cmd.npca_params.dis_subch_bmap =
|
||||
cpu_to_le16(link->chanreq.oper.npca_punctured);
|
||||
cmd.npca_params.initial_qsrc = link->npca.init_qsrc;
|
||||
cmd.npca_params.min_dur_threshold = link->npca.min_dur_thresh;
|
||||
/* spec/mac80211 have these in units of 4 usec */
|
||||
cmd.npca_params.switch_delay =
|
||||
4 * link->npca.switch_delay;
|
||||
cmd.npca_params.switch_back_delay =
|
||||
4 * link->npca.switch_back_delay;
|
||||
}
|
||||
|
||||
send_cmd:
|
||||
cmd.modify_mask = cpu_to_le32(changes);
|
||||
cmd.flags = cpu_to_le32(flags);
|
||||
|
||||
@@ -981,6 +981,30 @@ void iwl_mld_remove_chanctx(struct ieee80211_hw *hw,
|
||||
mld->used_phy_ids &= ~BIT(phy->fw_id);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_update_link_npca_puncturing(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
for_each_active_interface(vif, hw) {
|
||||
struct ieee80211_bss_conf *link;
|
||||
int link_id;
|
||||
|
||||
for_each_vif_active_link(vif, link, link_id) {
|
||||
if (rcu_access_pointer(link->chanctx_conf) != ctx)
|
||||
continue;
|
||||
|
||||
if (!link->npca.enabled)
|
||||
continue;
|
||||
|
||||
iwl_mld_change_link_in_fw(mld, link,
|
||||
LINK_CONTEXT_MODIFY_UHR_PARAMS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void iwl_mld_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx, u32 changed)
|
||||
@@ -996,9 +1020,19 @@ void iwl_mld_change_chanctx(struct ieee80211_hw *hw,
|
||||
IEEE80211_CHANCTX_CHANGE_CHANNEL)))
|
||||
return;
|
||||
|
||||
/* NPCA puncturing is in link API for FW */
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_NPCA_PUNCT) {
|
||||
iwl_mld_update_link_npca_puncturing(hw, ctx);
|
||||
changed &= ~IEEE80211_CHANCTX_CHANGE_NPCA_PUNCT;
|
||||
}
|
||||
|
||||
/* Check if a FW update is required */
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_AP)
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_AP ||
|
||||
changed & IEEE80211_CHANCTX_CHANGE_NPCA)
|
||||
goto update;
|
||||
|
||||
if (chandef->chan == phy->chandef.chan &&
|
||||
@@ -1255,6 +1289,9 @@ u32 iwl_mld_link_changed_mapping(struct iwl_mld *mld,
|
||||
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_NPCA)
|
||||
link_changes |= LINK_CONTEXT_MODIFY_UHR_PARAMS;
|
||||
|
||||
return link_changes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
* Copyright (C) 2024-2026 Intel Corporation
|
||||
*/
|
||||
#include <net/mac80211.h>
|
||||
|
||||
@@ -99,9 +99,9 @@ iwl_mld_nl80211_width_to_fw(enum nl80211_chan_width width)
|
||||
/* Maps the driver specific control channel position (relative to the center
|
||||
* freq) definitions to the fw values
|
||||
*/
|
||||
u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef)
|
||||
static u8 _iwl_mld_get_fw_ctrl_pos(u32 control, u32 cf1)
|
||||
{
|
||||
int offs = chandef->chan->center_freq - chandef->center_freq1;
|
||||
int offs = control - cf1;
|
||||
int abs_offs = abs(offs);
|
||||
u8 ret;
|
||||
|
||||
@@ -127,6 +127,12 @@ u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef)
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
return _iwl_mld_get_fw_ctrl_pos(chandef->chan->center_freq,
|
||||
chandef->center_freq1);
|
||||
}
|
||||
|
||||
int iwl_mld_phy_fw_action(struct iwl_mld *mld,
|
||||
struct ieee80211_chanctx_conf *ctx, u32 action)
|
||||
{
|
||||
@@ -150,6 +156,18 @@ int iwl_mld_phy_fw_action(struct iwl_mld *mld,
|
||||
cmd.sbb_ctrl_channel_loc = iwl_mld_get_fw_ctrl_pos(&ctx->ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set NPCA channel if NPCA is used; if not used, just set it to an
|
||||
* arbitrary channel on the other side to help firmware.
|
||||
*/
|
||||
if (chandef->npca_chan)
|
||||
cmd.secondary_ctrl_chnl_loc =
|
||||
_iwl_mld_get_fw_ctrl_pos(chandef->npca_chan->center_freq,
|
||||
chandef->center_freq1);
|
||||
else
|
||||
cmd.secondary_ctrl_chnl_loc =
|
||||
cmd.ci.ctrl_pos ^ IWL_PHY_CTRL_POS_ABOVE;
|
||||
|
||||
ret = iwl_mld_send_cmd_pdu(mld, PHY_CONTEXT_CMD, &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mld, "Failed to send PHY_CONTEXT_CMD ret = %d\n", ret);
|
||||
|
||||
Reference in New Issue
Block a user