@@ -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;
}