wifi: iwlwifi: Use iwl_pnvm_image in reduce power tables flow
authorAlon Giladi <alon.giladi@intel.com>
Tue, 6 Jun 2023 07:43:05 +0000 (10:43 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Jun 2023 11:44:40 +0000 (13:44 +0200)
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>
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h
drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c

index bb6300469f4a3e1408332dcd418f6bc494b77ec8..42d994240b3178b0a89ec2d5fe89321e3696628e 100644 (file)
@@ -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 @@ reduce_tables:
                         */
                        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",
index 01afea33c38cc04446900bdddab868331f041e27..64b45a5b767e5cfbc267b5e5d521ffcc9c171894 100644 (file)
@@ -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,
index 17089bc74cf92236a7d83808b9b2b444fa73819c..03176f73151a3dc747db1986b37833f4bee890cd 100644 (file)
@@ -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
index e019aec027d604f59359a0228d19aa90aa5606ca..7e7d135e85b13c6ae450b676bf74c7a54675db67 100644 (file)
@@ -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);
index 0c80644730336517e55aeb07c4114892a8a7e0dc..4faf9fc6bbe4c7975f09b6246ba15e4879f05da2 100644 (file)
@@ -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)
index 2619c868b51ff88b16d8b7341253d5d19c36b220..26d5ba777d247a92c43af2a5a4dbceaad7e7e6ab 100644 (file)
@@ -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;
 }