@@ -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);
@@ -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,
@@ -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 */
@@ -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;