Search Linux Wireless

[PATCH 10/13] wifi: iwlwifi: Separate reading and parsing of reduce power table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Alon Giladi <alon.giladi@xxxxxxxxx>

It enables to better handle error cases. Also save the image till the
end of the loading and only then free it.

Signed-off-by: Alon Giladi <alon.giladi@xxxxxxxxx>
Signed-off-by: Gregory Greenman <gregory.greenman@xxxxxxxxx>
---
 drivers/net/wireless/intel/iwlwifi/fw/pnvm.c  | 40 ++++++++++++-------
 drivers/net/wireless/intel/iwlwifi/fw/uefi.c  | 31 +++++++-------
 drivers/net/wireless/intel/iwlwifi/fw/uefi.h  | 27 ++++++++-----
 .../net/wireless/intel/iwlwifi/iwl-trans.h    |  2 +
 4 files changed, 58 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index b556abece896..3b5a3c89fedf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -319,29 +319,39 @@ int iwl_pnvm_load(struct iwl_trans *trans,
 
 reduce_tables:
 	/* now try to get the reduce power table, if not loaded yet */
+	if (trans->failed_to_load_reduce_power_image)
+		goto notification;
+
 	if (!trans->reduce_power_loaded) {
 		memset(&pnvm_data, 0, sizeof(pnvm_data));
-		ret = iwl_uefi_get_reduced_power(trans, &pnvm_data);
+		data = iwl_uefi_get_reduced_power(trans, &length);
+		if (IS_ERR(data)) {
+			ret = PTR_ERR(data);
+			trans->failed_to_load_reduce_power_image = true;
+			goto notification;
+		}
+
+		ret = iwl_uefi_reduce_power_parse(trans, data, length,
+						  &pnvm_data);
 		if (ret) {
-			/*
-			 * Pretend we've loaded it - at least we've tried and
-			 * couldn't load it at all, so there's no point in
-			 * trying again over and over.
-			 */
-			trans->reduce_power_loaded = true;
-		} else {
-			ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa);
-			if (ret) {
-				IWL_DEBUG_FW(trans,
-					     "Failed to load reduce power table %d\n",
-					     ret);
-				trans->reduce_power_loaded = true;
-			}
+			trans->failed_to_load_reduce_power_image = true;
 			kfree(data);
+			goto notification;
+		}
+
+		ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa);
+		kfree(data);
+		if (ret) {
+			IWL_DEBUG_FW(trans,
+				     "Failed to load reduce power table %d\n",
+				     ret);
+			trans->failed_to_load_reduce_power_image = true;
+			goto notification;
 		}
 	}
 	iwl_trans_set_reduce_power(trans, capa);
 
+notification:
 	iwl_init_notification_wait(notif_wait, &pnvm_wait,
 				   ntf_cmds, ARRAY_SIZE(ntf_cmds),
 				   iwl_pnvm_complete_fn, trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 64b45a5b767e..1666ef3a482e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
  */
 
 #include "iwl-drv.h"
@@ -123,9 +123,9 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
 	return 0;
 }
 
-static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
-				       const u8 *data, size_t len,
-				       struct iwl_pnvm_image *pnvm_data)
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+				const u8 *data, size_t len,
+				struct iwl_pnvm_image *pnvm_data)
 {
 	const struct iwl_ucode_tlv *tlv;
 
@@ -181,17 +181,15 @@ static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
 	return -ENOENT;
 }
 
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-			       struct iwl_pnvm_image *pnvm_data)
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
 {
 	struct pnvm_sku_package *package;
 	unsigned long package_size;
 	efi_status_t status;
-	int ret;
-	size_t len = 0;
+	u8 *data;
 
 	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	/*
 	 * TODO: we hardcode a maximum length here, because reading
@@ -202,7 +200,7 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
 
 	package = kmalloc(package_size, GFP_KERNEL);
 	if (!package)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
 				  NULL, &package_size, package);
@@ -211,23 +209,22 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
 			     "Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
 			     status, package_size);
 		kfree(package);
-		return -ENOENT;
+		return ERR_PTR(-ENOENT);
 	}
 
 	IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
 		     package_size);
-	len = package_size;
 
 	IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
 		     package->rev, package->total_size, package->n_skus);
 
-	ret = iwl_uefi_reduce_power_parse(trans, package->data,
-					  len - sizeof(*package),
-					  pnvm_data);
-
+	*len = package_size - sizeof(*package);
+	data = kmemdup(package->data, *len, GFP_KERNEL);
+	if (!data)
+		return ERR_PTR(-ENOMEM);
 	kfree(package);
 
-	return ret;
+	return data;
 }
 
 static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index 03176f73151a..10bed372e67c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
  */
 #ifndef __iwl_fw_uefi__
 #define __iwl_fw_uefi__
@@ -50,25 +50,32 @@ struct uefi_cnv_common_step_data {
  */
 #ifdef CONFIG_EFI
 void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-			       struct iwl_pnvm_image *pnvm_data);
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+				const u8 *data, size_t len,
+				struct iwl_pnvm_image *pnvm_data);
 void iwl_uefi_get_step_table(struct iwl_trans *trans);
 #else /* CONFIG_EFI */
-static inline
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
 	return ERR_PTR(-EOPNOTSUPP);
 }
 
-static inline
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-			       struct iwl_pnvm_image *pnvm_data)
+static inline int
+iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+			    const u8 *data, size_t len,
+			    struct iwl_pnvm_image *pnvm_data)
 {
 	return -EOPNOTSUPP;
 }
 
-static inline
-void iwl_uefi_get_step_table(struct iwl_trans *trans)
+static inline u8 *
+iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void iwl_uefi_get_step_table(struct iwl_trans *trans)
 {
 }
 #endif /* CONFIG_EFI */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 61ee6c1f4a1e..2915f9b2534c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -1047,6 +1047,7 @@ struct iwl_trans_txqs {
  * @pm_support: set to true in start_hw if link pm is supported
  * @ltr_enabled: set to true if the LTR is enabled
  * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
+ * @failed_to_load_reduce_power_image: set to true if pnvm loading failed
  * @wide_cmd_header: true when ucode supports wide command header format
  * @wait_command_queue: wait queue for sync commands
  * @num_rx_queues: number of RX queues allocated by the transport;
@@ -1096,6 +1097,7 @@ struct iwl_trans {
 	u8 pnvm_loaded:1;
 	u8 fail_to_parse_pnvm_image:1;
 	u8 reduce_power_loaded:1;
+	u8 failed_to_load_reduce_power_image:1;
 
 	const struct iwl_hcmd_arr *command_groups;
 	int command_groups_size;
-- 
2.38.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux