Commit 380bf72d authored by Alon Giladi's avatar Alon Giladi Committed by Johannes Berg

wifi: iwlwifi: Separate reading and parsing of reduce power table

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: default avatarAlon Giladi <alon.giladi@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230606103519.71e3b3e0e794.Ifbe69ad99a7e805eb70e09280365821eb146b1c9@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7c9c8477
...@@ -319,29 +319,39 @@ int iwl_pnvm_load(struct iwl_trans *trans, ...@@ -319,29 +319,39 @@ int iwl_pnvm_load(struct iwl_trans *trans,
reduce_tables: reduce_tables:
/* now try to get the reduce power table, if not loaded yet */ /* 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) { if (!trans->reduce_power_loaded) {
memset(&pnvm_data, 0, sizeof(pnvm_data)); 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) { if (ret) {
/* trans->failed_to_load_reduce_power_image = true;
* 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;
}
kfree(data); 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); iwl_trans_set_reduce_power(trans, capa);
notification:
iwl_init_notification_wait(notif_wait, &pnvm_wait, iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds), ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, trans); iwl_pnvm_complete_fn, trans);
......
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause // 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" #include "iwl-drv.h"
...@@ -123,9 +123,9 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -123,9 +123,9 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
return 0; return 0;
} }
static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
const u8 *data, size_t len, const u8 *data, size_t len,
struct iwl_pnvm_image *pnvm_data) struct iwl_pnvm_image *pnvm_data)
{ {
const struct iwl_ucode_tlv *tlv; const struct iwl_ucode_tlv *tlv;
...@@ -181,17 +181,15 @@ static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, ...@@ -181,17 +181,15 @@ static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
return -ENOENT; return -ENOENT;
} }
int iwl_uefi_get_reduced_power(struct iwl_trans *trans, u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
struct iwl_pnvm_image *pnvm_data)
{ {
struct pnvm_sku_package *package; struct pnvm_sku_package *package;
unsigned long package_size; unsigned long package_size;
efi_status_t status; efi_status_t status;
int ret; u8 *data;
size_t len = 0;
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 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 * TODO: we hardcode a maximum length here, because reading
...@@ -202,7 +200,7 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans, ...@@ -202,7 +200,7 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
package = kmalloc(package_size, GFP_KERNEL); package = kmalloc(package_size, GFP_KERNEL);
if (!package) if (!package)
return -ENOMEM; return ERR_PTR(-ENOMEM);
status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
NULL, &package_size, package); NULL, &package_size, package);
...@@ -211,23 +209,22 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans, ...@@ -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", "Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
status, package_size); status, package_size);
kfree(package); kfree(package);
return -ENOENT; return ERR_PTR(-ENOENT);
} }
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
package_size); package_size);
len = package_size;
IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
package->rev, package->total_size, package->n_skus); package->rev, package->total_size, package->n_skus);
ret = iwl_uefi_reduce_power_parse(trans, package->data, *len = package_size - sizeof(*package);
len - sizeof(*package), data = kmemdup(package->data, *len, GFP_KERNEL);
pnvm_data); if (!data)
return ERR_PTR(-ENOMEM);
kfree(package); kfree(package);
return ret; return data;
} }
static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data, static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data,
......
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* 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__ #ifndef __iwl_fw_uefi__
#define __iwl_fw_uefi__ #define __iwl_fw_uefi__
...@@ -50,25 +50,32 @@ struct uefi_cnv_common_step_data { ...@@ -50,25 +50,32 @@ struct uefi_cnv_common_step_data {
*/ */
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len); void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
int iwl_uefi_get_reduced_power(struct iwl_trans *trans, u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, 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);
void iwl_uefi_get_step_table(struct iwl_trans *trans); void iwl_uefi_get_step_table(struct iwl_trans *trans);
#else /* CONFIG_EFI */ #else /* CONFIG_EFI */
static inline static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{ {
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
} }
static inline static inline int
int iwl_uefi_get_reduced_power(struct iwl_trans *trans, iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
struct iwl_pnvm_image *pnvm_data) const u8 *data, size_t len,
struct iwl_pnvm_image *pnvm_data)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline static inline u8 *
void iwl_uefi_get_step_table(struct iwl_trans *trans) 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 */ #endif /* CONFIG_EFI */
......
...@@ -1047,6 +1047,7 @@ struct iwl_trans_txqs { ...@@ -1047,6 +1047,7 @@ struct iwl_trans_txqs {
* @pm_support: set to true in start_hw if link pm is supported * @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled * @ltr_enabled: set to true if the LTR is enabled
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed * @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 * @wide_cmd_header: true when ucode supports wide command header format
* @wait_command_queue: wait queue for sync commands * @wait_command_queue: wait queue for sync commands
* @num_rx_queues: number of RX queues allocated by the transport; * @num_rx_queues: number of RX queues allocated by the transport;
...@@ -1096,6 +1097,7 @@ struct iwl_trans { ...@@ -1096,6 +1097,7 @@ struct iwl_trans {
u8 pnvm_loaded:1; u8 pnvm_loaded:1;
u8 fail_to_parse_pnvm_image:1; u8 fail_to_parse_pnvm_image:1;
u8 reduce_power_loaded:1; u8 reduce_power_loaded:1;
u8 failed_to_load_reduce_power_image:1;
const struct iwl_hcmd_arr *command_groups; const struct iwl_hcmd_arr *command_groups;
int command_groups_size; int command_groups_size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment