All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ping-Ke Shih <pkshih@realtek.com>
To: <linux-wireless@vger.kernel.org>
Cc: <kevin_yang@realtek.com>
Subject: [PATCH rtw-next 3/6] wifi: rtw89: fw: duplicate firmware suit data by vmalloc to reduce memory fragment
Date: Wed, 23 Sep 2026 13:45:02 +0800	[thread overview]
Message-ID: <20260923054505.43329-4-pkshih@realtek.com> (raw)
In-Reply-To: <20260923054505.43329-1-pkshih@realtek.com>

The firmware suit data might be just over 512kB (e.g. 540kB) and actual
allocation size of devm_kmemdup() can be 1MB, which is a big internal
fragment. Use vmalooc() instead to reduce fragment.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.c |  1 +
 drivers/net/wireless/realtek/rtw89/core.h |  3 ++
 drivers/net/wireless/realtek/rtw89/fw.c   | 52 ++++++++++++++++++-----
 3 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 5ca0c401c43a..e61d7e89882f 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -6986,6 +6986,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
 	}
 	INIT_LIST_HEAD(&rtwdev->scan_info.chan_list);
 	INIT_LIST_HEAD(&rtwdev->tx_waits);
+	INIT_LIST_HEAD(&rtwdev->fw.dup_data_list);
 	INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work);
 	INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work);
 	INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 4b4500a7a068..d8adf7425a3a 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -6059,6 +6059,7 @@ enum rtw89_fw_feature {
 struct rtw89_fw_suit {
 	enum rtw89_fw_type type;
 	const u8 *data;
+	struct list_head list;
 	u32 size;
 	u8 major_ver;
 	u8 minor_ver;
@@ -6150,6 +6151,8 @@ struct rtw89_fw_info {
 	struct rtw89_fw_elm_info elm_info;
 	struct rtw89_fw_secure sec;
 
+	struct list_head dup_data_list;
+
 	DECLARE_BITMAP(feature_map, NUM_OF_RTW89_FW_FEATURES);
 };
 
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index e4b59690622d..7c7c0a4f703e 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -3,6 +3,7 @@
  */
 
 #include <linux/if_arp.h>
+#include <linux/vmalloc.h>
 #include "cam.h"
 #include "chan.h"
 #include "coex.h"
@@ -138,15 +139,23 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type
 }
 
 static const void *__rtw89_fw_elem_dup_if_needed(struct rtw89_dev *rtwdev,
-						 const void *src, size_t len)
+						 const void *src, size_t len,
+						 bool is_fw_suit)
 {
 	struct rtw89_fw_req_info *fw_req = &rtwdev->fw.req;
-	const void *dup;
+	void *dup;
 
 	if (!fw_req->free_after_probe)
 		return src;
 
-	dup = devm_kmemdup(rtwdev->dev, src, len, GFP_KERNEL);
+	if (is_fw_suit) {
+		dup = vmalloc(len);
+		if (dup)
+			memcpy(dup, src, len);
+	} else {
+		dup = devm_kmemdup(rtwdev->dev, src, len, GFP_KERNEL);
+	}
+
 	if (!dup) {
 		/* If failed to memdup, fallback to point to firmware->data. */
 		fw_req->free_after_probe = false;
@@ -161,7 +170,22 @@ static const void *rtw89_fw_elem_dup_if_needed(struct rtw89_dev *rtwdev,
 {
 	size_t len = sizeof(*elm) + le32_to_cpu(elm->size);
 
-	return __rtw89_fw_elem_dup_if_needed(rtwdev, elm, len);
+	return __rtw89_fw_elem_dup_if_needed(rtwdev, elm, len, false);
+}
+
+static const void *rtw89_fw_suit_data_dup_if_needed(struct rtw89_dev *rtwdev,
+						    struct rtw89_fw_suit *fw_suit,
+						    const void *src)
+{
+	struct rtw89_fw_info *fw = &rtwdev->fw;
+	const void *dup;
+
+	dup = __rtw89_fw_elem_dup_if_needed(rtwdev, src, fw_suit->size, true);
+
+	if (dup != src)
+		list_add_tail(&fw_suit->list, &fw->dup_data_list);
+
+	return dup;
 }
 
 static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
@@ -680,8 +704,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
 		if (type != RTW89_FW_NORMAL)
 			return -EINVAL;
 		fw_suit->size = mfw_len;
-		fw_suit->data = __rtw89_fw_elem_dup_if_needed(rtwdev, mfw,
-							      fw_suit->size);
+		fw_suit->data = rtw89_fw_suit_data_dup_if_needed(rtwdev, fw_suit, mfw);
 		return 0;
 	}
 
@@ -725,8 +748,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
 	}
 
 	fw_suit->size = mfw_info_size;
-	fw_suit->data = __rtw89_fw_elem_dup_if_needed(rtwdev, mfw_info_ptr,
-						      fw_suit->size);
+	fw_suit->data = rtw89_fw_suit_data_dup_if_needed(rtwdev, fw_suit, mfw_info_ptr);
 
 	return 0;
 }
@@ -866,8 +888,8 @@ int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev,
 		return 1; /* ignore this element (a firmware is taken already) */
 
 	fw_suit->size = le32_to_cpu(elm->size);
-	fw_suit->data = __rtw89_fw_elem_dup_if_needed(rtwdev, elm->u.bbmcu.contents,
-						      fw_suit->size);
+	fw_suit->data =
+		rtw89_fw_suit_data_dup_if_needed(rtwdev, fw_suit, elm->u.bbmcu.contents);
 
 	return rtw89_fw_update_ver(rtwdev, type, fw_suit);
 }
@@ -2206,6 +2228,15 @@ static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev)
 	kfree(elm_info->rfk_log_fmt);
 }
 
+static void rtw89_unload_firmware_dup_data(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_fw_info *fw = &rtwdev->fw;
+	struct rtw89_fw_suit *fw_suit;
+
+	list_for_each_entry(fw_suit, &fw->dup_data_list, list)
+		vfree(fw_suit->data);
+}
+
 void __rtw89_unload_firmware(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_fw_info *fw = &rtwdev->fw;
@@ -2229,6 +2260,7 @@ void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
 
 	kfree(fw->log.fmts);
 	rtw89_unload_firmware_elements(rtwdev);
+	rtw89_unload_firmware_dup_data(rtwdev);
 }
 
 static u32 rtw89_fw_log_get_fmt_idx(struct rtw89_dev *rtwdev, u32 fmt_id)
-- 
2.25.1


  parent reply	other threads:[~2026-09-23  5:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23  5:44 [PATCH rtw-next 0/6] wifi: rtw89: fw: reduce memory use of firmware, and support board file Ping-Ke Shih
2026-09-23  5:45 ` [PATCH rtw-next 1/6] wifi: rtw89: fw: duplicate recognized firmware elements Ping-Ke Shih
2026-09-30  1:56   ` Ping-Ke Shih
2026-09-23  5:45 ` [PATCH rtw-next 2/6] wifi: rtw89: fw: release firmware after recognizing " Ping-Ke Shih
2026-09-23  5:45 ` Ping-Ke Shih [this message]
2026-09-23  5:45 ` [PATCH rtw-next 4/6] wifi: rtw89: led: check if board variant assigns led desc Ping-Ke Shih
2026-09-23  5:45 ` [PATCH rtw-next 5/6] wifi: rtw89: support variants of FW elements Ping-Ke Shih
2026-09-23  5:45 ` [PATCH rtw-next 6/6] wifi: rtw89: 8852cu: take board ID 1 for FW elements 28de/2432 Ping-Ke Shih

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260923054505.43329-4-pkshih@realtek.com \
    --to=pkshih@realtek.com \
    --cc=kevin_yang@realtek.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.