1

wifi: iwlwifi: Enable channel puncturing for US/CAN from bios

Add support for enabling channel puncturing for US/CAN based
on BIOS configuration through UEFI

Signed-off-by: Somashekhar(Som) <somashekhar.puttagangaiah@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20240729201718.828f3ecf5118.I5561ab8c7cd48ad4e5d6daf21b037bf88c619a4a@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Somashekhar(Som) 2024-07-29 20:20:17 +03:00 committed by Johannes Berg
parent db9979d5aa
commit b312e35720
7 changed files with 79 additions and 6 deletions

View File

@ -634,3 +634,19 @@ int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
GET_BIOS_TABLE(dsm, fwrt, func, value);
}
IWL_EXPORT_SYMBOL(iwl_bios_get_dsm);
bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc)
{
/* Some kind of regulatory mess means we need to currently disallow
* puncturing in the US and Canada unless enabled in BIOS.
*/
switch (mcc) {
case IWL_MCC_US:
return puncturing & IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK;
case IWL_MCC_CANADA:
return puncturing & IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK;
default:
return true;
}
}
IWL_EXPORT_SYMBOL(iwl_puncturing_is_allowed_in_bios);

View File

@ -217,4 +217,6 @@ static inline u32 iwl_bios_get_ppag_flags(const u32 ppag_modes,
return ppag_modes & (ppag_ver < 3 ? IWL_PPAG_ETSI_CHINA_MASK :
IWL_PPAG_REV3_MASK);
}
bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
#endif /* __fw_regulatory_h__ */

View File

@ -729,3 +729,32 @@ out:
kfree(data);
return ret;
}
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
{
struct uefi_cnv_var_puncturing_data *data;
/* default value is not enabled if there is any issue in reading
* uefi variable or revision is not supported
*/
int puncturing = 0;
data = iwl_uefi_get_verified_variable(fwrt->trans,
IWL_UEFI_PUNCTURING_NAME,
"UefiCnvWlanPuncturing",
sizeof(*data), NULL);
if (IS_ERR(data))
return puncturing;
if (data->revision != IWL_UEFI_PUNCTURING_REVISION) {
IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PUNCTURING rev:%d\n",
data->revision);
} else {
puncturing = data->puncturing & IWL_UEFI_PUNCTURING_REV0_MASK;
IWL_DEBUG_RADIO(fwrt, "Loaded puncturing bits from UEFI: %d\n",
puncturing);
}
kfree(data);
return puncturing;
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_puncturing);

View File

@ -22,6 +22,7 @@
#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV"
#define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg"
#define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM"
#define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing"
#define IWL_SGOM_MAP_SIZE 339
@ -38,6 +39,7 @@
#define IWL_UEFI_ECKV_REVISION 0
#define IWL_UEFI_WBEM_REVISION 0
#define IWL_UEFI_DSM_REVISION 4
#define IWL_UEFI_PUNCTURING_REVISION 0
struct pnvm_sku_package {
u8 rev;
@ -194,6 +196,25 @@ struct uefi_cnv_wlan_wbem_data {
u32 wbem_320mhz_per_mcc;
} __packed;
enum iwl_uefi_cnv_puncturing_flags {
IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK = BIT(0),
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK = BIT(1),
};
#define IWL_UEFI_PUNCTURING_REV0_MASK (IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK | \
IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK)
/**
* struct uefi_cnv_var_puncturing_data - controlling channel
* puncturing for few countries.
* @revision: the revision of the table
* @puncturing: enablement of channel puncturing per mcc
* see &enum iwl_uefi_cnv_puncturing_flags.
*/
struct uefi_cnv_var_puncturing_data {
u8 revision;
u32 puncturing;
} __packed;
/*
* This is known to be broken on v4.19 and to work on v5.4. Until we
* figure out why this is the case and how to make it work, simply
@ -224,6 +245,7 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
int iwl_uefi_get_uats_table(struct iwl_trans *trans,
struct iwl_fw_runtime *fwrt);
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
#else /* CONFIG_EFI */
static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
@ -320,5 +342,11 @@ int iwl_uefi_get_uats_table(struct iwl_trans *trans,
{
return 0;
}
static inline
int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt)
{
return 0;
}
#endif /* CONFIG_EFI */
#endif /* __iwl_fw_uefi__ */

View File

@ -165,12 +165,8 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
mvm->lar_regdom_set = true;
mvm->mcc_src = src_id;
/* Some kind of regulatory mess means we need to currently disallow
* puncturing in the US and Canada. Do that here, at least until we
* figure out the new chanctx APIs for puncturing.
*/
if (resp->mcc == cpu_to_le16(IWL_MCC_US) ||
resp->mcc == cpu_to_le16(IWL_MCC_CANADA))
if (!iwl_puncturing_is_allowed_in_bios(mvm->bios_enable_puncturing,
le16_to_cpu(resp->mcc)))
ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING);
else
__clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags);

View File

@ -1368,6 +1368,7 @@ struct iwl_mvm {
struct iwl_mvm_acs_survey *acs_survey;
bool statistics_clear;
u32 bios_enable_puncturing;
};
/* Extract MVM priv from op_mode and _hw */

View File

@ -1296,6 +1296,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0;
mvm->bios_enable_puncturing = iwl_uefi_get_puncturing(&mvm->fwrt);
if (iwl_mvm_has_new_tx_api(mvm)) {
/*