summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2021-12-10 12:12:42 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-01-27 13:04:46 +0300
commite23f075d77987de4215c8e0696f28bcc707506f7 (patch)
tree887187e31c284a059e1793280f1bc8eacc8f9222
parent73a32ee6daefbcbc2d2a6d20c7c27e06a7441f05 (diff)
downloadlinux-e23f075d77987de4215c8e0696f28bcc707506f7.tar.xz
iwlwifi: fix leaks/bad data after failed firmware load
[ Upstream commit ab07506b0454bea606095951e19e72c282bfbb42 ] If firmware load fails after having loaded some parts of the firmware, e.g. the IML image, then this would leak. For the host command list we'd end up running into a WARN on the next attempt to load another firmware image. Fix this by calling iwl_dealloc_ucode() on failures, and make that also clear the data so we start fresh on the next round. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20211210110539.1f742f0eb58a.I1315f22f6aa632d94ae2069f85e1bca5e734dce0@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 94553f272d37..2206f66f6994 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -131,6 +131,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
+
+ /* clear the data for the aborted load case */
+ memset(&drv->fw, 0, sizeof(drv->fw));
}
static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
@@ -1333,6 +1336,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
int i;
bool load_module = false;
bool usniffer_images = false;
+ bool failure = true;
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size =
@@ -1602,6 +1606,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
op->name, err);
#endif
}
+ failure = false;
goto free;
try_again:
@@ -1617,6 +1622,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
complete(&drv->request_firmware_complete);
device_release_driver(drv->trans->dev);
free:
+ if (failure)
+ iwl_dealloc_ucode(drv);
+
if (pieces) {
for (i = 0; i < ARRAY_SIZE(pieces->img); i++)
kfree(pieces->img[i].sec);