summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
diff options
context:
space:
mode:
authorAlon Giladi <alon.giladi@intel.com>2023-06-06 10:43:05 +0300
committerJohannes Berg <johannes.berg@intel.com>2023-06-06 13:44:40 +0200
commitea3571f48953df2cf77a9c4200a7363236736673 (patch)
tree4487a422efda4f7450ed3244b62533a98338d395 /drivers/net/wireless/intel/iwlwifi/fw/uefi.c
parentc738fb6163b213dd9565ba1951d4f130975db10f (diff)
wifi: iwlwifi: Use iwl_pnvm_image in reduce power tables flow
Generalize the parsing, loading, and setting of the power-reduce tables, in order to support allocation of several DRAM payloads 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.564f1eead99b.Iaba653b21dc09aafc72b9bbb3928abddce0db50a@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw/uefi.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c90
1 files changed, 37 insertions, 53 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 01afea33c38c..64b45a5b767e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -55,14 +55,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
return data;
}
-static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
- const u8 *data, size_t len)
+static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
- u8 *reduce_power_data = NULL, *tmp;
- u32 size = 0;
IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n");
+ memset(pnvm_data, 0, sizeof(*pnvm_data));
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
@@ -76,9 +76,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-EINVAL);
- goto out;
+ return -EINVAL;
}
data += sizeof(*tlv);
@@ -89,23 +87,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
"Got IWL_UCODE_TLV_MEM_DESC len %d\n",
tlv_len);
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
-
- tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
- if (!tmp) {
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
IWL_DEBUG_FW(trans,
- "Couldn't allocate (more) reduce_power_data\n");
-
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOMEM);
- goto out;
+ "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
}
- reduce_power_data = tmp;
-
- memcpy(reduce_power_data + size, data, tlv_len);
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
- size += tlv_len;
+ pnvm_data->chunks[pnvm_data->n_chunks].data = data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len;
+ pnvm_data->n_chunks++;
break;
}
@@ -124,27 +116,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
}
done:
- if (!size) {
+ if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
- /* Better safe than sorry, but 'reduce_power_data' should
- * always be NULL if !size.
- */
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOENT);
- goto out;
+ return -ENOENT;
}
-
- IWL_INFO(trans, "loaded REDUCE_POWER\n");
-
-out:
- return reduce_power_data;
+ return 0;
}
-static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
- const u8 *data, size_t len)
+static 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;
- void *sec_data;
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
@@ -160,7 +143,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
@@ -181,11 +164,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
- sec_data = iwl_uefi_reduce_power_section(trans,
- data,
- len);
- if (!IS_ERR(sec_data))
- return sec_data;
+ int ret = iwl_uefi_reduce_power_section(trans,
+ data, len,
+ pnvm_data);
+ if (!ret)
+ return 0;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
@@ -195,20 +178,20 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
}
}
- return ERR_PTR(-ENOENT);
+ return -ENOENT;
}
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
+ struct iwl_pnvm_image *pnvm_data)
{
struct pnvm_sku_package *package;
- void *data = NULL;
unsigned long package_size;
efi_status_t status;
-
- *len = 0;
+ int ret;
+ size_t len = 0;
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
/*
* TODO: we hardcode a maximum length here, because reading
@@ -219,7 +202,7 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
package = kmalloc(package_size, GFP_KERNEL);
if (!package)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
NULL, &package_size, package);
@@ -228,22 +211,23 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
status, package_size);
kfree(package);
- return ERR_PTR(-ENOENT);
+ return -ENOENT;
}
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
package_size);
- *len = 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);
- data = iwl_uefi_reduce_power_parse(trans, package->data,
- *len - sizeof(*package));
+ ret = iwl_uefi_reduce_power_parse(trans, package->data,
+ len - sizeof(*package),
+ pnvm_data);
kfree(package);
- return data;
+ return ret;
}
static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data,