Commit ea3571f4 authored by Alon Giladi's avatar Alon Giladi Committed by Johannes Berg

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: default avatarAlon Giladi <alon.giladi@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230606103519.564f1eead99b.Iaba653b21dc09aafc72b9bbb3928abddce0db50a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c738fb61
......@@ -320,8 +320,9 @@ int iwl_pnvm_load(struct iwl_trans *trans,
reduce_tables:
/* now try to get the reduce power table, if not loaded yet */
if (!trans->reduce_power_loaded) {
data = iwl_uefi_get_reduced_power(trans, &length);
if (IS_ERR_OR_NULL(data)) {
memset(&pnvm_data, 0, sizeof(pnvm_data));
ret = iwl_uefi_get_reduced_power(trans, &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
......@@ -329,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
*/
trans->reduce_power_loaded = true;
} else {
ret = iwl_trans_load_reduce_power(trans, data, length);
ret = iwl_trans_load_reduce_power(trans, &pnvm_data);
if (ret) {
IWL_DEBUG_FW(trans,
"Failed to load reduce power table %d\n",
......
......@@ -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,
......
......@@ -50,7 +50,8 @@ struct uefi_cnv_common_step_data {
*/
#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
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);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
#else /* CONFIG_EFI */
static inline
......@@ -60,9 +61,10 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
}
static inline
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)
{
return ERR_PTR(-EOPNOTSUPP);
return -EOPNOTSUPP;
}
static inline
......
......@@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa);
void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa);
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
const void *data, u32 len);
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power
(struct iwl_trans *trans,
const struct iwl_pnvm_image *payloads);
void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans);
int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
u32 mbx_addr_0_step, u32 mbx_addr_1_step);
......
......@@ -641,8 +641,7 @@ struct iwl_trans_ops {
void (*set_pnvm)(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa);
int (*load_reduce_power)(struct iwl_trans *trans,
const void *data,
u32 len);
const struct iwl_pnvm_image *payloads);
void (*set_reduce_power)(struct iwl_trans *trans);
void (*interrupts)(struct iwl_trans *trans, bool enable);
......@@ -1559,11 +1558,11 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans,
trans->ops->set_pnvm(trans, capa);
}
static inline int iwl_trans_load_reduce_power(struct iwl_trans *trans,
const void *data,
u32 len)
static inline int iwl_trans_load_reduce_power
(struct iwl_trans *trans,
const struct iwl_pnvm_image *payloads)
{
return trans->ops->load_reduce_power(trans, data, len);
return trans->ops->load_reduce_power(trans, payloads);
}
static inline void iwl_trans_set_reduce_power(struct iwl_trans *trans)
......
......@@ -443,31 +443,24 @@ void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
}
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
const void *data,
u32 len)
const struct iwl_pnvm_image *payloads)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
int ret;
struct iwl_dram_data *dram = &trans_pcie->reduce_power_dram;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
/* only allocate the DRAM if not allocated yet */
if (!trans->reduce_power_loaded) {
if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
return -EBUSY;
if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
return -EBUSY;
ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
&trans_pcie->reduce_power_dram);
if (ret < 0) {
IWL_DEBUG_FW(trans,
"Failed to allocate reduce power DMA %d.\n",
ret);
return ret;
}
}
/* only allocate the DRAM if not allocated yet */
if (!trans->reduce_power_loaded)
return iwl_pcie_load_payloads_continuously(trans,
payloads,
dram);
return 0;
}
......
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