wifi: iwlwifi: Separate reading and parsing of reduce power table
authorAlon Giladi <alon.giladi@intel.com>
Tue, 6 Jun 2023 07:43:07 +0000 (10:43 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Jun 2023 11:45:06 +0000 (13:45 +0200)
It enables to better handle error cases. Also save the image till the
end of the loading and only then free it.

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.71e3b3e0e794.Ifbe69ad99a7e805eb70e09280365821eb146b1c9@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-trans.h

index b556abece89637a2c48df377eb6b21a929bb6519..3b5a3c89fedff5f3565a3d80ce5748f3876acdf2 100644 (file)
@@ -319,29 +319,39 @@ int iwl_pnvm_load(struct iwl_trans *trans,
 
 reduce_tables:
        /* now try to get the reduce power table, if not loaded yet */
+       if (trans->failed_to_load_reduce_power_image)
+               goto notification;
+
        if (!trans->reduce_power_loaded) {
                memset(&pnvm_data, 0, sizeof(pnvm_data));
-               ret = iwl_uefi_get_reduced_power(trans, &pnvm_data);
+               data = iwl_uefi_get_reduced_power(trans, &length);
+               if (IS_ERR(data)) {
+                       ret = PTR_ERR(data);
+                       trans->failed_to_load_reduce_power_image = true;
+                       goto notification;
+               }
+
+               ret = iwl_uefi_reduce_power_parse(trans, data, length,
+                                                 &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
-                        * trying again over and over.
-                        */
-                       trans->reduce_power_loaded = true;
-               } else {
-                       ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa);
-                       if (ret) {
-                               IWL_DEBUG_FW(trans,
-                                            "Failed to load reduce power table %d\n",
-                                            ret);
-                               trans->reduce_power_loaded = true;
-                       }
+                       trans->failed_to_load_reduce_power_image = true;
                        kfree(data);
+                       goto notification;
+               }
+
+               ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa);
+               kfree(data);
+               if (ret) {
+                       IWL_DEBUG_FW(trans,
+                                    "Failed to load reduce power table %d\n",
+                                    ret);
+                       trans->failed_to_load_reduce_power_image = true;
+                       goto notification;
                }
        }
        iwl_trans_set_reduce_power(trans, capa);
 
+notification:
        iwl_init_notification_wait(notif_wait, &pnvm_wait,
                                   ntf_cmds, ARRAY_SIZE(ntf_cmds),
                                   iwl_pnvm_complete_fn, trans);
index 64b45a5b767e5cfbc267b5e5d521ffcc9c171894..1666ef3a482efb40f23e1eb828dd46e07574a3bf 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
  */
 
 #include "iwl-drv.h"
@@ -123,9 +123,9 @@ done:
        return 0;
 }
 
-static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
-                                      const u8 *data, size_t len,
-                                      struct iwl_pnvm_image *pnvm_data)
+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;
 
@@ -181,17 +181,15 @@ static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
        return -ENOENT;
 }
 
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-                              struct iwl_pnvm_image *pnvm_data)
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
 {
        struct pnvm_sku_package *package;
        unsigned long package_size;
        efi_status_t status;
-       int ret;
-       size_t len = 0;
+       u8 *data;
 
        if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
-               return -ENODEV;
+               return ERR_PTR(-ENODEV);
 
        /*
         * TODO: we hardcode a maximum length here, because reading
@@ -202,7 +200,7 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
 
        package = kmalloc(package_size, GFP_KERNEL);
        if (!package)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
                                  NULL, &package_size, package);
@@ -211,23 +209,22 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
                             "Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
                             status, package_size);
                kfree(package);
-               return -ENOENT;
+               return ERR_PTR(-ENOENT);
        }
 
        IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
                     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);
 
-       ret = iwl_uefi_reduce_power_parse(trans, package->data,
-                                         len - sizeof(*package),
-                                         pnvm_data);
-
+       *len = package_size - sizeof(*package);
+       data = kmemdup(package->data, *len, GFP_KERNEL);
+       if (!data)
+               return ERR_PTR(-ENOMEM);
        kfree(package);
 
-       return ret;
+       return data;
 }
 
 static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data,
index 03176f73151a3dc747db1986b37833f4bee890cd..10bed372e67cb7d668bc588e7a64cbf0b0bb3040 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
  */
 #ifndef __iwl_fw_uefi__
 #define __iwl_fw_uefi__
@@ -50,25 +50,32 @@ struct uefi_cnv_common_step_data {
  */
 #ifdef CONFIG_EFI
 void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-                              struct iwl_pnvm_image *pnvm_data);
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+                               const u8 *data, size_t len,
+                               struct iwl_pnvm_image *pnvm_data);
 void iwl_uefi_get_step_table(struct iwl_trans *trans);
 #else /* CONFIG_EFI */
-static inline
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
        return ERR_PTR(-EOPNOTSUPP);
 }
 
-static inline
-int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
-                              struct iwl_pnvm_image *pnvm_data)
+static inline int
+iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+                           const u8 *data, size_t len,
+                           struct iwl_pnvm_image *pnvm_data)
 {
        return -EOPNOTSUPP;
 }
 
-static inline
-void iwl_uefi_get_step_table(struct iwl_trans *trans)
+static inline u8 *
+iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void iwl_uefi_get_step_table(struct iwl_trans *trans)
 {
 }
 #endif /* CONFIG_EFI */
index eb32683c36fb5f7810ca34f34e2f04aae88868e4..d9e465d0f4af35c012c63986362fd51c291bc16d 100644 (file)
@@ -1047,6 +1047,7 @@ struct iwl_trans_txqs {
  * @pm_support: set to true in start_hw if link pm is supported
  * @ltr_enabled: set to true if the LTR is enabled
  * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
+ * @failed_to_load_reduce_power_image: set to true if pnvm loading failed
  * @wide_cmd_header: true when ucode supports wide command header format
  * @wait_command_queue: wait queue for sync commands
  * @num_rx_queues: number of RX queues allocated by the transport;
@@ -1096,6 +1097,7 @@ struct iwl_trans {
        u8 pnvm_loaded:1;
        u8 fail_to_parse_pnvm_image:1;
        u8 reduce_power_loaded:1;
+       u8 failed_to_load_reduce_power_image:1;
 
        const struct iwl_hcmd_arr *command_groups;
        int command_groups_size;