wifi: iwlwifi: Take loading and setting of pnvm image out of parsing part
Change iwl_pnvm_parse so it will only save the information into the iwl_pnvm_image struct. This enables to use the parsing code for the power reduce tables in the future. Signed-off-by: Alon Giladi <alon.giladi@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230606103519.504b42fc1611.I4ddf6ad76d922d118fcbcc4f0e9ec003753d0b75@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
194d1f84d5
commit
b99e32cbfd
2 changed files with 73 additions and 61 deletions
|
@ -1,6 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||||
/*
|
/*
|
||||||
* Copyright(c) 2020-2022 Intel Corporation
|
* Copyright(c) 2020-2023 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "iwl-drv.h"
|
#include "iwl-drv.h"
|
||||||
|
@ -31,17 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||||
size_t len)
|
size_t len,
|
||||||
|
struct iwl_pnvm_image *pnvm_data)
|
||||||
{
|
{
|
||||||
const struct iwl_ucode_tlv *tlv;
|
const struct iwl_ucode_tlv *tlv;
|
||||||
u32 sha1 = 0;
|
u32 sha1 = 0;
|
||||||
u16 mac_type = 0, rf_id = 0;
|
u16 mac_type = 0, rf_id = 0;
|
||||||
struct iwl_pnvm_image pnvm_data = {};
|
|
||||||
bool hw_match = false;
|
bool hw_match = false;
|
||||||
int ret;
|
|
||||||
|
|
||||||
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
|
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
|
||||||
|
|
||||||
|
memset(pnvm_data, 0, sizeof(*pnvm_data));
|
||||||
|
|
||||||
while (len >= sizeof(*tlv)) {
|
while (len >= sizeof(*tlv)) {
|
||||||
u32 tlv_len, tlv_type;
|
u32 tlv_len, tlv_type;
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||||
IWL_DEBUG_FW(trans,
|
IWL_DEBUG_FW(trans,
|
||||||
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
|
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
|
||||||
sha1);
|
sha1);
|
||||||
|
pnvm_data->version = sha1;
|
||||||
break;
|
break;
|
||||||
case IWL_UCODE_TLV_HW_TYPE:
|
case IWL_UCODE_TLV_HW_TYPE:
|
||||||
if (tlv_len < 2 * sizeof(__le16)) {
|
if (tlv_len < 2 * sizeof(__le16)) {
|
||||||
|
@ -110,7 +112,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pnvm_data.n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
|
if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
|
||||||
IWL_DEBUG_FW(trans,
|
IWL_DEBUG_FW(trans,
|
||||||
"too many payloads to allocate in DRAM.\n");
|
"too many payloads to allocate in DRAM.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -119,9 +121,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
|
||||||
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
|
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
|
||||||
data_len);
|
data_len);
|
||||||
|
|
||||||
pnvm_data.chunks[pnvm_data.n_chunks].data = section->data;
|
pnvm_data->chunks[pnvm_data->n_chunks].data = section->data;
|
||||||
pnvm_data.chunks[pnvm_data.n_chunks].len = data_len;
|
pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
|
||||||
pnvm_data.n_chunks++;
|
pnvm_data->n_chunks++;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -148,23 +150,17 @@ done:
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pnvm_data.n_chunks) {
|
if (!pnvm_data->n_chunks) {
|
||||||
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
|
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_trans_load_pnvm(trans, &pnvm_data);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
|
|
||||||
|
|
||||||
iwl_trans_set_pnvm(trans);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
||||||
size_t len)
|
size_t len,
|
||||||
|
struct iwl_pnvm_image *pnvm_data)
|
||||||
{
|
{
|
||||||
const struct iwl_ucode_tlv *tlv;
|
const struct iwl_ucode_tlv *tlv;
|
||||||
|
|
||||||
|
@ -205,7 +201,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
|
||||||
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
|
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = iwl_pnvm_handle_section(trans, data, len);
|
ret = iwl_pnvm_handle_section(trans, data, len,
|
||||||
|
pnvm_data);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -248,70 +245,81 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
|
||||||
|
{
|
||||||
|
struct pnvm_sku_package *package;
|
||||||
|
u8 *image = NULL;
|
||||||
|
|
||||||
|
/* First attempt to get the PNVM from BIOS */
|
||||||
|
package = iwl_uefi_get_pnvm(trans_p, len);
|
||||||
|
if (!IS_ERR_OR_NULL(package)) {
|
||||||
|
if (*len >= sizeof(*package)) {
|
||||||
|
/* we need only the data */
|
||||||
|
*len -= sizeof(*package);
|
||||||
|
image = kmemdup(package->data, *len, GFP_KERNEL);
|
||||||
|
}
|
||||||
|
/* free package regardless of whether kmemdup succeeded */
|
||||||
|
kfree(package);
|
||||||
|
if (image)
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's not available, try from the filesystem */
|
||||||
|
if (iwl_pnvm_get_from_fs(trans_p, &image, len))
|
||||||
|
return NULL;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
int iwl_pnvm_load(struct iwl_trans *trans,
|
int iwl_pnvm_load(struct iwl_trans *trans,
|
||||||
struct iwl_notif_wait_data *notif_wait)
|
struct iwl_notif_wait_data *notif_wait)
|
||||||
{
|
{
|
||||||
u8 *data;
|
u8 *data;
|
||||||
size_t len;
|
size_t length;
|
||||||
struct pnvm_sku_package *package;
|
|
||||||
struct iwl_notification_wait pnvm_wait;
|
struct iwl_notification_wait pnvm_wait;
|
||||||
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||||
PNVM_INIT_COMPLETE_NTFY) };
|
PNVM_INIT_COMPLETE_NTFY) };
|
||||||
|
struct iwl_pnvm_image pnvm_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* if the SKU_ID is empty, there's nothing to do */
|
/* if the SKU_ID is empty, there's nothing to do */
|
||||||
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
|
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/* failed to get/parse the image in the past, no use to try again */
|
||||||
* If we already loaded (or tried to load) it before, we just
|
if (trans->fail_to_parse_pnvm_image)
|
||||||
* need to set it again.
|
goto reduce_tables;
|
||||||
*/
|
|
||||||
if (trans->pnvm_loaded) {
|
|
||||||
iwl_trans_set_pnvm(trans);
|
|
||||||
goto skip_parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First attempt to get the PNVM from BIOS */
|
/* get the image, parse and load it, if not loaded yet */
|
||||||
package = iwl_uefi_get_pnvm(trans, &len);
|
if (!trans->pnvm_loaded) {
|
||||||
if (!IS_ERR_OR_NULL(package)) {
|
data = iwl_get_pnvm_image(trans, &length);
|
||||||
if (len >= sizeof(*package)) {
|
if (!data) {
|
||||||
/* we need only the data */
|
trans->fail_to_parse_pnvm_image = true;
|
||||||
len -= sizeof(*package);
|
goto reduce_tables;
|
||||||
data = kmemdup(package->data, len, GFP_KERNEL);
|
}
|
||||||
} else {
|
ret = iwl_pnvm_parse(trans, data, length, &pnvm_data);
|
||||||
data = NULL;
|
if (ret) {
|
||||||
|
trans->fail_to_parse_pnvm_image = true;
|
||||||
|
kfree(data);
|
||||||
|
goto reduce_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free package regardless of whether kmemdup succeeded */
|
ret = iwl_trans_load_pnvm(trans, &pnvm_data);
|
||||||
kfree(package);
|
/* can only free data after pvnm_data use, but
|
||||||
|
* pnvm_data.version used below is not a pointer
|
||||||
if (data)
|
|
||||||
goto parse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If it's not available, try from the filesystem */
|
|
||||||
ret = iwl_pnvm_get_from_fs(trans, &data, &len);
|
|
||||||
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->pnvm_loaded = true;
|
kfree(data);
|
||||||
|
if (ret)
|
||||||
goto skip_parse;
|
goto reduce_tables;
|
||||||
|
IWL_INFO(trans, "loaded PNVM version %08x\n",
|
||||||
|
pnvm_data.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse:
|
iwl_trans_set_pnvm(trans);
|
||||||
iwl_pnvm_parse(trans, data, len);
|
|
||||||
|
|
||||||
kfree(data);
|
reduce_tables:
|
||||||
|
|
||||||
skip_parse:
|
|
||||||
/* 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->reduce_power_loaded) {
|
if (!trans->reduce_power_loaded) {
|
||||||
data = iwl_uefi_get_reduced_power(trans, &len);
|
data = iwl_uefi_get_reduced_power(trans, &length);
|
||||||
if (IS_ERR_OR_NULL(data)) {
|
if (IS_ERR_OR_NULL(data)) {
|
||||||
/*
|
/*
|
||||||
* Pretend we've loaded it - at least we've tried and
|
* Pretend we've loaded it - at least we've tried and
|
||||||
|
@ -320,7 +328,7 @@ skip_parse:
|
||||||
*/
|
*/
|
||||||
trans->reduce_power_loaded = true;
|
trans->reduce_power_loaded = true;
|
||||||
} else {
|
} else {
|
||||||
ret = iwl_trans_set_reduce_power(trans, data, len);
|
ret = iwl_trans_set_reduce_power(trans, data, length);
|
||||||
if (ret)
|
if (ret)
|
||||||
IWL_DEBUG_FW(trans,
|
IWL_DEBUG_FW(trans,
|
||||||
"Failed to set reduce power table %d\n",
|
"Failed to set reduce power table %d\n",
|
||||||
|
|
|
@ -466,6 +466,7 @@ struct iwl_trans_rxq_dma_data {
|
||||||
* struct iwl_pnvm_image - contains info about the parsed pnvm image
|
* struct iwl_pnvm_image - contains info about the parsed pnvm image
|
||||||
* @chunks: array of pointers to pnvm payloads and their sizes
|
* @chunks: array of pointers to pnvm payloads and their sizes
|
||||||
* @n_chunks: the number of the pnvm payloads.
|
* @n_chunks: the number of the pnvm payloads.
|
||||||
|
* @version: the version of the loaded PNVM image
|
||||||
*/
|
*/
|
||||||
struct iwl_pnvm_image {
|
struct iwl_pnvm_image {
|
||||||
struct {
|
struct {
|
||||||
|
@ -473,6 +474,7 @@ struct iwl_pnvm_image {
|
||||||
u32 len;
|
u32 len;
|
||||||
} chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
|
} chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
|
||||||
u32 n_chunks;
|
u32 n_chunks;
|
||||||
|
u32 version;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1023,6 +1025,7 @@ struct iwl_trans_txqs {
|
||||||
* @hw_rev_step: The mac step of the HW
|
* @hw_rev_step: The mac step of the HW
|
||||||
* @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
|
||||||
* @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;
|
||||||
|
@ -1070,6 +1073,7 @@ struct iwl_trans {
|
||||||
bool pm_support;
|
bool pm_support;
|
||||||
bool ltr_enabled;
|
bool ltr_enabled;
|
||||||
u8 pnvm_loaded:1;
|
u8 pnvm_loaded:1;
|
||||||
|
u8 fail_to_parse_pnvm_image:1;
|
||||||
u8 reduce_power_loaded:1;
|
u8 reduce_power_loaded:1;
|
||||||
|
|
||||||
const struct iwl_hcmd_arr *command_groups;
|
const struct iwl_hcmd_arr *command_groups;
|
||||||
|
|
Loading…
Add table
Reference in a new issue