From: Ping-Ke Shih <pkshih@realtek.com>
To: <linux-wireless@vger.kernel.org>
Cc: <kevin_yang@realtek.com>
Subject: [PATCH rtw-next 1/6] wifi: rtw89: fw: duplicate recognized firmware elements
Date: Wed, 23 Sep 2026 13:45:00 +0800 [thread overview]
Message-ID: <20260923054505.43329-2-pkshih@realtek.com> (raw)
In-Reply-To: <20260923054505.43329-1-pkshih@realtek.com>
The firmware file contains variant elements for variant hardware, and
currently whole firmware content is persistent. However, RTL8922DE has many
variants and firmware file become grown to over 4MB, but actually size of
necessary duplicate elements are about 1.0MB.
To reduce memory usage, duplicate recognized firmware elements as
persistent memory, and will release firmware by next coming patch.
However, firmware for early chips doesn't have many variant elements, and
no need to duplicate memory for the purpose, so do it only if firmware
size is over 2MB.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 1 +
drivers/net/wireless/realtek/rtw89/fw.c | 72 ++++++++++++++++++-----
2 files changed, 59 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 3a6099386b09..4b4500a7a068 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -6094,6 +6094,7 @@ struct rtw89_fw_suit {
struct rtw89_fw_req_info {
const struct firmware *firmware;
struct completion completion;
+ bool free_after_probe;
};
struct rtw89_fw_log {
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 535cc2ad8611..3cdfb141f075 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -137,6 +137,33 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type
return 0;
}
+static const void *__rtw89_fw_elem_dup_if_needed(struct rtw89_dev *rtwdev,
+ const void *src, size_t len)
+{
+ struct rtw89_fw_req_info *fw_req = &rtwdev->fw.req;
+ const void *dup;
+
+ if (!fw_req->free_after_probe)
+ return src;
+
+ 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;
+ return src;
+ }
+
+ return dup;
+}
+
+static const void *rtw89_fw_elem_dup_if_needed(struct rtw89_dev *rtwdev,
+ const struct rtw89_fw_element_hdr *elm)
+{
+ size_t len = sizeof(*elm) + le32_to_cpu(elm->size);
+
+ return __rtw89_fw_elem_dup_if_needed(rtwdev, elm, len);
+}
+
static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
struct rtw89_fw_bin_info *info)
{
@@ -641,6 +668,8 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
const struct rtw89_mfw_hdr *mfw_hdr;
const u8 *mfw = firmware->data;
u32 mfw_len = firmware->size;
+ const u8 *mfw_info_ptr;
+ u32 mfw_info_size;
int ret;
int i;
@@ -650,8 +679,9 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
/* legacy firmware support normal type only */
if (type != RTW89_FW_NORMAL)
return -EINVAL;
- fw_suit->data = mfw;
fw_suit->size = mfw_len;
+ fw_suit->data = __rtw89_fw_elem_dup_if_needed(rtwdev, mfw,
+ fw_suit->size);
return 0;
}
@@ -686,14 +716,18 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
return -ENOENT;
found:
- fw_suit->data = mfw + le32_to_cpu(mfw_info->shift);
- fw_suit->size = le32_to_cpu(mfw_info->size);
+ mfw_info_ptr = mfw + le32_to_cpu(mfw_info->shift);
+ mfw_info_size = le32_to_cpu(mfw_info->size);
- if (fw_suit->data + fw_suit->size > mfw + mfw_len) {
+ if (mfw_info_ptr + mfw_info_size > mfw + mfw_len) {
rtw89_err(rtwdev, "fw_suit %d out of address\n", type);
return -EFAULT;
}
+ fw_suit->size = mfw_info_size;
+ fw_suit->data = __rtw89_fw_elem_dup_if_needed(rtwdev, mfw_info_ptr,
+ fw_suit->size);
+
return 0;
}
@@ -831,8 +865,9 @@ int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev,
if (fw_suit->data)
return 1; /* ignore this element (a firmware is taken already) */
- fw_suit->data = elm->u.bbmcu.contents;
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);
return rtw89_fw_update_ver(rtwdev, type, fw_suit);
}
@@ -1252,7 +1287,12 @@ int rtw89_fw_recognize_txpwr_from_elm(struct rtw89_dev *rtwdev,
conf->rfe_type = txpwr_elm->rfe_type;
conf->ent_sz = txpwr_elm->ent_sz;
conf->num_ents = le32_to_cpu(txpwr_elm->num_ents);
+ /*
+ * The conf->data is used by rtw89_core_setup_rfe_parms() to do format
+ * conversion before releasing firmware. No need to duplicate.
+ */
conf->data = txpwr_elm->content;
+
return 0;
}
@@ -1263,6 +1303,7 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
const struct rtw89_chip_info *chip = rtwdev->chip;
+ const struct rtw89_fw_element_hdr *elm_dup;
struct rtw89_hal *hal = &rtwdev->hal;
u16 aid = le16_to_cpu(elm->aid);
u32 needed_bitmap = 0;
@@ -1293,6 +1334,8 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
if (!elm_info->txpwr_trk)
return -ENOMEM;
+ elm_dup = rtw89_fw_elem_dup_if_needed(rtwdev, elm);
+
for (type = 0; bitmap; type++, bitmap >>= 1) {
if (!(bitmap & BIT(0)))
continue;
@@ -1309,10 +1352,10 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
else
break;
- elm_info->txpwr_trk->delta[type] = &elm->u.txpwr_trk.contents[offset];
+ elm_info->txpwr_trk->delta[type] = &elm_dup->u.txpwr_trk.contents[offset];
offset += subband;
- if (offset * DELTA_SWINGIDX_SIZE > le32_to_cpu(elm->size))
+ if (offset * DELTA_SWINGIDX_SIZE > le32_to_cpu(elm_dup->size))
goto err;
}
@@ -1347,7 +1390,7 @@ int rtw89_build_rfk_log_fmt_from_elm(struct rtw89_dev *rtwdev,
if (rfk_id >= RTW89_PHY_C2H_RFK_LOG_FUNC_NUM)
return 1;
- elm_info->rfk_log_fmt->elm[rfk_id] = elm;
+ elm_info->rfk_log_fmt->elm[rfk_id] = rtw89_fw_elem_dup_if_needed(rtwdev, elm);
return 0;
}
@@ -1454,7 +1497,7 @@ int rtw89_build_afe_pwr_seq_from_elm(struct rtw89_dev *rtwdev,
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
- elm_info->afe = elm;
+ elm_info->afe = rtw89_fw_elem_dup_if_needed(rtwdev, elm);
return 0;
}
@@ -1466,7 +1509,7 @@ int rtw89_recognize_diag_mac_from_elm(struct rtw89_dev *rtwdev,
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
- elm_info->diag_mac = elm;
+ elm_info->diag_mac = rtw89_fw_elem_dup_if_needed(rtwdev, elm);
return 0;
}
@@ -1492,7 +1535,7 @@ int rtw89_build_tx_comp_from_elm(struct rtw89_dev *rtwdev,
else if (elm_info->tx_comp)
return 1; /* ignore if an element is existing */
- elm_info->tx_comp = elm;
+ elm_info->tx_comp = rtw89_fw_elem_dup_if_needed(rtwdev, elm);
return 0;
}
@@ -2106,13 +2149,12 @@ static int rtw89_load_firmware_req(struct rtw89_dev *rtwdev,
struct rtw89_fw_req_info *req,
const char *fw_name, bool nowarn)
{
- int ret;
+ int ret = 0;
if (req->firmware) {
rtw89_debug(rtwdev, RTW89_DBG_FW,
"full firmware has been early requested\n");
- complete_all(&req->completion);
- return 0;
+ goto out;
}
if (nowarn)
@@ -2120,6 +2162,8 @@ static int rtw89_load_firmware_req(struct rtw89_dev *rtwdev,
else
ret = request_firmware(&req->firmware, fw_name, rtwdev->dev);
+out:
+ req->free_after_probe = req->firmware && req->firmware->size > 0x200000;
complete_all(&req->completion);
return ret;
--
2.25.1
next prev parent reply other threads:[~2026-09-23 5:45 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 ` Ping-Ke Shih [this message]
2026-09-30 1:56 ` [PATCH rtw-next 1/6] wifi: rtw89: fw: duplicate recognized firmware elements 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 ` [PATCH rtw-next 3/6] wifi: rtw89: fw: duplicate firmware suit data by vmalloc to reduce memory fragment Ping-Ke Shih
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-2-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox