From patchwork Mon Mar 20 13:06:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ping-Ke Shih X-Patchwork-Id: 665522 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8602AC7618A for ; Mon, 20 Mar 2023 13:07:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230035AbjCTNH3 (ORCPT ); Mon, 20 Mar 2023 09:07:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229901AbjCTNH1 (ORCPT ); Mon, 20 Mar 2023 09:07:27 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 576B71B561 for ; Mon, 20 Mar 2023 06:07:26 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 32KD74l44025612, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36505.realtek.com.tw[172.21.6.25]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 32KD74l44025612 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Mon, 20 Mar 2023 21:07:04 +0800 Received: from RTEXMBS04.realtek.com.tw (172.21.6.97) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.32; Mon, 20 Mar 2023 21:07:17 +0800 Received: from localhost (172.16.16.31) by RTEXMBS04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Mon, 20 Mar 2023 21:07:17 +0800 From: Ping-Ke Shih To: CC: , Subject: [PATCH 1/3] wifi: rtw89: fw: use generic flow to set/check features Date: Mon, 20 Mar 2023 21:06:04 +0800 Message-ID: <20230320130606.20777-2-pkshih@realtek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230320130606.20777-1-pkshih@realtek.com> References: <20230320130606.20777-1-pkshih@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.16.16.31] X-ClientProxiedBy: RTEXMBS02.realtek.com.tw (172.21.6.95) To RTEXMBS04.realtek.com.tw (172.21.6.97) X-KSE-ServerInfo: RTEXMBS04.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-ServerInfo: RTEXH36505.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Zong-Zhe Yang In early feature bitmap obtained from rtw89_early_fw_feature_recognize(), the bits needed to check get increased. It's more friendly to work with RTW89_CHK_FW_FEATURE(). So, we concentrate the flow of iterating FW feature configures and calling RTW89_SET_FW_FEATURE() for various uses. And then, we adjust rtw89_early_fw_feature_recognize() for RTW89_CHK_FW_FEATURE(). Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 8 ++--- drivers/net/wireless/realtek/rtw89/fw.c | 41 +++++++++++------------ drivers/net/wireless/realtek/rtw89/fw.h | 2 +- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index bed1d9f045a4d..0c722c52c9fce 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3756,23 +3756,23 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, u32 bus_data_size, const struct rtw89_chip_info *chip) { + struct rtw89_fw_info early_fw = {}; const struct firmware *firmware; struct ieee80211_hw *hw; struct rtw89_dev *rtwdev; struct ieee80211_ops *ops; u32 driver_data_size; - u32 early_feat_map = 0; bool no_chanctx; - firmware = rtw89_early_fw_feature_recognize(device, chip, &early_feat_map); + firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw); ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL); if (!ops) goto err; no_chanctx = chip->support_chanctx_num == 0 || - !(early_feat_map & BIT(RTW89_FW_FEATURE_SCAN_OFFLOAD)) || - !(early_feat_map & BIT(RTW89_FW_FEATURE_BEACON_FILTER)); + !RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &early_fw) || + !RTW89_CHK_FW_FEATURE(BEACON_FILTER, &early_fw); if (no_chanctx) { ops->add_chanctx = NULL; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d3348f9bcc2a7..d9bd4339a59e5 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -269,38 +269,45 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER), }; +static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, + const struct rtw89_chip_info *chip, + u32 ver_code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) { + const struct __fw_feat_cfg *ent = &fw_feat_tbl[i]; + + if (chip->chip_id != ent->chip_id) + continue; + + if (ent->cond(ver_code, ent->ver_code)) + RTW89_SET_FW_FEATURE(ent->feature, fw); + } +} + static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - const struct __fw_feat_cfg *ent; const struct rtw89_fw_suit *fw_suit; u32 suit_ver_code; - int i; fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); - for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) { - ent = &fw_feat_tbl[i]; - if (chip->chip_id != ent->chip_id) - continue; - - if (ent->cond(suit_ver_code, ent->ver_code)) - RTW89_SET_FW_FEATURE(ent->feature, &rtwdev->fw); - } + rtw89_fw_iterate_feature_cfg(&rtwdev->fw, chip, suit_ver_code); } const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, - u32 *early_feat_map) + struct rtw89_fw_info *early_fw) { union rtw89_compat_fw_hdr buf = {}; const struct firmware *firmware; bool full_req = false; u32 ver_code; int ret; - int i; /* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will * be denied (-EPERM). Then, we don't get right firmware things as @@ -329,15 +336,7 @@ rtw89_early_fw_feature_recognize(struct device *device, if (!ver_code) goto out; - for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) { - const struct __fw_feat_cfg *ent = &fw_feat_tbl[i]; - - if (chip->chip_id != ent->chip_id) - continue; - - if (ent->cond(ver_code, ent->ver_code)) - *early_feat_map |= BIT(ent->feature); - } + rtw89_fw_iterate_feature_cfg(early_fw, chip, ver_code); out: if (full_req) diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 4d8d961f7b236..c5c7279ccc23a 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3658,7 +3658,7 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev); const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, - u32 *early_feat_map); + struct rtw89_fw_info *early_fw); int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type); int rtw89_load_firmware(struct rtw89_dev *rtwdev); void rtw89_unload_firmware(struct rtw89_dev *rtwdev); From patchwork Mon Mar 20 13:06:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ping-Ke Shih X-Patchwork-Id: 665521 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 39ADAC76195 for ; Mon, 20 Mar 2023 13:07:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231429AbjCTNHs (ORCPT ); Mon, 20 Mar 2023 09:07:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57184 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229901AbjCTNHq (ORCPT ); Mon, 20 Mar 2023 09:07:46 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E855CE3BB for ; Mon, 20 Mar 2023 06:07:44 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 32KD7NbsC025639, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36506.realtek.com.tw[172.21.6.27]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 32KD7NbsC025639 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Mon, 20 Mar 2023 21:07:23 +0800 Received: from RTEXMBS04.realtek.com.tw (172.21.6.97) by RTEXH36506.realtek.com.tw (172.21.6.27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.17; Mon, 20 Mar 2023 21:07:19 +0800 Received: from localhost (172.16.16.31) by RTEXMBS04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Mon, 20 Mar 2023 21:07:18 +0800 From: Ping-Ke Shih To: CC: , Subject: [PATCH 2/3] wifi: rtw89: use schedule_work to request firmware Date: Mon, 20 Mar 2023 21:06:05 +0800 Message-ID: <20230320130606.20777-3-pkshih@realtek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230320130606.20777-1-pkshih@realtek.com> References: <20230320130606.20777-1-pkshih@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.16.16.31] X-ClientProxiedBy: RTEXMBS02.realtek.com.tw (172.21.6.95) To RTEXMBS04.realtek.com.tw (172.21.6.97) X-KSE-ServerInfo: RTEXMBS04.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Since we are going to load more than one firmware and some are not presented or optional, using asynchronous API request_firmware_nowait() will become complicated. Also, we want to use firmware_request_nowarn() to avoid warning messages when loading optional files. So, use schedule_work to be simpler. To abstract loading a firmware or file, define a struct rtw89_fw_req_info containing a struct firmware and a completion to ensure this firmware is loaded completely. Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 17 +++--- drivers/net/wireless/realtek/rtw89/core.h | 8 ++- drivers/net/wireless/realtek/rtw89/fw.c | 68 ++++++++++------------- drivers/net/wireless/realtek/rtw89/fw.h | 2 +- 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 0c722c52c9fce..33460954ebf13 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3427,7 +3427,6 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) int rtw89_core_init(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; - int ret; u8 band; INIT_LIST_HEAD(&rtwdev->ba_list); @@ -3464,6 +3463,8 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work); INIT_WORK(&rtwdev->ips_work, rtw89_ips_work); + INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work); + skb_queue_head_init(&rtwdev->c2h_queue); rtw89_core_ppdu_sts_init(rtwdev); rtw89_traffic_stats_init(rtwdev, &rtwdev->stats); @@ -3475,12 +3476,10 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_WORK(&btc->dhcp_notify_work, rtw89_btc_ntfy_dhcp_packet_work); INIT_WORK(&btc->icmp_notify_work, rtw89_btc_ntfy_icmp_packet_work); - ret = rtw89_load_firmware(rtwdev); - if (ret) { - rtw89_warn(rtwdev, "no firmware loaded\n"); - destroy_workqueue(rtwdev->txq_wq); - return ret; - } + init_completion(&rtwdev->fw.req.completion); + + schedule_work(&rtwdev->load_firmware_work); + rtw89_ser_init(rtwdev); rtw89_entity_init(rtwdev); @@ -3794,7 +3793,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, rtwdev->dev = device; rtwdev->ops = ops; rtwdev->chip = chip; - rtwdev->fw.firmware = firmware; + rtwdev->fw.req.firmware = firmware; rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n", no_chanctx ? "without" : "with"); @@ -3811,7 +3810,7 @@ EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw); void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev) { kfree(rtwdev->ops); - release_firmware(rtwdev->fw.firmware); + release_firmware(rtwdev->fw.req.firmware); ieee80211_free_hw(rtwdev->hw); } EXPORT_SYMBOL(rtw89_free_ieee80211_hw); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 7d80d0fc50c38..5fd189dde17e7 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3274,10 +3274,13 @@ struct rtw89_fw_suit { GET_FW_HDR_SUBVERSION(fw_hdr), \ GET_FW_HDR_SUBINDEX(fw_hdr)) -struct rtw89_fw_info { +struct rtw89_fw_req_info { const struct firmware *firmware; - struct rtw89_dev *rtwdev; struct completion completion; +}; + +struct rtw89_fw_info { + struct rtw89_fw_req_info req; u8 h2c_seq; u8 rec_seq; u8 h2c_counter; @@ -3994,6 +3997,7 @@ struct rtw89_dev { struct sk_buff_head c2h_queue; struct work_struct c2h_work; struct work_struct ips_work; + struct work_struct load_firmware_work; struct list_head early_h2c_list; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d9bd4339a59e5..9edc421e176cf 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -155,8 +155,9 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, struct rtw89_fw_suit *fw_suit, bool nowarn) { struct rtw89_fw_info *fw_info = &rtwdev->fw; - const u8 *mfw = fw_info->firmware->data; - u32 mfw_len = fw_info->firmware->size; + const struct firmware *firmware = fw_info->req.firmware; + const u8 *mfw = firmware->data; + u32 mfw_len = firmware->size; const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw; const struct rtw89_mfw_info *mfw_info; int i; @@ -631,67 +632,58 @@ int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev) { struct rtw89_fw_info *fw = &rtwdev->fw; - wait_for_completion(&fw->completion); - if (!fw->firmware) + wait_for_completion(&fw->req.completion); + if (!fw->req.firmware) return -EINVAL; return 0; } -static void rtw89_load_firmware_cb(const struct firmware *firmware, void *context) +static int rtw89_load_firmware_req(struct rtw89_dev *rtwdev, + struct rtw89_fw_req_info *req, + const char *fw_name, bool nowarn) { - struct rtw89_fw_info *fw = context; - struct rtw89_dev *rtwdev = fw->rtwdev; - - if (!firmware || !firmware->data) { - rtw89_err(rtwdev, "failed to request firmware\n"); - complete_all(&fw->completion); - return; - } - - fw->firmware = firmware; - complete_all(&fw->completion); -} - -int rtw89_load_firmware(struct rtw89_dev *rtwdev) -{ - struct rtw89_fw_info *fw = &rtwdev->fw; - const char *fw_name = rtwdev->chip->fw_name; int ret; - fw->rtwdev = rtwdev; - init_completion(&fw->completion); - - if (fw->firmware) { + if (req->firmware) { rtw89_debug(rtwdev, RTW89_DBG_FW, "full firmware has been early requested\n"); - complete_all(&fw->completion); + complete_all(&req->completion); return 0; } - ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, - GFP_KERNEL, fw, rtw89_load_firmware_cb); - if (ret) { - rtw89_err(rtwdev, "failed to async firmware request\n"); - return ret; - } + if (nowarn) + ret = firmware_request_nowarn(&req->firmware, fw_name, rtwdev->dev); + else + ret = request_firmware(&req->firmware, fw_name, rtwdev->dev); - return 0; + complete_all(&req->completion); + + return ret; +} + +void rtw89_load_firmware_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev = + container_of(work, struct rtw89_dev, load_firmware_work); + const char *fw_name = rtwdev->chip->fw_name; + + rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false); } void rtw89_unload_firmware(struct rtw89_dev *rtwdev) { struct rtw89_fw_info *fw = &rtwdev->fw; - rtw89_wait_firmware_completion(rtwdev); + cancel_work_sync(&rtwdev->load_firmware_work); - if (fw->firmware) { - release_firmware(fw->firmware); + if (fw->req.firmware) { + release_firmware(fw->req.firmware); /* assign NULL back in case rtw89_free_ieee80211_hw() * try to release the same one again. */ - fw->firmware = NULL; + fw->req.firmware = NULL; } } diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index c5c7279ccc23a..661e08ae7bc8c 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3660,7 +3660,7 @@ rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, struct rtw89_fw_info *early_fw); int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type); -int rtw89_load_firmware(struct rtw89_dev *rtwdev); +void rtw89_load_firmware_work(struct work_struct *work); void rtw89_unload_firmware(struct rtw89_dev *rtwdev); int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev); void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, From patchwork Mon Mar 20 13:06:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ping-Ke Shih X-Patchwork-Id: 665855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8173C7618A for ; Mon, 20 Mar 2023 13:08:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231432AbjCTNIb (ORCPT ); Mon, 20 Mar 2023 09:08:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231455AbjCTNI0 (ORCPT ); Mon, 20 Mar 2023 09:08:26 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F2F11CAF0 for ; Mon, 20 Mar 2023 06:08:24 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 32KD84voC025931, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36505.realtek.com.tw[172.21.6.25]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 32KD84voC025931 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Mon, 20 Mar 2023 21:08:04 +0800 Received: from RTEXMBS04.realtek.com.tw (172.21.6.97) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.32; Mon, 20 Mar 2023 21:07:20 +0800 Received: from localhost (172.16.16.31) by RTEXMBS04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Mon, 20 Mar 2023 21:07:19 +0800 From: Ping-Ke Shih To: CC: , Subject: [PATCH 3/3] wifi: rtw89: add firmware format version to backward compatible with older drivers Date: Mon, 20 Mar 2023 21:06:06 +0800 Message-ID: <20230320130606.20777-4-pkshih@realtek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230320130606.20777-1-pkshih@realtek.com> References: <20230320130606.20777-1-pkshih@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.16.16.31] X-ClientProxiedBy: RTEXMBS02.realtek.com.tw (172.21.6.95) To RTEXMBS04.realtek.com.tw (172.21.6.97) X-KSE-ServerInfo: RTEXMBS04.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-ServerInfo: RTEXH36505.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org In the discuss threads [1] [2], new firmware format break user space because older drivers can't recognize new firmware format. To avoid this, the new format will be named rtw89/rtw8852b_fw-1.bin and only new driver try to load it. Old drivers only load original and understandable firmware rtw89/rtw8852b_fw.bin. More, new driver will be still backward compatible with old firmware, so original firmware can be used by new driver. If there is newer firmware format is introduced, rtw89/rtw8852b_fw-2.bin will be given. The same rules will be applied like above. So, we will have firmware like below in linux-firmware in the future. rtw89/rtw8852b_fw-2.bin rtw89/rtw8852b_fw-1.bin rtw89/rtw8852b_fw.bin After this patch, MODULE_FIRMWARE() of 8852A/B/C become rtw89/rtw8852a_fw.bin rtw89/rtw8852b_fw-1.bin rtw89/rtw8852c_fw.bin [1] https://lore.kernel.org/linux-wireless/df1ce994-3368-a57e-7078-8bdcccf4a1fd@gmail.com/T/#m24cb43be31a762d0ea70bf07f27ae96c59f6931b [2] https://bugzilla.kernel.org/show_bug.cgi?id=217207 Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 4 ++- drivers/net/wireless/realtek/rtw89/core.h | 4 ++- drivers/net/wireless/realtek/rtw89/fw.c | 33 ++++++++++++++----- drivers/net/wireless/realtek/rtw89/fw.h | 12 ++++++- drivers/net/wireless/realtek/rtw89/rtw8852a.c | 10 ++++-- drivers/net/wireless/realtek/rtw89/rtw8852b.c | 10 ++++-- drivers/net/wireless/realtek/rtw89/rtw8852c.c | 10 ++++-- 7 files changed, 66 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 33460954ebf13..592e26b627d21 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3761,9 +3761,10 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, struct rtw89_dev *rtwdev; struct ieee80211_ops *ops; u32 driver_data_size; + int fw_format = -1; bool no_chanctx; - firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw); + firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw, &fw_format); ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL); if (!ops) @@ -3794,6 +3795,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, rtwdev->ops = ops; rtwdev->chip = chip; rtwdev->fw.req.firmware = firmware; + rtwdev->fw.fw_format = fw_format; rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n", no_chanctx ? "without" : "with"); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 5fd189dde17e7..e483381f8c1e9 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3058,7 +3058,8 @@ struct rtw89_phy_ul_tb_info { struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; const struct rtw89_chip_ops *ops; - const char *fw_name; + const char *fw_basename; + u8 fw_format_max; bool try_ce_fw; u32 fifo_size; u32 dle_scc_rsvd_size; @@ -3281,6 +3282,7 @@ struct rtw89_fw_req_info { struct rtw89_fw_info { struct rtw89_fw_req_info req; + int fw_format; u8 h2c_seq; u8 rec_seq; u8 h2c_counter; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 9edc421e176cf..239dfb33eed5f 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -302,11 +302,14 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev) const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, - struct rtw89_fw_info *early_fw) + struct rtw89_fw_info *early_fw, + int *used_fw_format) { union rtw89_compat_fw_hdr buf = {}; const struct firmware *firmware; bool full_req = false; + char fw_name[64]; + int fw_format; u32 ver_code; int ret; @@ -317,12 +320,22 @@ rtw89_early_fw_feature_recognize(struct device *device, if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE)) full_req = true; - if (full_req) - ret = request_firmware(&firmware, chip->fw_name, device); - else - ret = request_partial_firmware_into_buf(&firmware, chip->fw_name, - device, &buf, sizeof(buf), - 0); + for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) { + rtw89_fw_get_filename(fw_name, sizeof(fw_name), + chip->fw_basename, fw_format); + + if (full_req) + ret = request_firmware(&firmware, fw_name, device); + else + ret = request_partial_firmware_into_buf(&firmware, fw_name, + device, &buf, sizeof(buf), + 0); + if (!ret) { + dev_info(device, "loaded firmware %s\n", fw_name); + *used_fw_format = fw_format; + break; + } + } if (ret) { dev_err(device, "failed to early request firmware: %d\n", ret); @@ -666,7 +679,11 @@ void rtw89_load_firmware_work(struct work_struct *work) { struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, load_firmware_work); - const char *fw_name = rtwdev->chip->fw_name; + const struct rtw89_chip_info *chip = rtwdev->chip; + char fw_name[64]; + + rtw89_fw_get_filename(fw_name, sizeof(fw_name), + chip->fw_basename, rtwdev->fw.fw_format); rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false); } diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 661e08ae7bc8c..a2ff173e55446 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -3515,6 +3515,15 @@ static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf) return RTW89_FW_HDR_VER_CODE(&compat->fw_hdr); } +static inline void rtw89_fw_get_filename(char *buf, size_t size, + const char *fw_basename, int fw_format) +{ + if (fw_format <= 0) + snprintf(buf, size, "%s.bin", fw_basename); + else + snprintf(buf, size, "%s-%d.bin", fw_basename, fw_format); +} + #define RTW89_H2C_RF_PAGE_SIZE 500 #define RTW89_H2C_RF_PAGE_NUM 3 struct rtw89_fw_h2c_rf_reg_info { @@ -3658,7 +3667,8 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev); const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, - struct rtw89_fw_info *early_fw); + struct rtw89_fw_info *early_fw, + int *used_fw_format); int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type); void rtw89_load_firmware_work(struct work_struct *work); void rtw89_unload_firmware(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 5f7e948507f8a..018fad3bc462c 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -12,6 +12,11 @@ #include "rtw8852a_table.h" #include "txrx.h" +#define RTW8852A_FW_FORMAT_MAX 0 +#define RTW8852A_FW_BASENAME "rtw89/rtw8852a_fw" +#define RTW8852A_MODULE_FIRMWARE \ + RTW8852A_FW_BASENAME ".bin" + static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = { {128, 1896, grp_0}, /* ACH 0 */ {128, 1896, grp_0}, /* ACH 1 */ @@ -2054,7 +2059,8 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { const struct rtw89_chip_info rtw8852a_chip_info = { .chip_id = RTL8852A, .ops = &rtw8852a_chip_ops, - .fw_name = "rtw89/rtw8852a_fw.bin", + .fw_basename = RTW8852A_FW_BASENAME, + .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, .fifo_size = 458752, .dle_scc_rsvd_size = 0, @@ -2150,7 +2156,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { }; EXPORT_SYMBOL(rtw8852a_chip_info); -MODULE_FIRMWARE("rtw89/rtw8852a_fw.bin"); +MODULE_FIRMWARE(RTW8852A_MODULE_FIRMWARE); MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852A driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 895d216cfa27b..639c65025dd6f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -12,6 +12,11 @@ #include "rtw8852b_table.h" #include "txrx.h" +#define RTW8852B_FW_FORMAT_MAX 1 +#define RTW8852B_FW_BASENAME "rtw89/rtw8852b_fw" +#define RTW8852B_MODULE_FIRMWARE \ + RTW8852B_FW_BASENAME "-" __stringify(RTW8852B_FW_FORMAT_MAX) ".bin" + static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = { {5, 343, grp_0}, /* ACH 0 */ {5, 343, grp_0}, /* ACH 1 */ @@ -2431,7 +2436,8 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { const struct rtw89_chip_info rtw8852b_chip_info = { .chip_id = RTL8852B, .ops = &rtw8852b_chip_ops, - .fw_name = "rtw89/rtw8852b_fw.bin", + .fw_basename = RTW8852B_FW_BASENAME, + .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, .fifo_size = 196608, .dle_scc_rsvd_size = 98304, @@ -2526,7 +2532,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { }; EXPORT_SYMBOL(rtw8852b_chip_info); -MODULE_FIRMWARE("rtw89/rtw8852b_fw.bin"); +MODULE_FIRMWARE(RTW8852B_MODULE_FIRMWARE); MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852B driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index e8e577a1b9fc4..63af0c89bd80f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -13,6 +13,11 @@ #include "rtw8852c_table.h" #include "util.h" +#define RTW8852C_FW_FORMAT_MAX 0 +#define RTW8852C_FW_BASENAME "rtw89/rtw8852c_fw" +#define RTW8852C_MODULE_FIRMWARE \ + RTW8852C_FW_BASENAME ".bin" + static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_pcie[] = { {13, 1614, grp_0}, /* ACH 0 */ {13, 1614, grp_0}, /* ACH 1 */ @@ -2786,7 +2791,8 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, .ops = &rtw8852c_chip_ops, - .fw_name = "rtw89/rtw8852c_fw.bin", + .fw_basename = RTW8852C_FW_BASENAME, + .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, .fifo_size = 458752, .dle_scc_rsvd_size = 0, @@ -2886,7 +2892,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { }; EXPORT_SYMBOL(rtw8852c_chip_info); -MODULE_FIRMWARE("rtw89/rtw8852c_fw.bin"); +MODULE_FIRMWARE(RTW8852C_MODULE_FIRMWARE); MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852C driver"); MODULE_LICENSE("Dual BSD/GPL");