]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: iwlwifi: Enable channel puncturing for US/CAN from bios
authorSomashekhar(Som) <somashekhar.puttagangaiah@intel.com>
Mon, 29 Jul 2024 17:20:17 +0000 (20:20 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 27 Aug 2024 08:15:15 +0000 (10:15 +0200)
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>
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c

index 560a91998cc488fef33ec39ae0ff378f216bc314..4d9a1f83ef8c2d2601b8893dd10e7e2d5dfea922 100644 (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);
index e2c056f483c1c70980d62a70c811ccba33ba28e5..c2209948b4c01b95a02c1790c5c7a04328b1a354 100644 (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__ */
index fb982d4fe85100973be4ac1a87b0c7f7184599f3..754fc5014fbf621879194daed0121936fb527b6a 100644 (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);
index 1f8884ca8997c4476bb9b3276e671163058b2b2f..0b24771900704f85e3dbd860b300bce968147562 100644 (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__ */
index f48f445e006c11f9e14891b948943cb71b2f021a..d6f4caa939bd7841708b15c0b71d0f3f4acf923a 100644 (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);
index 9cb7045cc0ba9e280b65a5e731354cb91fca93bc..bd754b8a71fc1807a4c5c658a132ffaca8c3fce9 100644 (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 */
index 279c9230742080cbe80fb3344ba61083b08dff49..8896d9792feb295e2a728413dc19f5be45e1a40d 100644 (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)) {
                /*