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, ...@@ -320,8 +320,9 @@ 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->reduce_power_loaded) { if (!trans->reduce_power_loaded) {
data = iwl_uefi_get_reduced_power(trans, &length); memset(&pnvm_data, 0, sizeof(pnvm_data));
if (IS_ERR_OR_NULL(data)) { ret = iwl_uefi_get_reduced_power(trans, &pnvm_data);
if (ret) {
/* /*
* Pretend we've loaded it - at least we've tried and * Pretend we've loaded it - at least we've tried and
* couldn't load it at all, so there's no point in * couldn't load it at all, so there's no point in
...@@ -329,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, ...@@ -329,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
*/ */
trans->reduce_power_loaded = true; trans->reduce_power_loaded = true;
} else { } else {
ret = iwl_trans_load_reduce_power(trans, data, length); ret = iwl_trans_load_reduce_power(trans, &pnvm_data);
if (ret) { if (ret) {
IWL_DEBUG_FW(trans, IWL_DEBUG_FW(trans,
"Failed to load reduce power table %d\n", "Failed to load reduce power table %d\n",
......
...@@ -55,14 +55,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) ...@@ -55,14 +55,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
return data; return data;
} }
static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
const u8 *data, size_t len) const u8 *data, size_t len,
struct iwl_pnvm_image *pnvm_data)
{ {
const struct iwl_ucode_tlv *tlv; const struct iwl_ucode_tlv *tlv;
u8 *reduce_power_data = NULL, *tmp;
u32 size = 0;
IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n"); IWL_DEBUG_FW(trans, "Handling REDUCE_POWER 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;
...@@ -76,9 +76,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -76,9 +76,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
if (len < tlv_len) { if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n", IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len); len, tlv_len);
kfree(reduce_power_data); return -EINVAL;
reduce_power_data = ERR_PTR(-EINVAL);
goto out;
} }
data += sizeof(*tlv); data += sizeof(*tlv);
...@@ -89,23 +87,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -89,23 +87,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
"Got IWL_UCODE_TLV_MEM_DESC len %d\n", "Got IWL_UCODE_TLV_MEM_DESC len %d\n",
tlv_len); tlv_len);
IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
if (!tmp) {
IWL_DEBUG_FW(trans, IWL_DEBUG_FW(trans,
"Couldn't allocate (more) reduce_power_data\n"); "too many payloads to allocate in DRAM.\n");
return -EINVAL;
kfree(reduce_power_data);
reduce_power_data = ERR_PTR(-ENOMEM);
goto out;
} }
reduce_power_data = tmp; IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
memcpy(reduce_power_data + size, data, 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; break;
} }
...@@ -124,27 +116,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -124,27 +116,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
} }
done: done:
if (!size) { if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
/* Better safe than sorry, but 'reduce_power_data' should return -ENOENT;
* always be NULL if !size.
*/
kfree(reduce_power_data);
reduce_power_data = ERR_PTR(-ENOENT);
goto out;
} }
return 0;
IWL_INFO(trans, "loaded REDUCE_POWER\n");
out:
return reduce_power_data;
} }
static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, static 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)
{ {
const struct iwl_ucode_tlv *tlv; const struct iwl_ucode_tlv *tlv;
void *sec_data;
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
...@@ -160,7 +143,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, ...@@ -160,7 +143,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (len < tlv_len) { if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n", IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len); len, tlv_len);
return ERR_PTR(-EINVAL); return -EINVAL;
} }
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) { if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
...@@ -181,11 +164,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, ...@@ -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]) && 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[1] == le32_to_cpu(sku_id->data[1]) &&
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
sec_data = iwl_uefi_reduce_power_section(trans, int ret = iwl_uefi_reduce_power_section(trans,
data, data, len,
len); pnvm_data);
if (!IS_ERR(sec_data)) if (!ret)
return sec_data; return 0;
} else { } else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); 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, ...@@ -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; struct pnvm_sku_package *package;
void *data = NULL;
unsigned long package_size; unsigned long package_size;
efi_status_t status; efi_status_t status;
int ret;
*len = 0; 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 ERR_PTR(-ENODEV); return -ENODEV;
/* /*
* TODO: we hardcode a maximum length here, because reading * 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) ...@@ -219,7 +202,7 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
package = kmalloc(package_size, GFP_KERNEL); package = kmalloc(package_size, GFP_KERNEL);
if (!package) if (!package)
return ERR_PTR(-ENOMEM); return -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);
...@@ -228,22 +211,23 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) ...@@ -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", "Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
status, package_size); status, package_size);
kfree(package); kfree(package);
return ERR_PTR(-ENOENT); return -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; 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);
data = iwl_uefi_reduce_power_parse(trans, package->data, ret = iwl_uefi_reduce_power_parse(trans, package->data,
*len - sizeof(*package)); len - sizeof(*package),
pnvm_data);
kfree(package); kfree(package);
return data; return ret;
} }
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,
......
...@@ -50,7 +50,8 @@ struct uefi_cnv_common_step_data { ...@@ -50,7 +50,8 @@ 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);
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); void iwl_uefi_get_step_table(struct iwl_trans *trans);
#else /* CONFIG_EFI */ #else /* CONFIG_EFI */
static inline static inline
...@@ -60,9 +61,10 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) ...@@ -60,9 +61,10 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
} }
static inline 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 static inline
......
...@@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, ...@@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa); const struct iwl_ucode_capabilities *capa);
void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa); const struct iwl_ucode_capabilities *capa);
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, int iwl_trans_pcie_ctx_info_gen3_load_reduce_power
const void *data, u32 len); (struct iwl_trans *trans,
const struct iwl_pnvm_image *payloads);
void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans); 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, int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
u32 mbx_addr_0_step, u32 mbx_addr_1_step); u32 mbx_addr_0_step, u32 mbx_addr_1_step);
......
...@@ -641,8 +641,7 @@ struct iwl_trans_ops { ...@@ -641,8 +641,7 @@ struct iwl_trans_ops {
void (*set_pnvm)(struct iwl_trans *trans, void (*set_pnvm)(struct iwl_trans *trans,
const struct iwl_ucode_capabilities *capa); const struct iwl_ucode_capabilities *capa);
int (*load_reduce_power)(struct iwl_trans *trans, int (*load_reduce_power)(struct iwl_trans *trans,
const void *data, const struct iwl_pnvm_image *payloads);
u32 len);
void (*set_reduce_power)(struct iwl_trans *trans); void (*set_reduce_power)(struct iwl_trans *trans);
void (*interrupts)(struct iwl_trans *trans, bool enable); void (*interrupts)(struct iwl_trans *trans, bool enable);
...@@ -1559,11 +1558,11 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, ...@@ -1559,11 +1558,11 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans,
trans->ops->set_pnvm(trans, capa); trans->ops->set_pnvm(trans, capa);
} }
static inline int iwl_trans_load_reduce_power(struct iwl_trans *trans, static inline int iwl_trans_load_reduce_power
const void *data, (struct iwl_trans *trans,
u32 len) 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) 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, ...@@ -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, int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
const void *data, const struct iwl_pnvm_image *payloads)
u32 len)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg; &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) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0; 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)) if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
return -EBUSY; return -EBUSY;
ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, /* only allocate the DRAM if not allocated yet */
&trans_pcie->reduce_power_dram); if (!trans->reduce_power_loaded)
if (ret < 0) { return iwl_pcie_load_payloads_continuously(trans,
IWL_DEBUG_FW(trans, payloads,
"Failed to allocate reduce power DMA %d.\n", dram);
ret);
return ret;
}
}
return 0; 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